2009-12-17 24 views
5

Asumamos esta función:¿Es posible curry al revés en Scala?

def autoClosing(f: {def close();})(t: =>Unit) = { 
    t 
    f.close() 
} 

y este fragmento:

val a = autoClosing(new X)(_) 
a { 
println("before close") 
} 

es posible ganarse la primera parte? Algo así como:

val a = autoClosing(_) { println("before close") } 

para que yo pudiera enviar los objetos sobre los que se deben realizar cerca, y tienen el mismo bloque que ejercen sobre ellos?

Respuesta

10

Sí, el fragmento que ha dado funciona, siempre que indique el tipo de carácter de marcador de posición.

Por lo tanto, el código que busca es:

val a = autoClosing(_: {def close();}) { println("before close") } 

que compila y funciona como se esperaba :).

Un par de notas:

  • Usted puede hacer su vida más fácil si se define un alias de tipo para un tipo AnyRef tener un close método, algo así como type Closeable = AnyRef {def close()}, o una interfaz adecuada.
  • El fragmento de código autoClosing(_: Closeable){ ... } es en realidad equivalente a la siguiente función anónima expandida: c: Closeable => autoClosing(c){ ... }. El carácter comodín es solo una abreviatura de una función parcialmente aplicada. Necesita dar el tipo de _ ya que el tipo inferer desafortunadamente no puede inferir el tipo en este caso.

creo que sirve,

- Flaviu Cipcigan

+0

Tipo de detallado. Mersi :) – Geo

+0

De nada. Agregué un par de notas para expandir mi respuesta :). Desafortunadamente, el tipo inferer no puede inferir el tipo del comodín aquí. –

6

Alternativamente se puede voltear los parámetros:

def flip[A1, A2, B](f: A1 => A2 => B): A2 => A1 => B = x1 => x2 => f(x2)(x1) 

En su caso:

val a = flip(autoClosing){ println("before close") } 

Editar: He añadido un sujetador ces para ayudar a que el analizador humana:

def flip[A1, A2, B](f: (A1 => (A2 => B))): (A2 => (A1 => B)) = { 
    x1 => (x2 => f(x2)(x1)) 
} 

tirón convierte una función (A1 => (A2 => B)) a (A2 => (A1 => B)).

scala> def x(x1 : Int)(x2 : Long) = 1.0 * x1/x2 
x: (Int)(Long)Double 

scala> val f = flip(x) 
f: (Long) => (Int) => Double = <function> 

scala> val g = f(1) 
g: (Int) => Double = <function> 

scala> val h = g(2) 
h: Double = 2.0 

scala> x(1)(2) 
res0: Double = 0.5 
+0

¿Puedes explicar un poco ese monstruo? :) – Geo

+0

Agregué algunas llaves y un código de muestra para ver la aplicación parcial en acción. Espero que esto ayude. –

3

Estoy feliz de ver tantas personas respondiendo preguntas de Scala hoy en día. Sin embargo, hace que sea más difícil para mí encontrar algo. Aquí hay una alternativa al Flaviu 's solution.

val a: {def close();} => Unit = autoClosing(_) { println("before close") } 

Por supuesto, la solución adecuada es definir autoclosing de forma compatible con la forma en que va a usarlo.

+0

Estoy feliz por eso también :). Voy a renunciar a Ruby por Scala ... tiene todo lo que quería en un idioma. – Geo

Cuestiones relacionadas