Преобразование в кортеж с параметром по имени

Я хотел бы создать функцию со следующей подписью:

def myFunction[T](functionWithName: (String, => T)): T 

так что я могу назвать это, например, так: val x = myFunction("abc" -> 4 * 3), Однако Tuple не принимает параметр by-name, поэтому подпись выше недействительна.

Вдохновленный этим ответом, я попробовал следующее неявное преобразование:

implicit class ByName[T](getValue: => T) extends Proxy {
  def apply(): T = getValue
  def self = apply()
}

def myFunction[T](functionWithName: (String, ByName[T])): T = {
  // do something
  functionWithName._2()
}

Однако неявное не работает в этом случае (в отличие от связанного ответа).

  • Почему неявное преобразование в ByName не работает?
  • Как мне добиться желаемого эффекта от звонка myFunction("abc" -> 4 * 3) где 4 * 3 передается по имени?

2 ответа

Решение

У меня есть два предложения для реализации этого:

  • Сделать целый кортеж по имени: functionWithName: => (String, T)

  • Создайте свой собственный класс:

    class MyTuple[A, B](a: A, b: => B) {
      def _1: A = a
      def _2: B = b
      def toTuple = a -> b // optional
    }
    

и где-то есть собственный неявный метод, например -> за Tuple2 (увидеть ArrowAssoc в Predef):

  implicit final class ArrAssoc[A](private val self: A) extends AnyVal {
    @inline def -->[B](y: => B): MyTuple[A, B] = {
      new MyTuple(self, y)
    }
  }

Тогда вы могли бы сказать это:

  val t = 1 --> { println("blah"); 5 }
  //t._2
  //t.toTuple

b параметр не должен оцениваться, пока вы не вызовете t._2Или даже сделать toTuple неявное преобразование, поэтому, когда Tuple2 Предполагается, что вы можете передать MyTuple...

Вы можете изменить параметр call-by-name на thunk.

def myFunction[T](functionWithName: (String,() => T)): T = functionWithName._2()

myFunction(("abc", () => 4 * 3)) // 12

или заставить его работать с implicitвам просто нужно явно указать тип myFunction:

myFunction[Int]("abc" -> 4 * 3) // 12
Другие вопросы по тегам