From: Brian Candler Date: 2003-08-08T00:40:27+09:00 Subject: Re: Elegant solution for a loop-break problem 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.