viernes, 19 de julio de 2013

Run play framework application from interactive console [Scala Play Framework 2.1]

UPDATE 22/Aug/2013: Lunatech published a more detailed explanation in it's blog article.
It's well documented that we have a interactive console in the Play Framewok

From it you can run, compile, execute test... But a really nice feature is that you can get a console inside your application. That's it, create objects from your model, call methods... interactively. To do this you just need run the console command.


Start your application in the interactive console

If you need to execute database commands from the interactive console, you will need to start your application.

You can do this way:

1. - Launch the play console with applyEvolutions.enabled
play -DapplyEvolutions.default=true console

2.-. Enter the console
console

3.- Start the application
new play.core.StaticApplication(new java.io.File("."))

Now you can execute any command, even the database ones


Example: Get a list of users with Slick

1.- Do the imports you need. In slick you will need something like this:
import play.api.Play.current
import play.api.db.slick.Config.driver.simple._
import play.api.db.slick.DB
import models._

2.- Do the queries:
scala> val userborn = for { u <- Users if u.id < 2 } yield (u.username, u.born)
userborn: scala.slick.lifted.Query[(scala.slick.lifted.Column[String], ...
scala> userborn.selectStatement
res5: String = select x2."username", x2."born" from "user" x2 where x2."id" < 2 
scala> DB.withSession { implicit session  => userborn.list.mkString }
res6: String = (Admin Surname,2003-07-19) 

lunes, 15 de julio de 2013

Problems overriding vals in Scala classes

In Scala you must be careful with parameters when creating classes or you can get strange results.

class Parent(i: Int) {
  def iDef = i
  val iVal = i
  lazy val iLazy = i
}
class Child(val i: Int) extends Parent(i+10)

val c = new Child(1)
c.iLazy  // Int = 11
c.iVal   // Int = 11
c.iDef   // Int = 11
c.i      // Int = 1  Ops!

Child has different values for the same i? Lets try with val in the parent

class Parent(val i: Int)
class Child(i: Int) extends Parent(i+10)  {
  val childi = i
}
val c = new Child(1)
c.i      // Int = 11
c.childi // Int = 1

Don't confuse parent and child parameters! There are two, one in Parent and one in Child.

Maybe that's not what you want. So, why not define both as val and override in Child?

class Parent(val i: Int) {
  def iDef = i
  val iVal = i
  lazy val iLazy = i
}
class Child(override val i: Int) extends Parent(i+10)

val c = new Child(1)
c.iLazy  // Int = 1
c.iVal   // Int = 11 Hmmmm... ?
c.iDef   // Int = 1
c.i      // Int = 1
Oh, this is weird... Even with override I have two different values!

Be careful with construction order in classes. The problem is you made a copy in the parent constructor, which it was created before the child constructor.

sábado, 13 de julio de 2013

Iterador en Scala


En Scala trabajar con conjuntos (List, Set, Map) es muy cómodo (map, filter...) pero ¿Qué pasa si no necesitas calcular el conjunto completo?

Para estos casos Scala dispone de Iterator, View y Stream, que posibilitan el cálculo bajo demanda.

Ejemplo

Encontrar un nombre de archivo no existente.
Supongamos que la función de cálculo de nombre (randomName en este caso) es costosa.

Alternativa funcional: Defino un conjunto (lista de nombres) y la operación a realizar (buscar el primero no existente).
  1. Obtengo un iterador a la lista de nombres ¡Que todavía no están generados!
  2. Usando el iterador busco el primero que no exista (paths.find(!_exists)) calculando únicamente los nombres que he necesitado.


Alternativa iterativa: Defino un bucle que calcula nombres y comprueba si no existe, finalizando cuando encuentre uno no existente. Posiblemente más propenso a errores (más variables, condición de finalización) y menos legible.

Posibles dudas

¿val o def ?
Val guarda el iterador, que puedes usar para obtener valores consecutivos. Por ejemplo: iterador.next; iterador.next;
Def crea un nuevo iterador cada vez que lo llamas.

¿En qué se diferencia iterator de stream? Simplificando: Stream guarda los valores en memoria al calcularlos, con lo que no tiene que recalcularlos si vuelves a recorrer la lista.

¿En qué se diferencia iterator de view? View permite acceso aleatorio al valor. Iterator recorre la lista avanzando y calculando cada elemento. Realmente View no es un contenedor, si no un envoltorio alrededor del contenedor que hace las peticiones cuando es necesario, lo que para elementos pequeños puede suponer una sobrecarga a considerar. Más información sobre las diferencias entre iterator y view en stackoferflow.