-
-
Save felipeg48/b570e69837c7b36cd548 to your computer and use it in GitHub Desktop.
This file contains 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
// No commas | |
def a = 'tim' | |
def nocom = match( a ) { | |
when 'dave' 'Hi Dave' | |
when 'tim' 'Hi Tim' | |
otherwise 'none of the above' | |
} | |
assert nocom == 'Hi Tim' | |
// Commas | |
a = 'William' | |
def com = match( a ) { | |
when 'dave', 'Hi Dave' | |
when 'tim', 'Hi Tim' | |
otherwise 'none of the above' | |
} | |
assert com == 'none of the above' | |
// Lists (can't use commas) | |
a = [1,3] | |
def list = match( a ) { | |
when [1,2] 'One and two' | |
when [1,3] 'One and three' | |
when [2,1] 'Two and one' | |
} | |
assert list == 'One and three' | |
// Wildcard Lists (can't use commas) | |
a = [1,2,3] | |
def wild = match( a ) { | |
when [1,3,2] 'One, three and two' | |
when [1,_] 'One and something' | |
when [1,_,3] 'One, something and three' | |
when [1,_,_] 'One, something and something' | |
otherwise 'Something else' | |
} | |
assert wild == 'One, something and three' | |
// Closures as the when/results | |
String toRoman( int num ) { | |
match( num ) { | |
when { it >= 100 } { "C" + toRoman( num - 100 ) } | |
when { it >= 90 } { "XC" + toRoman( num - 90 ) } | |
when { it >= 50 } { "L" + toRoman( num - 50 ) } | |
when { it >= 40 } { "XL" + toRoman( num - 40 ) } | |
when { it >= 10 } { "X" + toRoman( num - 10 ) } | |
when { it >= 9 } { "IX" + toRoman( num - 9 ) } | |
when { it >= 5 } { "V" + toRoman( num - 5 ) } | |
when { it >= 4 } { "IV" + toRoman( num - 4 ) } | |
when { it >= 1 } { "I" + toRoman( num - 1 ) } | |
otherwise "" | |
} | |
} | |
assert "I" == toRoman( 1 ) | |
assert "II" == toRoman( 2 ) | |
assert "IV" == toRoman( 4 ) | |
assert "V" == toRoman( 5 ) | |
assert "VI" == toRoman( 6 ) | |
assert "IX" == toRoman( 9 ) | |
assert "X" == toRoman( 10 ) | |
assert "XVII" == toRoman( 17 ) | |
assert "XXXVIII" == toRoman( 38 ) | |
assert "CCCXCIX" == toRoman( 399 ) | |
/////////////////////////// | |
// Implementation below... | |
def match( var, c ) { | |
new Matcher( var:var, closure:c ).match() | |
} | |
class Matcher { | |
def var | |
Closure closure | |
List<When> cases = [] | |
Otherwise otherwise | |
def propertyMissing( name ) { | |
if( name == '_' ) { | |
new Any() | |
} | |
else { | |
def w = new When() | |
cases << w | |
w | |
} | |
} | |
def when( condition ) { cases << new When( condition:condition ) } | |
def when( condition, result ) { cases << new When( condition:condition, result:result ) } | |
def otherwise( result ) { this.otherwise = new Otherwise( result:result ) } | |
public match() { | |
closure.delegate = this | |
closure.resolveStrategy = Closure.DELEGATE_ONLY | |
closure() | |
def ret = cases.find { | |
it.condition instanceof Closure ? | |
it.condition( var ) : | |
it.condition == var | |
}?.result ?: otherwise?.result | |
ret instanceof Closure ? ret() : ret | |
} | |
} | |
class When { | |
def condition | |
def result | |
def getAt( List a ) { condition = a ; this } | |
def call( result ) { this.result = result } | |
def propertyMissing( String result ) { this.result = result } | |
} | |
class Otherwise { | |
def result | |
} | |
class Any { | |
boolean equals( other ) { true } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment