| ryah ( @ 2008-05-09 21:00:00 |
| Entry tags: | io |
methodWithNamedArgs for IO
After much searching I found some code mentioned on a mailing list for creating methods with named parameters in io.
doFile("Assert.io")
evalNamedArgs := block(
positionalArgs := list
sender thisMessage arguments foreach(i, arg,
if (arg name == "updateSlot",
name := arg argAt(0) cachedResult
sender setSlot(name, sender sender doMessage(arg argAt(1)))
,
positionalArgs add(arg)
)
)
positionalArgs reverse
sender getSlot("thisBlock") argumentNames foreach(i, name,
if (positionalArgs count == 0, break)
sender hasSlot(name) ifNil(
sender setSlot(name, sender sender doMessage(positionalArgs pop))
)
)
)
methodWithNamedArgs := block(
count := thisMessage arguments count
argNames := thisMessage arguments select(i,v, i != count-1) map(i, v, v name)
body := thisMessage argAt(count-1)
result := Lobby getSlot("Block") clone setMessage(
thisMessage clone setName("evalNamedArgs") setArguments(list) setNextMessage(body)
)
getSlot("result") argumentNames := argNames
getSlot("result")
)
test := methodWithNamedArgs(a, x, b, y,
assert( (x + y) == 10 )
assert( (a + b) == 31 )
)
test(13, y=3, x=7, 18)update
but that code doesn't work on the modern io interpeter. i hacked together this:
methodWithNamedArgs := method(
defArgs := call message arguments
body := defArgs pop
B := block(
argContext := Object clone
call message arguments foreach(arg,
if(arg name == "updateSlot",
name := arg argAt(0) cachedResult
value := call sender doMessage(arg argAt(1))
argContext setSlot(name, value)
)
)
argContext doMessage(body)
) setIsActivatable(true)
)
NamedArgsTest := UnitTest clone do(
testMultiplication := method(
m := methodWithNamedArgs(a, b, c, b * c)
assertEquals(8, m(c=1+1,b=4))
assertEquals(60, m(b=6, c=10))
)
testJoin := method(
j := methodWithNamedArgs(a, b, c, list(b,c) join(","))
assertEquals("hello,world", j(c="world",b="hello"))
assertEquals("hi,mom", j(b="hi", c="mom"))
)
) run