Skip to content

Instantly share code, notes, and snippets.

@NicolasT
Created September 4, 2009 22:53
Show Gist options
  • Save NicolasT/181202 to your computer and use it in GitHub Desktop.
Save NicolasT/181202 to your computer and use it in GitHub Desktop.
// Some demo data classes
// Case classes are great!
sealed case class Agent(name: String)
sealed case class Machine(agent: Agent, parent: Machine)
// Our actual worker code. An Applicable is a Function1 which can also take
// another Applicable as argument, which will be combined.
// This works pretty much similar to the compose method of Function1, but
// without explicit call to it in client code
class Applicable[-T1, +R](fun: Function1[T1, R]) extends Function1[T1, R] {
// Function1 wants this, obviously
def apply(obj: T1) = fun(obj)
// Wrap compose. Not the argument can be any function which converts
// 'something' into an I
// So, we don't even need implicits
def apply[E1](a: Function1[E1, T1]) = new Applicable(compose(a))
}
object Selectors {
// A helper factory
def s[T1, R](fun: Function1[T1, R]) = new Applicable(fun)
// 2 default selectors
// Note there's almost no overhead code
val agent = s((_: Machine).agent)
val parent = s((_: Machine).parent)
}
object DSL {
def main(args: Array[String]): Unit = {
// Import our API
import Selectors._
// Create some test data
val m1 = Machine(Agent("agent1"), null)
val m2 = Machine(Agent("agent2"), m1)
val m3 = Machine(Agent("agent3"), m2)
// A first selector, assigned to a val
// Get the agent of the grandparent of a machine
val selector = agent(parent(parent))
// And print the name
println("Name of grandparent agent: " + selector(m3).name)
// Direct calls work as well, obviously
println("Name of agent of m3: " + agent(m3).name)
// Thank god for implicits, allows us to have custom selectors without
// any bizarre syntax (this might look strange to you, but all we do
// is define a custom inline function)
val selector2 = agent((_: Machine).parent)
println("Name of agent of parent of m3: " + selector2(m3).name)
// The first sample without predefined selectors
val selector3 = s((_: Machine).agent)((_: Machine).parent)((_: Machine).parent)
println("Name of grandparent agent again: " + selector3(m3).name)
}
}
p = lambda fun: lambda arg: (lambda m: fun(arg(m))) if callable(arg) \
else fun(arg)
agent = p(lambda m: m.agent)
parent = p(lambda m: m.parent)
class D: pass
m1 = D()
m1.agent = 'agentm1'
m2 = D()
m2.agent = 'agentm2'
m2.parent = m1
m3 = D()
m3.parent = m2
selector = agent(parent(parent))
print selector(m3)
/* POC code, abstract classes might be better */
class Machine {
private Agent agent;
private Machine parent;
public Machine(Agent agent) {
this.agent = agent;
this.parent = null;
}
public Machine(Agent agent, Machine parent) {
this(agent);
this.parent = parent;
}
public Machine getParent() {
return this.parent;
}
public Agent getAgent() {
return this.agent;
}
}
class Agent {
private String name;
public Agent(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}
abstract class Applicable<I, O> {
// A child should be an applicable which converts an input type into
// another input type. I think. Need to check
private Applicable<I, I> child;
public Applicable() {
this.child = null;
}
public Applicable(Applicable<I, I> a) {
this();
this.child = a;
}
abstract O do_apply(I obj);
public O apply(I obj) {
I real_i = null;
if(this.child != null)
real_i = this.child.apply(obj);
else
real_i = obj;
return do_apply(real_i);
}
}
class agent extends Applicable<Machine, Agent> {
public agent() {
super();
}
public agent(Applicable<Machine, Machine> a) {
super(a);
}
Agent do_apply(Machine obj) {
return obj.getAgent();
}
}
class parent extends Applicable<Machine, Machine> {
public parent() {
super();
}
public parent(Applicable<Machine, Machine> a) {
super(a);
}
Machine do_apply(Machine obj) {
return obj.getParent();
}
}
class DSL {
public static void main(String[] args) {
Machine m1 = new Machine(new Agent("agent1"));
Machine m2 = new Machine(new Agent("agent2"), m1);
Machine m3 = new Machine(new Agent("agent3"), m2);
System.out.println("Calculating name of parent's parent machine");
agent res = new agent(new parent(new parent()));
Agent a = res.apply(m3);
System.out.println("Name: " + a.getName());
System.out.println("Calculating agent name of m2");
agent res2 = new agent();
Agent b = res2.apply(m2);
System.out.println("Name: " + b.getName());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment