From: Luke Graham Date: 2005-02-16T19:34:30+09:00 Subject: Re: (ruby-talk: Re: can anyone verify this code as correct?) I added memoizing and then tried being lazy about my input.. and it is so much faster than Range! Why is Range so slow??? def choices(choicelist) @@cont ||= [] choicelist.each { |choice| callcc { |cc| @@cont << cc @@conditionCount = 0 return choice } } nil end def condition(dependsOn) @@memo ||= {} @@conditionCount ||= 0 @@conditionCount += 1 @@memo[@@conditionCount] ||= {} return if @@memo[@@conditionCount][dependsOn] == true if dependsOn.include? nil or @@memo[@@conditionCount][dependsOn] == false or !(@@memo[@@conditionCount][dependsOn] = yield) @@cont.pop.call if @@cont.last end end class Lazy def each x = 0 while (x < 100) x += 1 yield x end end end lazy = Lazy.new foo = choices(lazy) bar = choices(lazy) condition([foo, bar]) { bar == (foo * 2) } condition([bar]) { bar > 10 } condition([bar]) { (bar % 2) == 0 } condition([foo]) { foo > 30 } puts foo puts bar On Wed, 16 Feb 2005 10:30:25 +1000, Luke Graham wrote: > On Tue, 15 Feb 2005 16:26:13 -0800 (PST), E S > wrote: > > > L�hett�j�: Luke Graham > > > Aihe: Re: can anyone verify this code as correct? > > > > > > On Mon, 14 Feb 2005 17:52:06 +0900, E S wrote: > > > > > L�hett�j�: Luke Graham > > > > > Aihe: Re: can anyone verify this code as correct? > > > > > > > > > > On Mon, 14 Feb 2005 17:07:00 +0900, E S wrote: > > > > > > > L�hett�j�: Luke Graham > > > > > > > Aihe: can anyone verify this code as correct? > > > > > > > > > > > > > > class Object > > > > > > > def choices(choicelist) > > > > > > > if (!Class.class_variables.include? "@@cont") > > > > > > > @@cont = [] > > > > > > > end > > > > > > > > > > > > You can use '@@cont ||= []'. > > > > > > > > > > Thanks, I like that one. > > > > > > > > > > > > choicelist.each { |choice| > > > > > > > callcc { |cc| > > > > > > > @@cont << cc > > > > > > > return choice > > > > > > > } > > > > > > > } > > > > > > > nil > > > > > > > end > > > > > > > > > > > > Continuation returns after the block, either with the value of the > > > > > > block or the parameter to #call, and it stores its execution context. > > > > > > Here you're returning in the middle of a loop, so I'm thinking each > > > > > > #call will cause the remaining 'choicelist' to be iterated over again, > > > > > > so the actual return value is going to be 'choicelist'. > > > > > > > > > > I dont understand... the return value is definitely not choicelist, but > > > > > a different choice each time. The callcc is -inside- the internal iteration. > > > > > After all values have been exhausted, nil is the last thing to be > > > > > returned, and effectively marks the limit of choices, as '\0' does for > > > > > c-strings. The array could probably stand to be flattened first, just > > > > > in case. > > > > > > > > Ah, indeed. That's what I get for omitting 'return' (all keystrokes > > > > count at 03:00 :) So yes, the code remains valid (just without the > > > > interesting side-effects). > > > > > > They certainly do count, even at 3am when our human brains can > > > no longer compete with silicon. :) Would you consider this a > > > non-evil use of continuations? If so, I will be very pleased > > > with myself for re-inventing it. Havent seen it before personally, > > > but nothing is new in this world - Im sure LISP had it years ago ;) > > > > Non-evil and valid, yes. It may not be the most effective way to > > implement your idiom -which, I'd say, is some sort of emulation of > > lazy evaluation- though. The enhancements detailed later address the > > shortcomings quite well. > > > > E > > Lazy evaluation is another way of thinking of it. I believe you know you > are using true primitives (like callcc) when ideas start to blur into each > other and still take only a few lines of code. > > -- > spooq > -- spooq