Created
February 14, 2012 16:08
-
-
Save timyates/1827794 to your computer and use it in GitHub Desktop.
Closure Composition to run a stream of tokens
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
| // This will tag our closures so that we know to just push them on the Stack | |
| def fnMethod = { c -> | |
| c.getMetaClass().isFn = { -> true } | |
| c | |
| } | |
| // Define our operations | |
| def ops = [ | |
| fn_add: fnMethod( { a, b, Object... remaining -> [ a + b, *remaining ] } ), | |
| fn_sub: fnMethod( { a, b, Object... remaining -> [ a - b, *remaining ] } ), | |
| fn_div: fnMethod( { a, b, Object... remaining -> [ a / b, *remaining ] } ), | |
| fn_mul: fnMethod( { a, b, Object... remaining -> [ a * b, *remaining ] } ), | |
| fn_dup: fnMethod( { a, Object... remaining -> [ a, a, *remaining ] } ), | |
| ] |
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
| // Written as a category method on List | |
| class StackRunnerCategory { | |
| public static Closure compile( List program ) { | |
| List stack = program.collect { instr -> | |
| // if this is an op, return as-is, otherwise wrap in a closure which adds | |
| // itself into the program state | |
| if( instr.respondsTo( 'isFn' ) ) { | |
| instr | |
| } | |
| else { | |
| { Object... remaining -> [ *remaining, instr ].flatten() } | |
| } | |
| } | |
| // Then, compose all these closures into one... | |
| stack.drop( 1 ).inject( stack.head() ) { a, b -> b << a } | |
| } | |
| } |
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
| // take 1, duplicate it ([1,1]) | |
| // add these together ([2]) | |
| // add 4 to the stack ([2,4]) | |
| // Then multiply ([8]) | |
| def prg = [ 1, ops.fn_dup, ops.fn_add, 4, ops.fn_mul ] |
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
| use( StackRunnerCategory ) { | |
| // Convert our program to a single closure | |
| def code = prg.compile() | |
| // Then, print out the result of calling it | |
| println code() | |
| } |
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
| def prg = [ 1, 4, ops.fn_dup, ops.fn_add, ops.fn_mul ] |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Code described here