Seleccionar página

El viernes estuvimos en Huesca en el coding dojo organizado por frogtek con carlos ble. Fue bastante entretenido y muy interesante el programar por parejas. A pesar de que allí tiré de Java, me ha picado el gusanillo y he hecho la kata en Scala. Ahí va el código

import FluidApi._

case class User(val name: String, val surname: String, val age: Int, val location: String)

object FluidApi {

	def select(field: String): SelectClause = new SelectClause(field)
	def exec(clause: Executable) = clause.execute

	def getAttrib(user: User, field: String): Any = {
		val method = user.getClass.getDeclaredMethod(field)
		method.invoke(user).asInstanceOf[Object]
	}
}

trait Executable {
	def execute(): List[Any];
}

class FromClause(fromObjs: List[User], select: SelectClause) extends Executable {

	def execute() : List[Any] = fromObjs.map(getAttr(_, select.field))

	def where(field: String) = new WhereClause(field, this)

	def executeFiltered(filterfunc: (List[User]) => List[User]): List[Any] = {
		filterfunc(fromObjs).map(getAttrib(_, select.field))
	}

	private def getAttr(user: User, field: String): Any = {
		val method = user.getClass.getDeclaredMethod(field)
		method.invoke(user).asInstanceOf[Object]
	}
}

class SelectClause(val field: String) {

	def from(fromObjs: List[User]) = new FromClause(fromObjs, this)
}

class WhereClause(val field: String, from: FromClause) {

	def greater_than(value: Int) = new ConditionValueClause(this, from, {
		_.filter(getAttrib(_, field) match {
			case v: Int => v > value
		})
	})

	def less_than(value: Int) = new ConditionValueClause(this, from, {
		_.filter(getAttrib(_, field) match {
			case v: Int => v < value
		})
	})
}

class ConditionValueClause(where: WhereClause, from: FromClause,
		filterfunc: (List[User]) => List[User]) extends Executable {

	def filter = filterfunc
	def execute() : List[Any] = from.executeFiltered(filterfunc)
}

class FluidApiTest extends FunSuite {

	val users = List(User("pablito", "perez", 20, "Moscow"),
					User("pedrin", "rodriguez", 54, "Alcorcón"))
					User("pepito", "lopez", 40, "San Francisco")

	test("select name should return the name of all users") {
		val names = exec(select("name").from(users));
		assert(names.size === 2)
		assert(names.contains("pablito") && names.contains("pedrin"))
	}

	test("select age should return the age of all users") {
		val ages = exec(select("age").from(users));
		assert(ages.size === 2)
		assert(ages.contains(20) && ages.contains(54))
	}

	test("select name where age > 45 should return pedrin)") {
		val names = exec(select("name").from(users).where("age").greater_than(20));
		assert(names.size === 1)
		assert(names.contains("pedrin"))
	}

	test("select name where age < 21 should return pablito)") {
		val names = exec(select("name").from(users).where("age").less_than(21));
		assert(names.size === 1)
		assert(names.contains("pablito"))
	}
}

 

#codingdojohuesca

Share