2011-06-13 17 views
22

Perdóneme si esto ya se ha pedido en otro lugar. Tengo una pregunta de sintaxis de Scala que involucra valores-función y parámetros implícitos.Scala Literales funcionales con Implicits

Me siento cómodo al usar implícitos con la característica de curvar de Scala. Por ejemplo, si tuviera una función de suma y quería hacer el segundo argumento implícito:

scala> def sum(a: Int)(implicit b: Int) = a + b 
sum: (a: Int)(implicit b: Int)Int 

¿Hay una manera de hacer esto utilizando la sintaxis de la función valor? Haciendo caso omiso de lo implícito por un momento, yo normalmente escribo valores de función al curry así:

scala> val sum2 = (a: Int) => (b: Int) => a + b 
sum: (Int) => (Int) => Int = <function1> 

Sin embargo, la firma de la función en el segundo enfoque es muy diferente (la currificación se expresa de forma explícita). Simplemente añadiendo la palabra clave implícita a B no tiene mucho sentido y el compilador se queja así:

scala> val sum2 = (a: Int) => (implicit b: Int) => a + b 
<console>:1: error: '=>' expected but ')' found. 
     val sum2 = (a: Int) => (implicit b: Int) => a + b 
              ^

Por otra parte, la aplicación de suma desde el primer enfoque para obtener una función de valor hace que los problemas así:

scala> val sumFunction = sum _ 
<console>:14: error: could not find implicit value for parameter b: Int 
     val sumFunction = sum _ 
         ^

Esto me lleva a pensar que las funciones que tienen parámetros implícitos deben haber dicho parámetros determinan cuando se creó la función de valor, no cuando se aplica la función valor más adelante. ¿Es este realmente el caso? ¿Alguna vez puedes usar un parámetro implícito con un valor de función?

¡Gracias por la ayuda!

+0

Por desgracia, no tengo una respuesta para usted, pero tengo una pregunta aclaratoria: en su segundo párrafo se habla de un 'sum' * * función, pero su ejemplo de código correspondiente muestra un' sum' *método*. ¿A cuál te refieres? –

+0

Hola Jörg: entiendo que un método es simplemente una función asociada a una clase u objeto. Todas las funciones anteriores se escribieron en Scala REPL; no se crearon clases u objetos definidos por el usuario. Entonces diría que solo estamos lidiando con funciones aquí. – shj

Respuesta

16
scala> val sum2 = (a: Int) => {implicit b: Int => a + b} 
sum2: (Int) => (Int) => Int = <function1> 

Esto se acaba de hacer b un valor implícito para el alcance del cuerpo de la función, por lo que se puede llamar a los métodos que esperan un Int implícita.

No creo que pueda haber argumentos implícitos para las funciones, ya que entonces no está claro cuál es la función. ¿Es Int => Int o () => Int?

Lo más cerca que he encontrado es:

scala> case class Foo(implicit b: Int) extends (Int => Int) {def apply(a: Int) = a + b} 
defined class Foo 

scala> implicit val b = 3 
b: Int = 3 

scala> Foo() 
res22: Foo = <function1> 

scala> res22(2) 
res23: Int = 5 
9

En este fragmento

scala> val sum2 = (a: Int) => (b: Int) => a + b 
sum: (Int) => (Int) => Int = <function1> 

Tenga en cuenta que el tipo exacto de sum2 es Function1[Int, Function1[Int, Int]]. También podría escribirse como

val sum2 = new Function1[Int, Function1[Int, Int]] { 
    def apply(a: Int) = new Function1[Int, Int] { 
     def apply(b: Int) = a + b 
    } 
} 

Ahora, si usted trata de hacer b implícita, se obtiene lo siguiente:

scala>  val sum2 = new Function1[Int, Function1[Int, Int]] { 
    |   def apply(a: Int) = new Function1[Int, Int] { 
    |    def apply(implicit b: Int) = a + b 
    |   } 
    |  } 
<console>:8: error: object creation impossible, since method apply in trait Function1 of type (v1: Int)Int is not defined 
       def apply(a: Int) = new Function1[Int, Int] { 
            ^

O, dicho de otro modo, las interfaces Function 's no tienen parámetros implícitos, entonces cualquier cosa con un parámetro implícito no es Function.

3

Intente sobrecargar el método de aplicar.

scala> val sum = new Function1[Int, Function1[Int, Int]] { 
     |  def apply(a: Int) = (b: Int) => a + b 
     |  def apply(a: Int)(implicit b: Int) = a + b 
     |} 
sum: java.lang.Object with (Int) => (Int) => Int{def apply(a:Int)(implicit b: Int): Int} = <function1> 

scala> sum(2)(3) 
res0: Int = 5 

scala> implicit val b = 10 
b: Int = 10 

scala> sum(2) 
res1: Int = 12 
Cuestiones relacionadas