Created
September 4, 2009 22:53
-
-
Save NicolasT/181202 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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) | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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