Re: Change in semantics for some control flow operations
Jeremy Tregunna <[email protected]> Fri, 09 Dec 2011 16:46:47 -0600
| Newsgroups | gmane.comp.lang.io |
|---|---|
| Message-ID | <[email protected]> |
A quick test, code below, results first: Normal foreach (the way we implement it now): 0.045998, 0.042344, 0.04463 With a single throwaway context: 0.041687, 0.044041, 0.042541 With a block: 0.129006, 0.134746, 0.133294 The above results are based on three runs, of the code below. As you can tell, it's a very trivial example (single arg form, didn't implement the other two and three arg forms for the sake of time): List foreachNormal := method( body := call argAt(0) for(i, 1, size, call sender doMessage(body)) ) List foreachContext := method( body := call argAt(0) ctx := call sender clone for(i, 1, size, body doInContext(ctx)) ) List foreachBlock := method( body := call argAt(0) blk := block setMessage(body) setScope(call sender) for(i, 1, size, blk call) ) Range; lst := 1 to(10000) asList Date secondsToRun(lst foreachNormal(1000000)) println Date secondsToRun(lst foreachContext(1000000)) println Date secondsToRun(lst foreachBlock(1000000)) println On 2011-12-09, at 4:30 PM, Steve Dekorte wrote: > > > Can you do a test to determine what the performance costs are? > > On 2011-12-08 Thu, at 06:43 AM, Jeremy Tregunna wrote: >> I want to propose a change in direction for the standard library foreach(), select(), and friends methods. I'll supply code, don't worry about that. >> >> Right now, how we go about doing things is once we're iterating, we set values in the calling context directly. This has obvious problems worse than shadowing, i.e., overwriting values we want and persisting after the foreach() has finished. Now at present, anyone hit by this problem will have renamed their identifiers when they got bad results, but this is rather confusing. Additionally, why should we leak these values? >> >> I'm proposing one of two solutions I think are a better fit: >> >> 1. Set up a block with the argument name(s) we want to set, the body we want to evaluate, and the proper scope to capture (the sender). Call that inside our main loop. >> 2. Create a separate isolated context outside the loop, set our value(s) in it inside the loop, a sk our body to doInContext with that context and the sender. This has a slight advantage performance wise in that we only create one context, as opposed to creating N locals with the block worst case (or recycling N locals depending on our environment). >> >> Now, this does have the negative use in that it breaks operational semantics of these methods at present if a user depends on this behaviour, but I'm ok with that; I'd consider that behaviour broken anyway. >> >> I think this should be done to all the standard library objects that support these types of constructs. Take some of the surprise out of using them. >> >> Regards, >> >> Jeremy Tregunna > > > > Regards, Jeremy Tregunna