¿Cómo funciona la magia del método apply () de Scala?

79

En Scala, si defino un método llamado applyen una clase o un objeto de nivel superior, ese método se llamará cada vez que agregue un par de paréntesis a una instancia de esa clase y coloque los argumentos apropiados apply()entre ellos. Por ejemplo:

class Foo(x: Int) {
    def apply(y: Int) = {
        x*x + y*y
    }
}

val f = new Foo(3)
f(4)   // returns 25

Básicamente, object(args)es solo azúcar sintáctico para object.apply(args).

¿Cómo Scala realiza esta conversión?

¿Hay una conversión implícita definida globalmente aquí, similar a las conversiones de tipo implícitas en el objeto Predef (pero de diferente tipo)? ¿O es una magia más profunda? Lo pregunto porque parece que Scala favorece fuertemente la aplicación consistente de un conjunto más pequeño de reglas, en lugar de muchas reglas con muchas excepciones. Esto inicialmente me parece una excepción.

Jeff
fuente
1
Muy buena explicación, stackoverflow.com/questions/9737352/#9738862
Muhammad Hewedy

Respuestas:

67

No creo que haya nada más profundo que lo que dijiste originalmente: es simplemente azúcar sintáctico en el que el compilador se convierte f(a)en f.apply(a)un caso de sintaxis especial.

Esto puede parecer una regla específica, pero solo algunas de ellas (por ejemplo, con update) permiten construcciones y bibliotecas similares a DSL .

oxbow_lakes
fuente
4
Agregaría "cuándo fes un objeto (incluidas las funciones)". Cuando fes un método, obviamente no existe tal traducción.
Alexey Romanov
2
@AlexeyRomanov: Bueno, si fes un método que se define sin una lista de parámetros, entonces f(a)se interpreta como algo así val _tmp = f; _tmp.apply(a). Pero eso es realmente entrar firmemente en el territorio de la división de los pelos.
Jörg W Mittag
20

En realidad, es al revés, un objeto o clase con un método de aplicación es el caso normal y una función es una forma de construir implícitamente un objeto del mismo nombre con un método de aplicación. En realidad, cada función que defina es un subobjeto del rasgo Función n (n es el número de argumentos).

Consulte la sección 6.6: Aplicaciones de funciones de la especificación del lenguaje Scala para obtener más información sobre el tema.

sebasgo
fuente
+1 para cambiar la especificación del idioma Scala. Agregué la ubicación correcta ya que su número de página está desactualizado.
Alexandre Martins
8

Lo pregunto porque parece que Scala favorece fuertemente la aplicación consistente de un conjunto más pequeño de reglas, en lugar de muchas reglas con muchas excepciones.

Si. Y esta regla pertenece a este grupo más pequeño.

Alexey Romanov
fuente