superior orden funciones function scala currying

function - orden - Dos formas de definir funciones en Scala. ¿Cuál es la diferencia?



funciones de orden superior scala (3)

Aquí hay una pequeña sesión de Scala que define y prueba algunas funciones:

scala> def test1(str: String) = str + str; test1: (str: String)java.lang.String scala> test1("ab") res0: java.lang.String = abab

funciona bien

scala> val test2 = test1 <console>:6: error: missing arguments for method test1 in object $iw; follow this method with `_'' if you want to treat it as a partially applied function val test2 = test1 ^

Uy.

scala> val test2 = test1 _ test2: (String) => java.lang.String = <function1> scala> test2("ab") res1: java.lang.String = abab

¡funciona bien!

Ahora, he visto la sintaxis _ al plegar ( _ + _ , etc.). Entonces, según lo entiendo, básicamente significa "un argumento". Así que test1 _ básicamente significa una función con un argumento, que se da a test1 ". ¿Pero por qué no es exactamente lo mismo que test1 ? ¿Por qué hay una diferencia si agrego un _ ?

Así que seguí explorando ...

scala> val test3 = (str: String) => str + str test3: (String) => java.lang.String = <function1> scala> test3("ab") res2: java.lang.String = abab scala> val test4 = test3 test4: (String) => java.lang.String = <function1>

Aquí funciona sin _ ! ¿Cuál es la diferencia entre una función def ed y una función val ed?


El guión bajo significa diferentes cosas en diferentes contextos. Pero siempre se puede pensar que es lo que iría aquí, pero no necesita ser nombrado .

Cuando se aplica en lugar de parámetros, el efecto es elevar el método a una función.

scala> def test1(str: String) = str + str; test1: (str: String)java.lang.String scala> val f1 = test1 _ f1: (String) => java.lang.String = <function1>

Tenga en cuenta que el método se ha convertido en una función de tipo (String) => String.

La distinción entre un método y una función en Scala es que los métodos son similares a los métodos tradicionales de Java. No puedes pasarlos como valores. Sin embargo, las funciones son valores por derecho propio y se pueden usar como parámetros de entrada y valores de retorno.

El levantamiento puede ir más allá:

scala> val f2 = f1 _ f2: () => (String) => java.lang.String = <function0>

Al levantar esta función, se obtiene otra función. Esta vez de tipo () => (String) => (String)

Por lo que puedo decir, esta sintaxis es equivalente a sustituir todos los parámetros con un guión bajo explícitamente. Por ejemplo:

scala> def add(i: Int, j: Int) = i + j add: (i: Int,j: Int)Int scala> val addF = add(_, _) addF: (Int, Int) => Int = <function2> scala> val addF2 = add _ addF2: (Int, Int) => Int = <function2>


La def declara un método dentro de un objeto / clase / rasgo circundante, similar a la forma en que defines los métodos en Java. Solo puede usar def s dentro de otros objetos / clases / rasgos. En el REPL, no puede ver el objeto circundante porque está "oculto", pero sí existe.

No puede asignar una def a un valor, porque la def no es un valor; es un método en el objeto.

El (x: T) => x * x declara y crea una instancia de un objeto de función , que existe en tiempo de ejecución. Los objetos de función son instancias de clases anónimas que extienden rasgos de FunctionN . FunctionN rasgos de FunctionN vienen con un método de apply . El nombre apply es especial, porque puede ser omitido. La expresión f(x) se f.apply(x) en f.apply(x) .

La línea de fondo es que, dado que los objetos de función son valores de tiempo de ejecución que existen en el montón, puede asignarlos a valores, variables y parámetros, o devolverlos de métodos como valores de retorno.

Para resolver el problema de asignar métodos a valores (que pueden ser útiles), Scala le permite usar el carácter de marcador de posición para crear un objeto de función a partir de un método. Expression test1 _ en su ejemplo anterior realmente crea una función de envoltura alrededor del método test1 - es equivalente a x => test1(x) .


No hay diferencia entre una función definida y una función valuada:

scala> def test1 = (str: String) => str + str test1: (String) => java.lang.String scala> val test2 = test1 test2: (String) => java.lang.String = <function1> scala> val test3 = (str: String) => str + str test3: (String) => java.lang.String = <function1> scala> val test4 = test2 test4: (String) => java.lang.String = <function1>

¿Ver? Todas estas son funciones, que se indican con el tipo X => Y que tienen.

scala> def test5(str: String) = str + str test5: (str: String)java.lang.String

¿Ves un tipo X => Y ? Si lo hace, vaya a ver a un oftalmólogo, porque no hay ninguno. El tipo aquí es (X)Y , comúnmente usado para denotar un método .

En realidad, test1 , test2 , test3 y test4 son todos métodos que devuelven funciones. test5 es un método que devuelve un java.lang.String . Además, test1 a test4 no toman parámetros (solo test1 podría, de todos modos), mientras test5 hace.

Entonces, la diferencia es bastante simple. En el primer caso, trataste de asignar un método a un val, pero no completó los parámetros que tomó el método. Así que falló, hasta que agregó un guión bajo final, lo que significaba que convertiría mi método en una función .

En el segundo ejemplo, usted tenía una función, por lo que no tenía que hacer nada más.

Un método no es una función, y viceversa. Una función es un objeto de una de las clases de FunctionN . Un método es un identificador de algún código asociado a un objeto.

Vea varias preguntas sobre métodos vs funciones en .