¿Qué problema hay con el siguiente método?Uso de las funciones de evaluación diferidas en varargs
def someMethod(funcs: => Option[String]*) = {
...
}
¿Qué problema hay con el siguiente método?Uso de las funciones de evaluación diferidas en varargs
def someMethod(funcs: => Option[String]*) = {
...
}
Que en realidad "trabaja" en 2.7.7 si se agrega parens:
scala> def someMethod(funcs: => (Option[String]*)) = funcs
someMethod: (=> Option[String]*)Option[String]*
excepto que en realidad no trabajar en tiempo de ejecución:
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>) ...
En 2.8 se niega a permitir que se especifiquen X * como salida de cualquier función o parámetro de nombre, aunque puede especificarlo como entrada (esto es r21230, posterior a la versión Beta 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]*) = _
Pero si intenta convertir de un método, funciona:
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)
así que no es del todo coherente.
En cualquier caso, puede posiblemente lograr lo que desea pasando de una matriz y luego enviar esa matriz a algo que toma argumentos repetidos:
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
Si realmente desea pasar (fácilmente) un manojo de argumentos evaluados perezosamente, entonces necesita un poco de infraestructura que, por lo que sé, no existe muy bien en la biblioteca (esto es código para 2.8; véalo como inspiración para una estrategia similar en 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
}
Ahora puedes crear fácilmente un grupo de param eters que se evalúan de forma diferida:
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
Los argumentos evidentemente repetidos no están disponibles para los parámetros de nombre por nombre.
Pero, solo por las patadas, intente esto: 'def f (oi: Option [Int] *) = oi' en REPL. Interesante, ¿eh? –
@Rex_Kerr: supongo. ¿A qué cosa interesante te estás refiriendo? –
Puede devolver la Opción [Int] * desde un método, y puede usar (f _) para que sea una función. Pero intente encontrar la sintaxis que le permita representar el tipo. Por lo tanto, no está claro si los argumentos repetidos no están disponibles para los parámetros de nombre o si la sintaxis no le permite expresar el tipo que desea (o ambos). –
El nombre del parámetro formal, 'funcs', es muy sospechoso. Los parámetros By-name, si bien se implementan con un thunk, no son funciones manifiestamente. –
Tampoco son lo que comúnmente se conoce como argumentos evaluados perezosamente. Es decir, si usa el valor varias veces, la expresión dada como el parámetro real se evalúa varias veces. Eso tiene consecuencias en el rendimiento y si esa expresión tiene efectos secundarios, también se multiplicarán. –
Esa puede ser una solución: http://stackoverflow.com/a/34373967/2825964 –