On 5/20/06, Daniel Schierbeck <daniel.schierbeck / gmail.com> wrote: > Daniel Schierbeck wrote: > > List inject := method(n, blk, self foreach(v, n = blk call(n, v))) > > Found out what the problem was -- the 'call' message to 'blk' messed > things up. This works: > > List inject := method(n, blk, self foreach(v, n = blk(n, v))) > list(1, 2, 3) => 6 I've written this one quite a few times and ways in Io. The way you write it heavily depends on the features you want and which idioms you want to use. My first attempt at it was to mirror Ruby's inject as close as possible (updated to work with the latest darcs at iolanguage.com): List inject := method( lst := self clone index := 0 if(call argCount == 3, memo := lst removeFirst index = index - 1 , memo := call evalArgAt(0) ) memoName := call argAt(index + 1) name varName := call argAt(index + 2) name body := call argAt(index + 3) yield := block setMessage(body) setArgumentNames(list(memoName,varName)) setScope(call sender) lst foreach(elem, memo = yield(memo, elem)) memo ) # Usage list(1,2,3) inject(0,m,v, m+v) list(3,2,1) inject(m,v, m+v) Note that it is a bit complex looking because I allow it to work for calls with and calls without a seed value. This mirrors the ruby philosophy quite close as you might note that the inject code is called with a Block object that I construct (calling it yield even). It also creates the lexical closure and a block local scope like ruby would have. I prefer this in general but it is NOT considered idiomatic Io (at least at this point). The main thing Io does away with is scoping the code in its own block. Instead, most code is directly evaluated in the scope of the sender. This is simpler to write but can cause problems if you are not aware of this difference. In the end it comes down to a stylistic issue (I tend to lean more towards FP so I don't like such broad side effects). A sample implementation might look like this: List inject := method( lst := self clone index := 0 if(call argCount == 3, memo := lst removeFirst index = index - 1 , memo := call evalArgAt(0) ) memoName := call argAt(index + 1) name varName := call argAt(index + 2) name bodyIndex := index + 3 lst foreach(elem, call sender setSlot(memoName, memo) call sender setSlot(varName, elem) memo = call evalArgAt(bodyIndex) ) memo ) Of course, most of the code is the same (most of it is for dealing with optional seed values anyway). This time you can see that I am evaluating the messages in a very specific context rather than creating a high level calling mechanism. This mirrors a lot of Io (for many reasons outside the scope of this email). In the end I usually end up writing with my own style because many idioms in Io are still immature. Things are slowly developing but there are still things to be worked out (IMO -- some people refuse to admit fault on some things). I highly recommend you join the ML (no yahoo account needed -- find the subscribe email addr. and just send a mail to it) if you want to listen in. In the archives you might find some interesting threads. Related to this one might be the IoProp1 thread that deals with activation of objects which heavily determines how easy it is to build correct code that uses high order procedures (hint: both of the above have a bug in it related to activatable objects... I left it in for clarity as the solution muddles the solutions a bit more than I wanted). Brian.