=> nil
2 http://rubyurl.com/12y
I think what Martin wants is a bottom-tested loop, but I don’t
believe Ruby has that. until is a top-tested loop just like while.
The only way I know to get bottom-tested behavior is this.
I think it makes “until” less useful. Why would anyone want this?
def print_all(arr)
until arr.empty?
print “>”, arr.shift, “<\n”
end
end
Try this with post checked conditions and an empty array as argument.
Language designers seem to think otherwise. You described the logic of
loops with prechecked conditions which abound in programming languages -
for decades already.
irb(main):001:0> i = 0
=> 0
irb(main):002:0> until (i+=1) >5 do
irb(main):003:1* p i
irb(main):004:1> end
1
2
3
4
5
=> nil
irb(main):005:0>
Because i is incremented at each passage of the loop, before it starts
the
loop if i is 1 when i+=1 is evaluated it becomes 2 when you try to print
it.
It’s nether a bug nore a feature IMHO. If you do want to have a bottom
tested loop much as David just said;
irb(main):001:0> i = 1
=> 0
irb(main):002:0> begin
irb(main):003:1* puts i
irb(main):004:1> end until (i+=1)>5
1
2
3
4
5
=> nil
irb(main):005:0>
Works fine with i equal to 1 before starting the loop -> because it
prints i
before it is changed when i+=1 is evaluated before the second pass
through the
block is made.
If you do find a need to use a test at the bottom instead of the top,
you
should ether 0.) Keep the body of the loop short or 1.) Make it explicit
to
the reader that a loop is starting.
Generally I avoid code like that because If six months later you don’t
know
(or that a loop is starting until you see the until expression, it’s
more
trouble then following a more conventional style.
If you ask me, if the body of a loop grows to long that you don’t
remember why
the loop was executing when you hit the end of it, thats a problem in of
it
self any way
Thats just confusing. Why does that work different then “do_stuff until
condition”.
Consider this:
if foo() then
bar()
end
bar() if foo()
In both cases foo() is called before bar(), even though in one of the
cases it appears later in source code. The ‘if’ can go in different
places. Similarly with while and until. Now, sometimes you (both the
general populace and you in particular) want to evaluate after the
first iteration. For such cases we need a different syntax.
Do you have a better suggestion for how to differentiate between
evaluate-first and evaluate-after-one-iteration, that is also
consistent with if/unless?
3
irb(main):005:0> i = 1
What other behavior would you want, and why?
end
You can do:
begin
# do stuff
end until condition
David
Thats just confusing. Why does that work different then “do_stuff until
condition”.
I’m used to do things like this:
a= n
until (a*= 3.0)<=450.0
do stuff
end
I think it is more readable. You get the start value, the incrementer
and the stop condition nicely grouped together. You also get more
effective code, if the penalty for evaluating the condition is high. I’m
not a native english speaker, but I think it feels more in line with
natural languages as well as “mathematical language”. And it’s a lot
more like how you do things in real life.
Using the loop method would mean that I had to introduce a new scope.
Which, sometimes, means that I have to remember to “declare” a lot of
variables outside that scope. Even those that are never used. A lot of
unecessary code attract bugs like sugar. I like Ruby’s block iterators,
but many times it is wrong to use them.
In the repeat…until (our own version of the until) it does things then
checks for the break condition. In the while loop, it checks then does
things.
In our example here, we have:
i=1
until (i+=1)>5
p i
end
The question is, when does it evaluate? When I learned basic algebra, I
was taught to figure out the things inside the parens first. I think
that is what is done here. Therefore, the first thing done is to
increment, then evaluate.
To get what you seem to want, you would need to evaluate before you
increment, which would look more like this:
i = 1
until i>5
p i
i+=1
end
You were telling it to increment, THEN evaluate. That being the case,
it would not be a bug. IMHO
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.