"Phil Tomson" <ptkwt / aracnet.com> schrieb im Newsbeitrag 
news:d26uh30st5 / enews1.newsguy.com...
> We've been having this discussion about defining your own while loop in a
> thread about Haskell and I thought I'd change the subject in case people
> who had no interest in Haskell were avoiding it ;-)
>
> In article <d26sfn01vqs / enews3.newsguy.com>,
> Phil Tomson <ptkwt / aracnet.com> wrote:
>>In article <3anjpeF6d91alU1 / individual.net>,
>>Robert Klemme <bob.news / gmx.net> wrote:
>>>
>>>"Phil Tomson" <ptkwt / aracnet.com> schrieb im Newsbeitrag
>>>news:d24b8d02fq1 / enews4.newsguy.com...
>>>> In article <3alo9bF6d2vo8U1 / individual.net>,
>>>> Robert Klemme <bob.news / gmx.net> wrote:
>>>>>
>>>>>
>>>>>I'm surprised about "retry", too.  His analysis sounds all very
>>>>>resonable -
>>>>>only that "break" does not work for me but "return" does:
>>>>>
>>>>>>> def my_while(cond)
>>>>>>>   break unless cond
>>>>>>>   yield
>>>>>>>   retry
>>>>>>> end
>>>>>=> nil
>>>>>>> i = 0
>>>>>=> 0
>>>>>>> my_while i < 10 do
>>>>>?>   puts i
>>>>>>>   i += 1
>>>>>>> end
>>>>>0
>>>>>1
>>>>>2
>>>>>3
>>>>>4
>>>>>5
>>>>>6
>>>>>7
>>>>>8
>>>>>9
>>>>>LocalJumpError: unexpected break
>>>>>        from (irb):2:in `my_while'
>>>>>        from (irb):7
>>>>
>>>>
>>>> Hmmm...  break works find for me in 1.8.2.  Time to upgrade?
>>>
>>>Yeah, maybe.
>>>
>>>>>Btw, can anybody think of a way to make my_while return the result of 
>>>>>the
>>>>>last block evaluation?  It seems impossible because the return occurs
>>>>>before
>>>>>the yield...
>>>>>
>>>>
>>>>
>>>> How about:
>>>>
>>>>  def my_while(cond)
>>>>    return @ret unless cond
>>>>    @ret = yield
>>>>    retry
>>>>  end
>>>
>>>Not thread safe.  And I think also not nesting safe.
>>>
>>
>>Yes, I know.  Did you see my later post?  I don't think it made it from
>>the newsgroup to the mailing list.

Yes, I saw it - but too late. :-)

>>Here's the code to make it nestable and threadsafe:
>>
>>  class Whiler
>>    def initialize
>>      @ret = nil
>>    end
>>
>>    def while(cond)
>>      break @ret unless cond
>>      @ret = yield
>>      retry
>>    end
>>  end
>>
>>  outer = Whiler.new
>>  inner = Whiler.new
>>
>>  i=0
>>  outer.while i<5 do
>>    puts "i: #{i}"
>>    j=0
>>    inner.while j<5 do
>>      puts "  j: #{j}"
>>      j+=1
>>    end
>>    i+=1
>>  end
>>
>>A bit cumbersome, perhaps, but it is definately nestable and should be
>>threadsafe as well.
>>
>
> Actually, I figured out a way to make it much more natural:
>
> Change Whiler to accept an optional condition in it's constructor like
> so:
>
>  class Whiler
>    def initialize(cond=nil)
>      @ret = nil
>      @cond = cond
>    end
>    def while(cond=@cond)
>      break @ret unless cond
>      @ret = yield
>      retry
>    end
>  end
>
>
> Define the my_while top-level method like so:
>
>  def my_while(cond,&block)
>    Whiler.new(cond).method(:while).call(&block)
>  end
>
>
> Now the user of my_while doesn't need to know that a Whiler class even
> exists.  Usage example:
>
>  i = 0
>  my_while(i<10) do
>    puts i
>    j=0
>    my_while(j<10) do
>      puts "  j: #{j}"
>      j+=1
>    end
>    i+=1
>  end
>

This is nice!

> I think there are some implications for DSLs (Domain Specific Languages)
> in this example.
> The my_while method as defined above (the last one) hides some Ruby
> language details from the user of my_while so that my_while can appear 
> like a
> natural looping construct.  I've created DSLs for people who had
> no idea they were using Ruby underneath; this sort of thing is
> necessary so they don't feel as though they are obliged to learn
> Ruby to use the DSL.
>
> Another example of why Ruby is so good for creating DSLs. ;-)

+2

Kind regards

    robert