import system'routines; import extensions; import extensions'routines; joinable(former,later) = (former[former.Length - 1] == later[0]); dispatcher = { eval(object a, Func2 f) { ^ f(a[0],a[1]) } eval(object a, Func3 f) { ^ f(a[0], a[1],a[2]) } eval(object a, Func4 f) { ^ f(a[0],a[1],a[2],a[3]) } eval(object a, Func5 f) { ^ f(a[0],a[1],a[2],a[3],a[4]) } }; class AmbValueCollection { object theCombinator; constructor new(params object[] args) { theCombinator := SequentialEnumerator.new(params args) } seek(cond) { theCombinator.reset(); theCombinator.seekEach:(v => dispatcher.eval(v,cond)) } do(f) { var result := theCombinator.get(); if (nil != result) { dispatcher.eval(result,f) } else { InvalidArgumentException.raise() } } } singleton ambOperator { for(params object[] args) = AmbValueCollection.new(params args); } public program() { try { ambOperator .for(new::("the","that","a"),new::("frog", "elephant", "thing"),new::("walked", "treaded", "grows"), new::("slowly", "quickly")) .seek:(a,b,c,d => joinable(a,b) && joinable(b,c) && joinable(c,d) ) .do:(a,b,c,d) { console.printLine(a," ",b," ",c," ",d) } } catch(Exception e) { console.printLine:"AMB is angry" }; console.readChar() }