Leí Scala Functions (parte de Another tour of Scala ). En ese post declaró:
Los métodos y las funciones no son lo mismo.
Pero no explicó nada al respecto. ¿Qué estaba tratando de decir?
Leí Scala Functions (parte de Another tour of Scala ). En ese post declaró:
Los métodos y las funciones no son lo mismo.
Pero no explicó nada al respecto. ¿Qué estaba tratando de decir?
Respuestas:
Jim tiene esto bastante cubierto en su publicación de blog , pero estoy publicando un resumen aquí como referencia.
Primero, veamos qué nos dice la especificación Scala. El Capítulo 3 (tipos) nos informa sobre los Tipos de funciones (3.2.9) y los Tipos de métodos (3.3.1). El Capítulo 4 (declaraciones básicas) habla de la Declaración y Definiciones de Valor (4.1), Declaración y Definiciones Variables (4.2) y Declaraciones y Definiciones de Funciones (4.6). El Capítulo 6 (expresiones) habla de funciones anónimas (6.23) y valores de método (6.7). Curiosamente, los valores de la función se mencionan una vez en 3.2.9, y en ningún otro lugar.
Un tipo de función es (aproximadamente) un tipo de la forma (T1, ..., Tn) => U , que es una abreviatura del rasgo
FunctionN
en la biblioteca estándar. Las funciones anónimas y los valores de método tienen tipos de función, y los tipos de función se pueden usar como parte de las declaraciones y definiciones de valores, variables y funciones. De hecho, puede ser parte de un tipo de método.Un tipo de método es un tipo sin valor . Eso significa que no hay valor, ni objeto, ni instancia, con un tipo de método. Como se mencionó anteriormente, un valor de método en realidad tiene un tipo de función . Un tipo de método es una
def
declaración: todo sobre adef
excepto su cuerpo.Valor declaraciones y definiciones y declaraciones de variables y definiciones son
val
yvar
declaraciones, incluyendo tanto el tipo y valor - que puede ser, respectivamente, del tipo de función y funciones anónimas o Valores Método . Tenga en cuenta que, en la JVM, estos (valores de método) se implementan con lo que Java llama "métodos".Una declaración de función es una
def
declaración, que incluye el tipo y el cuerpo . La parte de tipo es el Tipo de método, y el cuerpo es una expresión o un bloque . Esto también se implementa en la JVM con lo que Java llama "métodos".Finalmente, una función anónima es una instancia de un tipo de función (es decir, una instancia del rasgo
FunctionN
), ¡y un valor de método es lo mismo! La distinción es que un Valor de método se crea a partir de métodos, ya sea mediante la colocación de un guión bajo (m _
es un valor de método correspondiente a la "declaración de función" (def
)m
), o mediante un proceso llamado eta-expansion , que es como un método de conversión automática desde funcionar.Eso es lo que dicen las especificaciones, así que permítanme poner esto por adelantado: ¡no usamos esa terminología! Conduce a demasiada confusión entre la llamada "declaración de función" , que es parte del programa (capítulo 4 - declaraciones básicas) y "función anónima" , que es una expresión, y "tipo de función" , que es, bueno un tipo, un rasgo.
La siguiente terminología, y utilizada por programadores experimentados de Scala, hace un cambio con respecto a la terminología de la especificación: en lugar de decir declaración de función , decimos método . O incluso la declaración del método. Además, observamos que las declaraciones de valor y las declaraciones de variables también son métodos para fines prácticos.
Entonces, dado el cambio anterior en la terminología, aquí hay una explicación práctica de la distinción.
Una función es un objeto que incluye uno de los
FunctionX
rasgos, tales comoFunction0
,Function1
,Function2
, etc. Se podría incluyendoPartialFunction
, así, que se extiende en realidadFunction1
.Veamos la firma de tipo para uno de estos rasgos:
Este rasgo tiene un método abstracto (también tiene algunos métodos concretos):
Y eso nos dice todo lo que hay que saber al respecto. Una función tiene un
apply
método que recibe N parámetros de los tipos T1 , T2 , ..., TN y devuelve algo de tipoR
. Es contra-variante en los parámetros que recibe, y co-variante en el resultado.Esa variación significa que a
Function1[Seq[T], String]
es un subtipo deFunction1[List[T], AnyRef]
. Ser un subtipo significa que se puede usar en lugar de él. Uno puede ver fácilmente que si voy a llamarf(List(1, 2, 3))
y esperar unaAnyRef
devolución, cualquiera de los dos tipos anteriores funcionaría.Ahora, ¿cuál es la similitud de un método y una función? Bueno, si
f
es una función ym
es un método local para el alcance, entonces ambos pueden llamarse así:Estas llamadas son realmente diferentes, porque la primera es solo un azúcar sintáctico. Scala lo expande a:
Lo cual, por supuesto, es un método llamado a objeto
f
. Las funciones también tienen otros azúcares sintácticos para su ventaja: literales de función (dos de ellos, en realidad) y(T1, T2) => R
firmas de tipo. Por ejemplo:Otra similitud entre un método y una función es que el primero se puede convertir fácilmente en el segundo:
Scala ampliará eso , suponiendo que el
m
tipo esté(List[Int])AnyRef
en (Scala 2.7):En Scala 2.8, en realidad usa una
AbstractFunction1
clase para reducir el tamaño de las clases.Tenga en cuenta que no se puede convertir al revés, de una función a un método.
Sin embargo, los métodos tienen una gran ventaja (bueno, dos: pueden ser un poco más rápidos): pueden recibir parámetros de tipo . Por ejemplo, si bien
f
arriba puede especificar necesariamente el tipo deList
recepción (List[Int]
en el ejemplo),m
puede parametrizarlo:Creo que esto cubre casi todo, pero me complacerá complementar esto con respuestas a cualquier pregunta que pueda quedar.
fuente
val f = m
compilador comoval f = new AnyRef with Function1[List[Int], AnyRef] { def apply(x$1: List[Int]) = this.m(x$1) }
debe señalar que elthis
interior delapply
método no se refiere alAnyRef
objeto, sino al objeto en cuyo métodoval f = m _
se evalúa (el exteriorthis
, por así decirlo). ), ya que sethis
encuentra entre los valores que captura el cierre (como, por ejemplo,return
como se indica a continuación).Una gran diferencia práctica entre un método y una función es lo que
return
significa.return
solo regresa de un método. Por ejemplo:Al regresar de una función definida en un método, se realiza un retorno no local:
Mientras que regresar de un método local solo regresa de ese método.
fuente
for (a <- List(1, 2, 3)) { return ... }
? Eso se desestima a un cierre.return
devuelve un valor de la función, y alguna forma deescape
obreak
ocontinue
para volver de métodos.Programación en Scala Segunda Edición. Martin Odersky - Cuchara Lex - Bill Venners
fuente
Deja que digas que tienes una lista
Definir un método
Definir una función
Método de aceptación de argumento
Definición de función con val
El argumento para funcionar es opcional
El argumento al método es obligatorio
Consulte el siguiente Tutorial que explica cómo pasar otras diferencias con ejemplos como otro ejemplo de diferencia con la Función Método Vs, Usar la función como Variables, crear la función que devolvió la función
fuente
Las funciones no admiten valores predeterminados de parámetros. Los métodos lo hacen. La conversión de un método a una función pierde los valores predeterminados de los parámetros. (Scala 2.8.1)
fuente
Hay un buen artículo aquí. a partir del cual se toman la mayoría de mis descripciones. Solo una breve comparación de funciones y métodos con respecto a mi comprensión. Espero eso ayude:
Funciones : son básicamente un objeto. Más precisamente, las funciones son objetos con un método de aplicación; Por lo tanto, son un poco más lentos que los métodos debido a su sobrecarga. Es similar a los métodos estáticos en el sentido de que son independientes de un objeto a invocar. Un ejemplo simple de una función es como se muestra a continuación:
La línea de arriba no es más que asignar un objeto a otro como object1 = object2. En realidad, el object2 en nuestro ejemplo es una función anónima y el lado izquierdo obtiene el tipo de objeto debido a eso. Por lo tanto, ahora f1 es un objeto (Función). La función anónima es en realidad una instancia de Function1 [Int, Int] que significa una función con 1 parámetro de tipo Int y valor de retorno de tipo Int. Llamar a f1 sin los argumentos nos dará la firma de la función anónima (Int => Int =)
Métodos : no son objetos sino asignados a una instancia de una clase, es decir, un objeto. Exactamente lo mismo que el método en java o las funciones miembro en c ++ (como Raffi Khatchadourian señaló en un comentario a esta pregunta ) y etc. Un ejemplo simple de un método es como se muestra a continuación:
La línea anterior no es una simple asignación de valor, sino una definición de un método. Cuando invocas este método con el valor 2 como la segunda línea, la x se sustituye por 2 y el resultado se calculará y obtendrás 4 como salida. Aquí obtendrá un error si simplemente escribe m1 porque es un método y necesita el valor de entrada. Al usar _ puede asignar un método a una función como la siguiente:
fuente
Aquí hay una gran publicación de Rob Norris que explica la diferencia, aquí hay un TL; DR
con la siguiente definición:
En pocas palabras ( extracto del blog ):
Cuando definimos un método, vemos que no podemos asignarlo a a
val
.Tenga en cuenta también el tipo de
add1
, que no parece normal; No puede declarar una variable de tipo(n: Int)Int
. Los métodos no son valores.Sin embargo, al agregar el operador de postfijo de expansión η (η se pronuncia "eta"), podemos convertir el método en un valor de función. Tenga en cuenta el tipo de
f
.El efecto de
_
es realizar el equivalente de lo siguiente: construimos unaFunction1
instancia que delega a nuestro método.fuente
En Scala 2.13, a diferencia de las funciones, los métodos pueden tomar / regresar
Sin embargo, estas restricciones se levantan en dotty (Scala 3) por los tipos de funciones polimórficas # 4672 , por ejemplo, dotty versión 0.23.0-RC1 habilita la siguiente sintaxis
Parámetros de tipo
Parámetros implícitos ( parámetros de contexto )
Tipos dependientes
Para más ejemplos, vea tests / run / polymorphic-functions.scala
fuente
Prácticamente, un programador de Scala solo necesita conocer las siguientes tres reglas para usar las funciones y métodos correctamente:
def
y literales de función definidos por=>
son funciones. Está definido en la página 143, Capítulo 8 del libro de Programación en Scala, 4a edición.someNumber.foreach(println)
Después de cuatro ediciones de Programación en Scala, todavía es un problema para las personas diferenciar los dos conceptos importantes: función y valor de función porque todas las ediciones no dan una explicación clara. La especificación del lenguaje es demasiado complicada. Encontré que las reglas anteriores son simples y precisas.
fuente