more functional, generic and dsl-ish version of https://gist.github.com/k33g/1dfb5bf477b7e121422d ;D
module prepostdeco
import java.lang.Math
# Decorator: apply checkers to parameters and result
function checkThat = |preTests...| {
return |postTest| {
return |fun| {
return |args...| {
_apply_tests_(preTests, args)
let result = fun: invokeWithArguments(args)
postTest(result)
return result
}
}
}
}
function _apply_tests_ = |tests, args| {
for ( var i = 0, i < min(tests: length(), args: length()), i = i + 1) {
tests: get(i)(args: get(i))
}
}
function any = |v| -> v
function checkType = |t| {
return |v| {
require(v oftype t, v + " is not a " + t: getName())
return v
}
}
function greaterThan = |m| {
return |v| {
require(v > m, v + " is not greater than " + m)
return v
}
}
function lengthIs = |l| {
return |v| {
require(v: length() == l, "length of " + v + " is not " + l)
return v
}
}
let isInteger = checkType(Integer.class)
let isString = checkType(String.class)
let isPositive = greaterThan(0)
@checkThat(isInteger: andThen(isPositive), isString)(isString: andThen(lengthIs(2)))
function foo = |a, b| {
return b + a
}
function main = |args| {
try { println(foo(1, "b")) } catch (e) { println(e) }
try { println(foo(-1, "b")) } catch (e) { println(e) }
try { println(foo("a", 2)) } catch (e) { println(e) }
try { println(foo(1, 2)) } catch (e) { println(e) }
try { println(foo(10, "ab")) } catch (e) { println(e) }
}