From: Luke Graham Date: 2005-02-15T10:12:46+09:00 Subject: Re: can anyone verify this code as correct? Ok, I see the problem; foo = choices(1..100) bar = choices(1..100) condition([bar]) { bar > 10 } condition([bar]) { (bar % 2) == 0 } condition([foo, bar]) { bar == (foo * 2) } foo never increments because we fall through when bar is exhausted. On Tue, 15 Feb 2005 10:58:00 +1000, Luke Graham wrote: > Forgot this snippet that may be on the way to fixing the NilClass problem... > > def choices(choicelist) > @@cont ||= [] > choicelist.each { |choice| > callcc { |cc| > @@cont << cc > return choice > } > } > nil > end > > def condition(value) > return if value.include? nil > @@cont.pop.call if !yield > end > > foo = choices(1..100) > bar = choices(1..100) > > condition([foo]) { foo > 101 } > condition([bar]) { bar == 1 } > > puts foo > puts bar > > > On Tue, 15 Feb 2005 10:51:21 +1000, Luke Graham wrote: > > On Tue, 15 Feb 2005 00:01:44 +0900, William Morgan > > wrote: > > > Hi, > > > > > > > foo = choices(1..100) > > > > bar = choices(1..100) > > > > condition(lambda{foo == (bar * 3)}) > > > > condition(lambda{bar > 10}) > > > > condition(lambda{(bar % 2) == 0}) > > > > > > Cute! Some comments: > > > > > > > def condition(cond) > > > > return if (self.class == NilClass?) > > > > @@cont.pop.call if !cond.call > > > > end > > > > > > More idiomatic usage would be to take a block here, rather than > > > requiring an explicit lambda. Then calling it looks like: > > > > > > condition { foo == bar * 3 } > > > > Thusly... > > > > def condition > > return if (self.class == NilClass) > > @@cont.pop.call if !yield > > end > > > > > Also, you can drop the "class Object" declaration if you like, as > > > top-level methods are automatically defined in Object. Or, move > > > everything to a new class (even better). > > > > Now that Ive seen the light with the ||= operator, I can indeed drop that class > > declaration. Ruby didnt seem to like it the way I had it originally. Maybe > > that was when I used attr_accessor, hmm cant remember. At any rate, > > the class line can go now. I dont want to move to another class > > because that would ruin the simplicity of use :) > > > > > The real problem, though, is here: > > > > > > > class NilClass? > > > > def method_missing(methId, *args) > > > > return false > > > > end > > > > end > > > > > > Which has high potential to break existing code, or at least make > > > debugging very difficult. I haven't thought this through thoroughly, but > > > rather than returning nil, maybe you can jump to another continuation? > > > > I have thought about that too, condition is a possible place to jump back to. > > That could have implications though, so I want to be sure of it first. > > A manual checkpoint/escape continuation may be necessary. > > > > At the moment Im concentrating more on something like : > > condition([bar, foo]) {bar < foo} > > > > The argument tells us what variables affect the outcome of the condition, > > so a hash table of results can be created. Then computation can be optimised > > by quickly allowing through values that are true and popping continuations that > > have no effect on the important input values. Note that the value of bar is good > > enough, ie theres no point using :bar, and that the value returned by time() > > is a valid and useful argument as well. This is straying into monadic territory > > if my understanding of those strange beasts is correct. > > > > > Interesting idea, at any rate. The code is correct, though you have to > > > drop the ? in NilClass?. > > > > Yeah, sorry about that, that came from a wiki I posted the code on, > > didnt realise till after I sent the mail. > > > > -- > > spooq > > > > -- > -- > spooq > -- spooq