Ruby while syntax

ruby

Solution

Is it because the `do` of the `while` syntax is just syntaxic sugar and as nothing to do with the `do` of a block?

More or less, yes. It's not syntactic sugar, it's simply a built-in language construct, like `def` or `class`, as @meagar already wrote.

It has nothing to do with the `do` of a block, except that keywords are expensive and so reusing keywords makes sense. (By "expensive" I mean that they limit the programmer in his expressiveness.)

In a `while` loop, there are two ways to separate the block from the condition:

- the `do` keyword and

- an expression separator.

There are, in turn, two different expression separators in Ruby:

- the semicolon `;` and

- a newline

So, all three of the following are valid:

while i = a.shift do puts i end # do

while i = a.shift; puts i end   # semicolon

while i = a.shift
  puts i end                    # newline

[Obviously, that last one wouldn't be written that way, you would put the `end` on a new line, dedented to match the `while`. I just wanted to demonstrate what is the minimum needed to separate the parts of the `while` loop.]

By the way: it is highly un-idiomatic to put the condition in parentheses. There's also a lot of superfluous semicolons in your code. And the variable name `i` is usually reserved for an index, not an element. (I normally use `el` for generic elements, but I much prefer more semantic names.)

It is also highly un-idiomatic to iterate a collection manually. Your code would be much better written as

a.each(&method(:puts)).clear

Not only is it much easier to understand what this does (print all elements of the array and delete all items from it), it is also much easier to write (there is no way to get the termination condition wrong, or screw up any assignments). It also happens to be more efficient: your version is Θ(n2), this one is Θ(n).

And actually, that's not really how you would write it, either, because `Kernel#puts` already implements that behavior, anyway. So, what you would really write is this

puts a
a.clear

or maybe this

a.tap(&method(:puts)).clear

[Note: this very last one is not 100% equivalent. It prints a newline for an empty array, all the other ones print nothing.]

Simple. Clear. Concise. Expressive. Fast.

Compare that to:

while (i = a.shift) do; puts i ; end

I actually had to run that multiple times to be 100% clear what it does.

Problem

Does anybody why I can write this: ``` ruby-1.8.7-p302 > a = %w( a b c) => ["a", "b", "c"] ruby-1.8.7-p302 > while (i = a.shift) do; puts i ; end a b c => nil ``` Which looks like passing a block to while. And not: ``` while(i = a.shift) { puts i; } ``` Is it because the "do" of the while syntax is just syntaxic sugar and as nothing to do with the "do" of a block?

Original source