Antes de aprender Scala, usaba principalmente Java y Python para el desarrollo de mi trabajo diario. Tengo la impresión de que no distinguía deliberadamente entre method y function, una relación similar a cuando en la vida cotidiana no distinguimos deliberadamente entre masa y peso. Sin embargo, ciertamente hay diferencias entre ellos, y estas diferencias se basan en la conexión que existe entre ambos.

Cómo definir

Primero, citemos el texto original en inglés para ver las diferencias y conexiones en sus definiciones:

A Function Type is (roughly) a type of the form (T1, ..., Tn) => U, which is a shorthand for the trait FunctionN in the standard library. Anonymous Functions and Method Values have function types, and function types can be used as part of value, variable and function declarations and definitions. In fact, it can be part of a method type.

A Method Type is a non-value type. That means there is no value - no object, no instance - with a method type. As mentioned above, a Method Value actually has a Function Type. A method type is a def declaration - everything about a def except its body.

Ejemplo:

scala> def m1(x:Int) = x+3
m1: (x: Int)Int    

scala> val f1 = (x: Int) => x+3
f1: Int => Int = <function1>

¿Ves? Las definiciones de método y función ya se muestran en la firma (signature) del intérprete de Scala. `def m1(x: Int) = x+3` es una definición simple de method. En la firma, `m1: (x: Int)Int` indica que el method m1 tiene un parámetro x de tipo Int y el valor de retorno es de tipo Int.

`val f1 = (x: Int) => x+3` es una definición de function. En la firma del intérprete, `f1: Int => Int = <function1>` indica que el cuerpo del method de la function f1 acepta un parámetro de tipo Int y el tipo del resultado de salida es Int.

De los ejemplos anteriores, se obtiene un resumen:

Un método es un bloque de operaciones lógico que comienza con `def` y tiene una lista de parámetros (puede no tener lista de parámetros), al igual que un método miembro en un object o class.

Una función es un método anónimo asignado a una variable (o constante), con o sin lista de parámetros, y es una expresión que va seguida de un bloque de código lógico mediante el símbolo de conversión `=>`. La escritura del bloque de código lógico después del símbolo de conversión `=>` es igual que la parte del body del method.

Otras diferencias

Un method puede aparecer como parte de una expresión (llamando a la función y pasando argumentos), pero un method (método con parámetros) no puede ser la expresión final (un método sin parámetros sí puede, pero esto se convierte en una llamada al método, porque Scala permite omitir los paréntesis `()` al llamar a métodos sin parámetros), mientras que una function sí puede aparecer como expresión final.

scala> m1
<console>:12: error: missing arguments for method m1;
follow this method with `_' if you want to treat it as a partially applied function
       m1
       ^

scala> f1
res1: Int => Int = <function1>

Un method puede no tener lista de parámetros, o la lista de parámetros puede estar vacía. Pero una function debe tener una lista de parámetros (que también puede estar vacía). El nombre del método implica una llamada al método; el nombre de la función solo representa a la función en sí:

scala> def m2 = 100;
m2: Int

scala> def m3() = 1000;
m3: ()Int

scala> var f2 = => 100;
<console>:1: error: illegal start of simple expression
var f2 = => 100;
         ^

scala> var f2 =()=> 100;
f2: () => Int = <function0>

scala> m2
res2: Int = 100

scala> m3
res3: Int = 1000

scala> m3()
res4: Int = 1000

scala> f2
res5: () => Int = <function0>

scala> f2()
res6: Int = 100

Donde aparece una función, podemos proporcionar un método.

Esto se debe a que, si en un lugar donde se espera una función proporcionamos un método, el método se convierte automáticamente en una función. Este comportamiento se llama ETA expansion.

Nota:

Donde se espera una función, podemos usar un método.

Donde no se espera una función, el método no se convertirá automáticamente en una función.

En Scala, los operadores se interpretan como métodos:

 
  • Operador prefijo: `op obj` se interpreta como `obj.op`
  • Operador infijo: `obj1 op obj2` se interpreta como `obj1.op(obj2)`
  • Operador sufijo: `obj op` se interpreta como `obj.op`
scala> val ml = List(1,2,3,4)
ml: List[Int] = List(1, 2, 3, 4)

scala> ml.map((x)=>2*x)
res0: List[Int] = List(2, 4, 6, 8)

scala> def m(x:Int) = 2*x
m: (x: Int)Int

scala> ml.map(m)
res1: List[Int] = List(2, 4, 6, 8)

scala> def m(x:Int) = 3*x
m: (x: Int)Int

scala> ml.map(m)
res2: List[Int] = List(3, 6, 9, 12)

Se puede agregar un guion bajo después del nombre del método para forzar su conversión en función.

Nota:¡Debe haber al menos un espacio entre el nombre del método y el guion bajo!

scala> def m3(x: Int): Int = x * x * x
m3: (x: Int)Int

scala> val f3 = m3_
<console>:10: error: not found: value m3_
       val f3 = m3_
                ^

scala> val f3 = m3 _
f3: Int => Int = <function1>

scala> f3(3)
res0: Int = 27

Dirección original: https://www.cnblogs.com/shihuc/p/5082701.html