I have an array of lambda's i would like to run all of the lamba's at the same time, the array can have any number of lamba's this makes it hard. Since you can only enumerate through an array.
def detect_int(*args)
return 1 if args.empty?
n = 1
args.each do |lam|
until lam.call(n) do
n += 1
end
retry if lam.call(n) == false
end
n
end
This method should work in theory, it should increase the count till lam1.call(n) returns true. then it will move to the next lam, if lam2.call(n) returns false it should retry the args.each loop with the incremented n starting at lam1 again. and so on.
Only i am getting an SyntaxError: (irb):76: Invalid retry how would you retry that each loop so that it will start it from the beginning
I was reading up on ruby loops and the retry method here. mine seems to fit the syntax correctly, but because its a loop within a loop it can get confusing. currently its sitting in the args loop which is the loop i would like to reset.
Since retry is a ruby keyword, parser wants to see either a native loop or a begin-rescue-end condition around. There is no one and the parser got stuck (Array#each is not a ruby loop, it’s an invocation of plain ruby method on array instance.) The possible solution would be:
args.each do |lam|
begin # grant parser with a scope
until lam.call(n) do
n += 1
end
raise if lam.call(n) == false
rescue
retry
end
end
Here is another way of doing it. Once every instance of args is true it will only break the loop. this is dangerous because it could never satisfy the loop and go on indefinitely
n = 1
while true do
args.all? { |lam| lam.call(n) } and return n
n += 1
end
Related
unable to understand this code how it works.
triangular_numbers = Enumerator.new do |yielder|
number = 0
count = 1
loop do
number += count
count += 1
yielder.yield number
end
end
5.times { print triangular_numbers.next, " " }
cant understand how yielder works for this block. how its yield work for number variable. how do loop runs 5 times. and how triangular_number.next works for the first time.
An enumerator is basically something that you can call next on and get something back. The yielder is the mechanism where it gives something back when next is called. Execution stops at the yield until the next call to next.
Farfetched analogy
You can think of an enumerator as a ticket machine like when you're waiting in line at a government office. When you press a button (next) it gives you a ticket. Inside the machine there's a chute where the ticket comes out. But the ticket machine is not constantly printing tickets. It waits for the button to be pressed before it prints the next ticket and puts it through the chute.
In this case the analogous code would be:
ticket_machine = Enumerator.new do |chute|
ticket = 0
loop do
#print_ticket
chute.yield ticket #waits here until you hit the button
ticket += 1
end
end
5.times { print ticket_machine.next, " " } # gets 5 tickets
Your code sample is basically the same thing, but instead of issuing tickets, it's issuing triangular numbers. The chute is the yielder where the numbers get passed through.
This is not the only way to use an enumerator, check the docs for more.
Enumerator::new accepts a block. This block, when run, receives an Enumerator::Yielder, which has a method #yield.
When the Enumerator#next is called, the block is executed, up to the first Enumerator::Yielder#yield. The execution is paused there; the value given to yield is the value that next returns. When you call next again on the same Enumerator, the execution is resumed, and proceeds until it encounters yield again.
So in your case, 5.times executes its block, intending to repeat it five times. triangular_numbers.next is called; this starts the execution of the block above. number and count are set to their values, and an infinite loop is started. number is set to 1, count is set to 2, and then we find yielder.yield. This pauses the execution of the block, and returns the control back to where next was called inside 5.times loop. next returns 1, because yielder.yield received number (1).
Second time through the 5.times loop, we want to print the next number. This stops the main execution line, and resumes the enumerator block from just after yielder.yield. The infinite loop continues; number is 3, count is 3, yielder.yield pauses the enumerator and resumes the main code. next gets 3, which gets printed.
Third, fourth and fifth time through the 5.times loop are exactly the same.
After five iterations, 5.times loop ends, and the execution proceeds past it. The enumerator is paused, ready to give the next number in sequence, if you ever call next on it again (since it has an infinite loop), but you never do, and the program exits.
I'll try to explain what it does bit by bit, so you can try to wrap your head around it.
Enumerator.new do |yielder|
end
So you instantiate an enumerator that will work over a variable called yielder.
Inside its scope you set some local vars (that will be kept as the object is reused):
number = 0
count = 1
And then you set a loop that increments number by count and count by 1 and then call yield over your argument passing number to it as an argument.
loop do
number += count
count += 1
yielder.yield number
end
5.times repeats the block passed to it 5 times. The block
-> { print triangular_numbers.next, " " }
calls print that takes n args and concatenates the parts to form a string, but does not append a newline.
The first argument is our enumerator next interaction (triangular_numbers.next), which will compute the current number and call yield on the Enumerator::Yielder that's implicitly created handling the control back to the calling Fiber along with any args that got passed to it.
(All Enumerators are implemented as "Fibers" on MRI)
So that yielder.yield call is similar to a Fiber.yield call and will allow the 5.times loop to run and return the number 1.
I'm adding a piece of code to the already clear explanation provided:
my_enum = Enumerator.new do |whatever_name_for_the_yielder|
n = 0
loop do
whatever_name_for_the_yielder.yield "Return this: #{n}"
n += 1
end
end
puts my_enum.next #=> Return this: 0
puts my_enum.next #=> Return this: 1
puts my_enum.next #=> Return this: 2
When you provide an end to the iteration, it stops with an error:
my_enum2 = Enumerator.new do |whatever_name_for_the_yielder|
2.times do |n|
whatever_name_for_the_yielder.yield "Return this: #{n}"
end
puts "Outside the loop"
end
puts my_enum2.next #=> Return this: 0
puts my_enum2.next #=> Return this: 1
puts my_enum2.next #=> Outside the loop
#=> ERROR: .....in `next': iteration reached an end (StopIteration)
In the following situation:
xxx.delete_if do |x|
yyy.descend do |y| # This is a pathname.descend
zzz.each do |z|
if x + y == z
# Do something
# Break all nested loops returning to "xxx.delete_if do |x|" loop
# The "xxx.delete_if do |x|" must receive a "true" so that it
# can delete the array item
end
end
end
end
What is the best way to achieve this multiple nested break while making sure I can pass the true value so that the array item is deleted?
Maybe I should use multiple break statements that return true or use a throw/catch with a variable, but I don't know if those are the best answer.
This question is different from How to break from nested loops in Ruby? because it requires that the parent loop receives a value from the nested loop.
throw/catch (NOT raise/rescue) is the way I typically see this done.
xxx.delete_if do |x|
catch(:done) do
yyy.each do |y|
zzz.each do |z|
if x + y == z
# Do something
throw(:done, true)
end
end
end
false
end
end
In fact, the Pickaxe explicitly recommends it:
While the exception mechanism of raise and rescue is great for abandoning execution when things go wrong, it's sometimes nice to be able to jump out of some deeply nested construct during normal processing. This is where catch and throw come in handy. When Ruby encounters a throw, it zips back up the call stack looking for a catch block with a matching symbol. When it finds it, Ruby unwinds the stack to that point and terminates the block. If the throw is called with the optional second parameter, that value is returned as the value of the catch.
That said, max's #any? suggestion is a better fit for this problem.
You can use multiple break statements.
For example:
xxx.delete_if do |x|
result = yyy.each do |y|
result2 = zzz.each do |z|
if x + y == z
break true
end
end
break true if result2 == true
end
result == true
end
However I would definitely avoid this in your particular situation.
You shouldn't be assigning variables to the result of each. Use map, reduce, select, reject, any?, all?, etc. instead
It makes more sense to use any? to accomplish the same purpose:
xxx.delete_if do |x|
yyy.any? do |y|
zzz.any? do |z|
x + y == z
end
end
end
I have a for loop that I would like to have increment forever.
My code:
for a in (0...Float::INFINITY).step(2)
puts a
end
Output:
0.0
2.0
4.0
Etc. Always with "#{a}.0"
Is there any way to express infinity as an integer, so that the output does not have a .0 at the end without preforming any operations on the contents of the loop?
Addendum
Could you also explain how your loop works? I am trying to find the most efficient solution, because since this loop will be iterating infinity, a few milliseconds shaved off will improve the performance greatly.
Also...
I will accept the solution that takes to shortest time to run to 1000000
According to benchmark both #Sefan and the while loop answers take the same ammount of timeFruity the while loop answers take a bit shorter, with the for loop answers in second, but the multiple loop do answers take far longer.
Since the reason why is out of the scope of this question, I have created another question that addresses why some loops are faster than others (https://stackoverflow.com/questions/33088764/peddle-to-the-metal-faster-loop-faster).
You can use Numeric#step without passing a limit:
0.step(by: 2) { |i| puts i }
Output:
0
2
4
6
...
You can also build your own Enumerator:
step2 = Enumerator.new do |y|
a = 0
loop do
y << a
a += 2
end
end
step2.each { |i| puts i }
You can use while true for that:
puts a = 0
puts a+=2 while true
BTW,
Is there any way to express infinity as an integer
NO
require 'bigdecimal'
(0..BigDecimal('Infinity')).step(2).each{ |n| puts n }
OR
require 'bigdecimal'
for a in (0...BigDecimal::INFINITY).step(2)
puts a
end
This is what the loop method is designed for. loop has no condition for which to run. It will run indefinitely and the only way to exit is to use the keyword break. (or raise a StopIteration)
a = 0
loop { puts a += 2}
This loop will be infinite as there is no break specified.
break can be specified very similarly to how the other answers use the while condition if needed:
a = 0
loop do
puts a += 2
break if a > 1_000_000
end
This loop will now exit once the value of a exceeds 1M.
That being said #Stefan's answer is more efficient as it does not store this integral value or have to perform any additional assignment but rather the number is simply yielded from an Enumerator and discarded it afterwards. The usefulness of this becomes more a matter of your implementation and purpose for this loop.
Try this:
arr = [0]
arr.cycle(1000000) { |i| puts arr[0] +=2 }
If you want infinite loop, then, don't pass any parameter to cycle
arr = [0]
arr.cycle { |i| puts arr[0] +=2 }
a = [-2]
puts a.unshift(a.shift+2) while 'loop forever'
I'm reading Programming with Ruby 2.0 and have a question
def my_while(cond, &body)
while cond.call
body.call
end
end
a=0
my_while -> { a < 3 } do
print a
a += 1
end #=> 0 1 2
I so the question is: why we can not use the method this way
def my_while(cond, &block)
while cond
block.call
end
end
a = 0
my_while (a<3) do
print a
a += 1
end #=> infinite loop
And actually how to use this function with condition (a<3) and a block parameter?
P.S. I saw this question but still can't comment there to ask!
In the last code sample, a<3 is evaluated when the line calling my_while is run.
As a has just been set to 0 in the line before, a<3 evaluates to true (0 being less than 3). This means that inside my_while, cond is set to true. It continues to be true because a<3 is never reevaluated, even though a is changed. Thus the while loop keeps looping.
Using the lambda and .calling it on every iteration of the loop ensure that the condition a<3 is evaluated for each loop, allowing the while loop to stop when a<3 no longer evaluates to true.
In Perl, there is an ability to break an outer cycle like this:
AAA: for my $stuff (#otherstuff) {
for my $foo (#bar) {
last AAA if (somethingbad());
}
}
(syntax may be wrong), which uses a loop label to break the outer loop from inside the inner loop. Is there anything similar in Ruby?
Consider throw/catch. Normally the outside loop in the below code will run five times, but with throw you can change it to whatever you like, breaking it in the process. Consider this perfectly valid ruby code:
catch (:done) do
5.times { |i|
5.times { |j|
puts "#{i} #{j}"
throw :done if i + j > 5
}
}
end
What you want is non-local control-flow, which Ruby has several options for doing:
Continuations,
Exceptions, and
throw/catch
Continuations
Pros:
Continuations are the standard mechanism for non-local control-flow. In fact, you can build any non-local control-flow (subroutines, procedures, functions, methods, coroutines, state machines, generators, conditions, exceptions) on top of them: they are pretty much the nicer twin of GOTO.
Cons:
Continuations are not a mandatory part of the Ruby Language Specification, which means that some implementations (XRuby, JRuby, Ruby.NET, IronRuby) don't implement them. So, you can't rely on them.
Exceptions
Pros:
There is a paper that proves mathematically that Exceptions can be more powerful than Continuations. IOW: they can do everything that continuations can do, and more, so you can use them as a replacement for continuations.
Exceptions are universally available.
Cons:
They are called "exceptions" which makes people think that they are "only for exceptional circumstances". This means three things: somebody reading your code might not understand it, the implementation might not be optimized for it (and, yes, exceptions are godawful slow in almost any Ruby implementation) and worst of all, you will get sick of all those people constantly, mindlessly babbling "exceptions are only for exceptional circumstances", as soon as they glance at your code. (Of course, they won't even try to understand what you are doing.)
throw/catch
This is (roughly) what it would look like:
catch :aaa do
stuff.each do |otherstuff|
foo.each do |bar|
throw :aaa if somethingbad
end
end
end
Pros:
The same as exceptions.
In Ruby 1.9, using exceptions for control-flow is actually part of the language specification! Loops, enumerators, iterators and such all use a StopIteration exception for termination.
Cons:
The Ruby community hates them even more than using exceptions for control-flow.
No, there isn't.
Your options are:
put the loop in a method and use return to break from the outer loop
set or return a flag from the inner loop and then check that flag in the outer loop and break from it when the flag is set (which is kind of cumbersome)
use throw/catch to break out of the loop
while c1
while c2
do_break=true
end
next if do_break
end
or "break if do_break" depending on what you want
Perhaps this is what you want? (not tested)
stuff.find do |otherstuff|
foo.find do
somethingbad() && AAA
end
end
The find method keeps looping until the block returns a non null value or the end of the list is hit.
Wrapping an internal method around the loops could do the trick
Example:
test = [1,2,3]
test.each do |num|
def internalHelper
for i in 0..3
for j in 0..3
puts "this should happen only 3 times"
if true
return
end
end
end
end
internalHelper
end
Here you can do a check inside any of the for loops and return from the internal method once a condition is met.
I know I will regret this in the morning but simply using a while loop could do the trick.
x=0
until x==10
x+=1
y=0
until y==10
y+=1
if y==5 && x==3
x,y=10,10
end
end
break if x==10
puts x
end
The if y==5 && x==3 is only an example of an expression turning true.
You may consider adding a flag, which is set inside the inner loop, for controlling the outer loop.
'next' the outer loop
for i in (1 .. 5)
next_outer_loop = false
for j in (1 .. 5)
if j > i
next_outer_loop = true if j % 2 == 0
break
end
puts "i: #{i}, j: #{j}"
end
print "i: #{i} "
if next_outer_loop
puts "with 'next'"
next
end
puts "withOUT 'next'"
end
'break' the outer loop
for i in (1 .. 5)
break_outer_loop = false
for j in (1 .. 5)
if j > i
break_outer_loop = true if i > 3
break
end
puts "i: #{i}, j: #{j}"
end
break if break_outer_loop
puts "i: #{i}"
end