Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   Ruby (http://www.velocityreviews.com/forums/f66-ruby.html)
-   -   Is it possible to break a loop from within an internal lambda function? (http://www.velocityreviews.com/forums/t865243-is-it-possible-to-break-a-loop-from-within-an-internal-lambda-function.html)

timr 11-14-2010 08:54 AM

Is it possible to break a loop from within an internal lambda function?
 
This code works because 'exit' within the lambda within the block
stops the loop. However, I don't want to stop the program. I need to
use break rather than exit. But break won't work within that lambda--
the loop doesn't stop. I can of course reorganize the statement so
that it isn't a terse one-liner, and get it to work. But I would like
to be able to break the loop from within that lambda function if it is
possible. Somehow, I guess I need to make that break have a binding
to the method. Any ideas?!?

def solve_by_iter
counter = 1
loop do
yield counter
counter += 1
end
end
solve_by_iter { |test| lambda{puts test; exit}.call if (1..6).all?{|
num| test%num == (num-1)} }
#I want to use: solve_by_iter { |test| lambda{puts test; break}.call
if (1..6).all?{|num| test%num == (num-1)} }

Skye Shaw!@#$ 11-14-2010 09:18 AM

Re: Is it possible to break a loop from within an internal lambda function?
 
On Nov 14, 12:54*am, timr <timra...@gmail.com> wrote:
> This code works because 'exit' within the lambda within the block
> stops the loop. However, I don't want to stop the program. I need to
> use break rather than exit.
>
> #I want to use: solve_by_iter { |test| *lambda{puts test; break}.call
> if (1..6).all?{|num| test%num == (num-1)} }



This seems like an odd code arrangement.

What's wrong with returning a boolean value from the inner lambda and
breaking in the block?

solve_by_iter { |test| break if lambda{puts test; false}.call }

-Skye

Skye Shaw!@#$ 11-14-2010 09:26 AM

Re: Is it possible to break a loop from within an internal lambda function?
 
On Nov 14, 1:18*am, "Skye Shaw!@#$" <skye.s...@gmail.com> wrote:
> On Nov 14, 12:54*am, timr <timra...@gmail.com> wrote:
>
> > #I want to use: solve_by_iter { |test| *lambda{puts test; break}.call
> > if (1..6).all?{|num| test%num == (num-1)} }

>
> What's wrong with returning a boolean value from the inner lambda and
> breaking in the block?
>
> solve_by_iter { |test| break if lambda{puts test; false}.call }


Though if you really, really -really, want to kill the call stack from
an arbitrary depth you could try (gulp):

def solve_by_iter
counter = 1
catch :break do
loop do
yield counter
counter += 1
end
end
end

solve_by_iter { |test| lambda{p test;throw :break}.call }


botp 11-14-2010 09:36 AM

Re: Is it possible to break a loop from within an internal lambda function?
 
On Sun, Nov 14, 2010 at 4:55 PM, timr <timrandg@gmail.com> wrote:
> solve_by_iter { |test| =A0lambda{puts test; exit}.call if (1..6).all?{|
> num| test%num =3D=3D (num-1)} }


try,

solve_by_iter { |test| break(lambda{puts test}.call) if
(1..6).all?{|num| test%num =3D=3D (num-1)} }

rare code, rare solution :)

kind regards -botp


timr 11-14-2010 10:19 AM

Re: Is it possible to break a loop from within an internal lambda function?
 
Thanks skye and botp. Both interesting solutions.

I also found this:
http://www.skorks.com/2010/05/ruby-p...-between-them/
"We get a LocalJumpError, what happened? Well, the break keyword is
used to break out of iteration, and we didn't have an iterator around
our proc, so we couldn't break out of anything, so Ruby tries to
punish us with an error. If we put an iterator around our proc,
everything would be fine:"

It gave me a better understanding of subtleties of lambdas and Procs.
Though, it looks like to make it work an iterator has to wrap the
calling of the proc more directly. I'll have to play with that more to
understand why. For the time being, I think break(lambda{}.call) is
the simplest solution.


w_a_x_man 11-14-2010 12:46 PM

Re: Is it possible to break a loop from within an internal lambda function?
 
On Nov 14, 2:54*am, timr <timra...@gmail.com> wrote:
> This code works because 'exit' within the lambda within the block
> stops the loop. However, I don't want to stop the program. I need to
> use break rather than exit. But break won't work within that lambda--
> the loop doesn't stop. I can of course reorganize the statement so
> that it isn't a terse one-liner, and get it to work. But I would like
> to be able to break the loop from within that lambda function if it is
> possible. *Somehow, I guess I need to make that break have a binding
> to the method. Any ideas?!?
>
> def solve_by_iter
> * counter = 1
> * loop do
> * * yield counter
> * * counter += 1
> * end
> end
> solve_by_iter { |test| *lambda{puts test; exit}.call if (1..6).all?{|
> num| test%num == (num-1)} }
> #I want to use: solve_by_iter { |test| *lambda{puts test; break}.call
> if (1..6).all?{|num| test%num == (num-1)} }



solve_by_iter{|test|
if (1..6).all?{|num| test % num == num - 1 }
puts test
break
end
}

solve_by_iter{|test|
(1..6).all?{|num| test%num == num-1} and (puts test; break)
}


timr 11-15-2010 06:50 AM

Re: Is it possible to break a loop from within an internal lambda function?
 
On Nov 14, 4:46*am, w_a_x_man <w_a_x_...@yahoo.com> wrote:
> On Nov 14, 2:54*am, timr <timra...@gmail.com> wrote:
>
>
>
>
>
>
>
>
>
> > This code works because 'exit' within the lambda within the block
> > stops the loop. However, I don't want to stop the program. I need to
> > use break rather than exit. But break won't work within that lambda--
> > the loop doesn't stop. I can of course reorganize the statement so
> > that it isn't a terse one-liner, and get it to work. But I would like
> > to be able to break the loop from within that lambda function if it is
> > possible. *Somehow, I guess I need to make that break have a binding
> > to the method. Any ideas?!?

>
> > def solve_by_iter
> > * counter = 1
> > * loop do
> > * * yield counter
> > * * counter += 1
> > * end
> > end
> > solve_by_iter { |test| *lambda{puts test; exit}.call if (1..6).all?{|
> > num| test%num == (num-1)} }
> > #I want to use: solve_by_iter { |test| *lambda{puts test; break}.call
> > if (1..6).all?{|num| test%num == (num-1)} }

>
> solve_by_iter{|test|
> * if (1..6).all?{|num| test % num == num - 1 }
> * * puts test
> * * break
> * end
>
> }
>
> solve_by_iter{|test|
> * (1..6).all?{|num| test%num == num-1} and (puts test; break)
>


That is also a clever solution. It uses 'and' for its ability control
whether a second statement should be evaluated rather than its boolean
sense. And I hadn't seen parentheses used to create multiline
statements like this before. That is the only reason I had been using
lambda before--to get a block of code with more than one line to be
executed as a single unit.

Similarly, break() is useful as previously suggested. The break() also
removes the need for a lambda statement. Combining solutions, and
using the if statement rather than 'and' which in my mind is slightly
easier to read, how about this (w/ slight refactoring of variable
names):

def solve_by_iter
counter = 1
loop do
yield(counter)
counter+=1
end
end

solve_by_iter{|numer| (puts numer; break) if (1..6).all?{|denom| numer
%denom == denom-1}}

Thanks guys, I learned a lot from your responses to this post.
Tim

botp 11-15-2010 07:31 AM

Re: Is it possible to break a loop from within an internal lambda function?
 
> solve_by_iter{|numer| (puts numer; break) if (1..6).all?{|denom| numer
> %denom == denom-1}}


in short, you can simply do

puts (1..1/0.0).find{|num| (1..6).all?{|denom| num % denom == denom - 1} }
59

kind regards -botp



All times are GMT. The time now is 06:31 AM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.