Преобразование в кортеж с параметром по имени
Я хотел бы создать функцию со следующей подписью:
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