8.01.2006
8:20 AM
Some important functional ... functions!
List foldl := method( accu := first args := list(nil) if(call message arguments size == 1, meth := call message argAt(0) name slice(1) foreach(i, accu = accu performWithArgList(meth, args atPut(0, i))) , fn := Protos getSlot("Block") clone setArgumentNames(call message arguments slice(0, 2) map(name)) setMessage(call argAt(2)) setScope(call sender) slice(1) foreach(i, accu = fn(accu, i)) ) accu ) List foldr := method( accu := last args := list(nil) if(call message arguments size == 1, meth := call message argAt(0) name slice(0, -1) reverseForeach(i, accu = i performWithArgList(meth, args atPut(0, accu))) , fn := Protos getSlot("Block") clone setArgumentNames(call message arguments slice(0, 2) map(name)) setMessage(call argAt(2)) setScope(call sender) slice(0, -1) reverseForeach(i, accu = fn(i, accu)) ) accu ) list(1, 2, 3) foldl(l, r, l + r) println // ((1 + 2) + 3) = 6 list(1, 2, 3) foldl(+) println list(2, 3, 5) foldr(l, r, l * r) println // (2 * (3 * 5)) = 30 list(2, 3, 5) foldr(*) println list(6, 2, 1) foldl(l, r, l - r) println // ((6 - 2) - 1) = 3 list(6, 2, 1) foldl(-) println list(6, 2, 1) foldr(l, r, l - r) println // (6 - (2 - 1)) = 5 list(6, 2, 1) foldr(-) println list(list, 1, 2, 3) foldl(l, r, l push(r)) println // list push(1) push(2) push(3) = list(1, 2, 3) list(list, 1, 2, 3) foldl(push) println list(42) foldr(+) println // (42) = 42
This is mostly to demonstrate the flexibility of Io's message manipulation, and method construction. The functions have two forms: an explicit and an implicit. The explicit form takes two symbols and a message, constructing a function to do the folding. The implicit form simply takes a symbol which it uses as the name of the function on the appropriate value to be called.
Next time I'll hit you up with some macro goodness using activatable messages.