Что не так, это следующий метод?Использование ленивых оценочных функций в varargs
def someMethod(funcs: => Option[String]*) = {
...
}
Что не так, это следующий метод?Использование ленивых оценочных функций в varargs
def someMethod(funcs: => Option[String]*) = {
...
}
Это на самом деле «работает» под 2.7.7, если добавить скобки:
scala> def someMethod(funcs: => (Option[String]*)) = funcs
someMethod: (=> Option[String]*)Option[String]*
кроме него фактически не работает во время выполнения:
scala> someMethod(Some("Fish"),None)
scala.MatchError: Some(Fish)
at scala.runtime.ScalaRunTime$.boxArray(ScalaRunTime.scala:136)
at .someMethod(<console>:4)
at .<init>(<console>:6)
at .<clinit>(<console>) ...
В 2.8 он отказывается, чтобы указать X * в качестве выхода любой функции или параметра имени, хотя вы можете указать его как вход (это r21230, пост-бета 1):
scala> var f: (Option[Int]*) => Int = _
f: (Option[Int]*) => Int = null
scala> var f: (Option[Int]*) => (Option[Int]*) = _
<console>:1: error: no * parameter type allowed here
var f: (Option[Int]*) => (Option[Int]*) = _
Но если вы пытаетесь конвертировать из метода, он работает:
scala> def m(oi: Option[Int]*) = oi
m: (oi: Option[Int]*)Option[Int]*
scala> var f = (m _)
f: (Option[Int]*) => Option[Int]* = <function1>
scala> f(Some(1),None)
res0: Option[Int]* = WrappedArray(Some(1), None)
Так что это не совсем последователен.
В любом случае, возможно, вы можете добиться того, что вы хотите, передавая массив, а затем посылает этот массив к чему-то, что принимает повторяющиеся аргументы:
scala> def aMethod(os: Option[String]*) { os.foreach(println) }
aMethod: (os: Option[String]*)Unit
scala> def someMethod(funcs: => Array[Option[String]]) { aMethod(funcs:_*) }
someMethod: (funcs: => Array[Option[String]])Unit
scala> someMethod(Array(Some("Hello"),Some("there"),None))
Some(Hello)
Some(there)
None
Если вы действительно хотите (легко) передавать кучу лениво оцениваемых аргументов, тогда вам нужна небольшая инфраструктура, которая, насколько мне известно, не очень хорошо существует в библиотеке (это код для 2.8, рассматривайте ее как вдохновитель для аналогичной стратегии в 2.7):
class Lazy[+T](t:() => T, lt: Lazy[T]) {
val params: List[() => T] = (if (lt eq null) Nil else t :: lt.params)
def ~[S >: T](s: => S) = new Lazy[S](s _,this)
}
object Lz extends Lazy[Nothing](null,null) {
implicit def lazy2params[T : Manifest](lz: Lazy[T]) = lz.params.reverse.toArray
}
Теперь вы можете легко создать кучу параметров которые оцениваются лениво:
scala> import Lz._ // To get implicit def
import Lz._
scala> def lazyAdder(ff: Array[()=>Int]) = {
| println("I'm adding now!");
| (0 /: ff){(n,f) => n+f()}
| }
lazyAdder: (ff: Array[() => Int])Int
scala> def yelp = { println("You evaluated me!"); 5 }
yelp: Int
scala> val a = 3
a: Int = 3
scala> var b = 7
b: Int = 7
scala> lazyAdder(Lz ~ yelp ~ (a+b))
I'm adding now!
You evaluated me!
res0: Int = 15
scala> val plist = Lz ~ yelp ~ (a+b)
plist: Lazy[Int] = [email protected]
scala> b = 1
b: Int = 1
scala> lazyAdder(plist)
I'm adding now!
You evaluated me!
res1: Int = 9
Очевидно, что повторяющиеся аргументы недоступны для параметров по имени.
Но, просто для ударов, попробуйте следующее: 'def f (oi: Option [Int] *) = oi' в REPL. Интересно, а? –
@Rex_Kerr: Наверное. На что интересное вы имеете дело? –
Вы можете вернуть Option [Int] * из метода, и вы можете использовать (f_), чтобы сделать его функцией. Но попробуйте найти синтаксис, который позволяет вам представлять тип. Поэтому мне непонятно, могут ли повторяющиеся аргументы недоступны для параметров по имени, или синтаксис не позволяет вам выражать нужный тип (или и то, и другое). –
Название официального параметра 'funcs', является очень подозрительным. Параметры имени-имени, реализованные с помощью thunk, не являются явно функциями. –
И это не то, что обычно называют лениво оцененными аргументами. I.e., если вы используете значение несколько раз, выражение, заданное как фактический параметр, оценивается несколько раз. Это имеет последствия для производительности, и если это выражение имеет побочные эффекты, они также будут размножаться. –
Это может быть решение: http://stackoverflow.com/a/34373967/2825964 –