play - Comprender los bloques de Scala
play framework stream response (2)
Tengo dificultades para encontrar respuestas específicas a lo que sé que es algo trivial. Me gustaría entender cómo funcionan los bloques en Scala. Vengo de un fondo de java / ruby y parece que Scala tiene una forma completamente diferente de usar bloques.
El siguiente código es de Play! Sitio web del framework . Me gustaría entender qué Acción es semánticamente. Es un objeto o una función que acepta un bloque, o quizás ninguno.
object Application extends Controller {
def index = Action {
Ok(views.html.index("Your new application is ready."))
}
}
Si se trata de una función, tal vez se trate de azúcar sintáctico para lo siguiente (en cuyo caso, ¿cómo pasa Scala alrededor de bloques detrás de escena)?
def index = Action({
Ok(views.html.index("Your new application is ready."))
})
O es una sintaxis scala que desconozco.
Cualquier referencia al código fuente de Scala me ayudaría a entender cómo funciona esto detrás de escena.
Hay algunas cosas pasando aquí. Action
es un objeto que implementa un método apply()
, a qué se llama cuando tratas el objeto como una función. Hay algunas implementaciones de apply()
. La primera implementación usa un parámetro de nombre por nombre.
Scala admite un concepto conocido como ''parámetros de nombre'', que son como parámetros normales, excepto que solo se evalúan cuando se ejecuta el código que los referencia. Ayudan a crear construcciones que parecen formar parte del lenguaje sin recurrir a macros. En este caso, el bloque que rodea a Ok(..)
es solo un bloque regular de instrucciones, y el último valor se usa como el valor del bloque. El ejemplo que proporcionó funcionará sin los frenos. Básicamente estás pasando el resultado del método de apply
de Ok al método de apply
de Action
.
La segunda versión de apply()
sí toma una función anónima completa que asigna una solicitud a un resultado. En este caso, puede pasar una función anónima (o nombrada).
Sería mejor pensar en los bloques de scala como clases anónimas de Java (por ejemplo, como funciones de guayaba) en lugar de como bloques de rubí. En realidad, si descompilas el código scala verás más o menos el mismo código ( tomado de ejemplos de Guava ):
Function<String, Integer> lengthFunction = new Function<String, Integer>() {
public Integer apply(String string) {
return string.length();
}
};
La diferencia es que Scala proporciona una gran cantidad de azúcar sintáctica y le permite escribir el código anterior como:
val lengthFunction = { string: String => string.length }
En cuanto a un ejemplo de acción específico:
def index = Action({
Ok(views.html.index("Your new application is ready."))
})
Aquí la Acción es un objeto probable con el método de aplicar. Otro azúcar scala: el idioma le permite escribir Foo(bar)
y significa Foo.apply(bar)
. Luego, puede soltar llaves redondas cuando su llamada no es ambigua , entonces sí, en realidad es un método que recibió una llamada como:
def index = Action({
Ok(views.html.index("Your new application is ready."))
})
Y tenga algo así como una firma:
object Action {
def apply(block: => Result) = ???
}
Como ya lo dijo @yan, es una manera fácil de decir " hey", soy una función que acepta otra función que produce el resultado.
La invocación desahuciada se verá como
def index = Action.apply(new AbstractFunction[Result] {
def apply() = Ok.apply(views.html.index.apply("..."))
})