On Fri, Aug 08, 2003 at 12:00:15AM +0900, KONTRA Gergely wrote:
> > > How can I alter items in a hash nicely?
> > 
> >          h[key] = value           # replace it
> >          h[key] << value          # append to existing array
> 
> Oops. Sorry. The question was dumb. I mean: I want to iterate over a
> hash and change some elements. (in perl you get the elements, not copys
> of the elements.

In Ruby you get the elements, not copies of the elements.

If you want to replace elements with completely new objects, you could do

    h.each_key do |k|
      h[k] = new_element
    end

But otherwise you call whatever mutator method you like on the object which
is in the hash:

    h.each do |e|
      e.change_my_state
    end

> > > Can I exit more loops with next/last/redo? (like in perl)
> > If you want to exit out of more than one level, use catch/throw.
> > [you mean next/break/redo I think]
> Yes, this works, but is there any exception? Wouldn't it be confusing?

I think it's pretty clear:

       catch(:foo) do
         8.times do |x|
           8.times do |y|
             puts "#{x},#{y}"
             throw :foo if x*y == 18
           end
         end
       end

But actually it's more powerful than that. You can throw exceptions from
within nested method calls. For example, you can have

     # program main event loop
     loop do
       catch :end_request do
         handle_request
       end
     end

Then handle_request can call methods, which call other methods, and
somewhere deep down you can decide to send a message to the user (say a page
of HTML) then "throw :end_request". This brings you right back to the main
loop. It's like "return" but for multiple levels of method call.

> > > Is there something similar to python's for .. else ... structure? (Do
> > > something, ONLY when the loop is terminated normally (without break)
> 
> Eg. suppose I want to search for value in array
> If it would be a for .. else .. end construction in ruby, I could write:
> 
> for element in array
>   if element==value
>     puts "#{element} found in array!"
>     break
>   end
> else
>   puts "#{element} not found in array"
> end
> 
> But ts showed, that a loop returns nil, if I use break without a
> parameter. (if I'm right...)

Oh I see what you want now - something which is executed after the last
iteration of the loop, if it was successful.

Regards,

Brian.