From: Luke Graham Date: 2005-02-17T17:49:41+09:00 Subject: Re: (ruby-talk: Re: can anyone verify this code as correct?) Heres another funny little function. Next is getting a list of all acceptable values. def again @@counter ||= 0 @@agains ||= 0 @@agains += 1 return if @@counter >= @@agains @@counter += 1 @@agains = 0 @@cont.last.call if @@cont.last end foo = choices(1..10) bar = choices(1..10) condition([foo]) { foo > 3 } condition([bar]) { bar > 3 } again again again puts foo puts bar On Wed, 16 Feb 2005 20:34:16 +1000, Luke Graham wrote: > 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 > -- spooq