Do/end vs braces

Hi all,

It looks to me like when you use an iterator (each for instance), you can make
the block either from a do/end pair, or from curly braces. All things being
equal, I'd greatly prefer to use do/end. Are there any differences in runtime
speed, capabilities, or Rubyness?

#!/usr/bin/ruby
(1..4).each do |i|
  puts i
end
print "================\n"
(1..4).each { |i|
  puts i
}

Output:

[slitt@mydesk slitt]$ ./test.rb
1
2
3
4

···

================
1
2
3
4
[slitt@mydesk slitt]$

Thanks

SteveT

Steve Litt
http://www.troubleshooters.com
slitt@troubleshooters.com

Typically,

5.times { |i| puts i }

5.times do |i|
  puts i
end

Generally people save do .. end for multiline stuff. Don't think
there's a difference in speed.

Sometimes people who use vim use only braces for vim's matching
capabilities, although didn't someone fix that for do..end?

···

On 12/8/05, Steve Litt <slitt@earthlink.net> wrote:

Hi all,

It looks to me like when you use an iterator (each for instance), you can make
the block either from a do/end pair, or from curly braces. All things being
equal, I'd greatly prefer to use do/end. Are there any differences in runtime
speed, capabilities, or Rubyness?

There is a subtle difference in binding precedence. I wrote about that in this message:

http://groups.google.com/group/comp.lang.ruby/msg/b67b116e49473e11

Hope that helps.

James Edward Gray II

···

On Dec 8, 2005, at 8:09 AM, Steve Litt wrote:

Are there any differences in runtime speed, capabilities, or Rubyness?

Steve Litt wrote:

Hi all,

It looks to me like when you use an iterator (each for instance), you can make the block either from a do/end pair, or from curly braces. All things being equal, I'd greatly prefer to use do/end. Are there any differences in runtime speed, capabilities, or Rubyness?

There's a slight difference in how they're parsed.

   foo bar { block }

is the same as

   foo(bar { block })

while

   foo bar do
     block
   end

is the same as

   foo(bar) do
     block
   end

or

   foo(bar) { block }

but it's only an issue when you leave out the parantheses. The styling convention is that the curly braces are used for one-line blocks and the do..end for multi-line blocks

   foo { make_me_a_bar }
   bar do
     foo = Foo.new
     pass_the_foo(foo)
     do_something_else
   end

Cheers,
Daniel

Quoting Joe Van Dyk joevandyk-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org:

5.times { |i| puts i }

5.times do |i|
puts i
end

Generally people save do … end for multiline stuff. Don’t think
there’s a difference in speed.

I can promise there’s no speed difference. They both parse to the
same thing:

(iter
(call
(lit #<5>) times)
(dasgn_curr i)
(fcall puts
(array
(dvar i))))

(iter
(call
(lit #<5>) times)
(dasgn_curr i)
(fcall puts
(array
(dvar i))))

However, {} and do…end are not totally interchangable as syntax.
These are all equivalent:

obj.meth( 1, 2 ) { |i|
puts i
}

obj.meth( 1, 2 ) do |i|
puts i
end

obj.meth 1, 2 do |i|
puts i
end

But this will net you a parse error (‘2’ is not a valid method
name):

obj.meth 1, 2 { |i|
puts i
}

And these two parse equivalently:

obj.meth 1, zog { |i|
puts i
}

obj.meth( 1, zog { |i| puts i } )

Think of {} as being more “clingy” than do…end.

Basically, {} has higher precedence than do…end, just as (among
otherwise equivalent operators) && has higher precedence than
‘and’, and || has higher precedence than ‘or’.

I’m sure Ter hates Ruby now. :slight_smile:

-mental

But this will net you a parse error (‘2’ is not a valid method
name):

obj.meth 1, 2 { |i|
puts i
}

Yikes! Not sure what’s up there. What does the {…} bind to then?
The 2? If so, why is 2 considered a method.

And these two parse equivalently:

obj.meth 1, zog { |i|
puts i
}

obj.meth( 1, zog { |i| puts i } )

Think of {} as being more “clingy” than do…end.

That I can parse mentally. :slight_smile:

Basically, {} has higher precedence than do…end, just as (among
otherwise equivalent operators) && has higher precedence than
‘and’, and || has higher precedence than ‘or’.

I’m sure Ter hates Ruby now. :slight_smile:

Well, I am trying to ignore edge cases while I learn the language :wink:
Starting with the warts is probably not a good idea :wink:

Ter

···

On Dec 8, 2005, at 7:27 AM, mental-uFjFfPRxV21eoWH0uzbU5w@public.gmane.org wrote:

Another convention some use is that { ... } are for the times when you care about the return value and do ... end is for when you're interested in the side effects. For example:

sum = [1, 2, 3].inject { |sum, n| sum + n } # return value

File.open("total.txt", "w") do |file| # side effects
   file.puts sum
end

James Edward Gray II

···

On Dec 8, 2005, at 8:13 AM, Joe Van Dyk wrote:

On 12/8/05, Steve Litt <slitt@earthlink.net> wrote:

Hi all,

It looks to me like when you use an iterator (each for instance), you can make
the block either from a do/end pair, or from curly braces. All things being
equal, I'd greatly prefer to use do/end. Are there any differences in runtime
speed, capabilities, or Rubyness?

Typically,

5.times { |i| puts i }

5.times do |i|
  puts i
end

Generally people save do .. end for multiline stuff. Don't think
there's a difference in speed.

Binds to the 2, yes. But then it fails to match, as 2 isn’t a method.
It should also fail if there were an lvar rather than a private method
call in that position.

That’s an interesting question actually … how it matches enough to
bind, but not enough to succeed.

-mental

···

On Thu, 2005-12-08 at 14:44 -0800, Terence Parr wrote:

On Dec 8, 2005, at 7:27 AM, mental-uFjFfPRxV21eoWH0uzbU5w@public.gmane.org wrote:

But this will net you a parse error (‘2’ is not a valid method
name):

obj.meth 1, 2 { |i|
puts i
}

Yikes! Not sure what’s up there. What does the {…} bind to then?
The 2? If so, why is 2 considered a method.

matchit.vim

martin

···

Joe Van Dyk <joevandyk@gmail.com> wrote:

Sometimes people who use vim use only braces for vim's matching
capabilities, although didn't someone fix that for do..end?

Steve Litt wrote:
> Hi all,
>
> It looks to me like when you use an iterator (each for instance), you can
> make the block either from a do/end pair, or from curly braces. All
> things being equal, I'd greatly prefer to use do/end. Are there any
> differences in runtime speed, capabilities, or Rubyness?

There's a slight difference in how they're parsed.

   foo bar { block }

is the same as

   foo(bar { block })

while

   foo bar do
     block
   end

is the same as

   foo(bar) do
     block
   end

or

   foo(bar) { block }

but it's only an issue when you leave out the parantheses.

Except I can't put in the parentheses:

#!/usr/bin/ruby
my_array = ["alpha", "beta", "gamma"]
puts (my_array.collect do
  >word>
  word.capitalize
end)

Output:
[slitt@mydesk slitt]$ ./test.rb
./test.rb:3: syntax error
./test.rb:6: syntax error
[slitt@mydesk slitt]$

Thanks

SteveT

···

On Thursday 08 December 2005 10:07 am, Daniel Schierbeck wrote:

The styling
convention is that the curly braces are used for one-line blocks and the
do..end for multi-line blocks

   foo { make_me_a_bar }
   bar do
     foo = Foo.new
     pass_the_foo(foo)
     do_something_else
   end

Cheers,
Daniel

--
Steve Litt

slitt@troubleshooters.com

Joe Van Dyk <joevandyk@gmail.com> writes:

Generally people save do .. end for multiline stuff. Don't think

I am not sure why Pickaxe mentioned this convention that is based
on LOC factor rather than one that is based on intent.

Basing it on LOC is silly, IMO. It really is more suitable for
languages that are white-space sensitive.

Consider you wrote:

foo.bar {|a| zoo(a)}

Oh, further down the road you realise that it is valuable to log the
value of a or perhaps you are simply reformatting your code.

foo.bar {|a|
  log.debug(a)
  zoo(a)
}

Whoops, that's out of the convention. Your eyes are itchy at that, so
you spent some time fixing it like:

foo.bar do |a|
   log.debug(a)
   zoo(a)
end

Later on, you decided that logging the value of a is frivolous, so you
changed it again:

foo.bar do |a| zoo(a) end

That violates the convention as well, so you do yet another do-end to
{} transformation

foo.bar {|a| zoo(a)}

All that works is just for one method call. Imagine if there are more,
and there are likely to be more.

Basing it on intent (return value or side-effect or what-have-you)
seems a more rational guideline. For certain, that would make code
reformatting a more pleasurable exercise.

YS.

Joe Van Dyk wrote:

Generally people save do .. end for multiline stuff. Don't think
there's a difference in speed.

I use do .. end always. I find it easier to read, and more in line with
the other foo .. end structures in ruby.

···

--
Neil Stevens - neil@hakubi.us

'A republic, if you can keep it.' -- Benjamin Franklin

Good point. And also use { ... } if you want to do crazy chains like

[1, 2, 3].collect { |a| i * a }.each { |a| puts a }

Joe

···

On 12/8/05, James Edward Gray II <james@grayproductions.net> wrote:

On Dec 8, 2005, at 8:13 AM, Joe Van Dyk wrote:

> On 12/8/05, Steve Litt <slitt@earthlink.net> wrote:
>> Hi all,
>>
>> It looks to me like when you use an iterator (each for instance),
>> you can make
>> the block either from a do/end pair, or from curly braces. All
>> things being
>> equal, I'd greatly prefer to use do/end. Are there any differences
>> in runtime
>> speed, capabilities, or Rubyness?
>
> Typically,
>
> 5.times { |i| puts i }
>
> 5.times do |i|
> puts i
> end
>
> Generally people save do .. end for multiline stuff. Don't think
> there's a difference in speed.

Another convention some use is that { ... } are for the times when
you care about the return value and do ... end is for when you're
interested in the side effects. For example:

sum = [1, 2, 3].inject { |sum, n| sum + n } # return value

File.open("total.txt", "w") do |file| # side effects
   file.puts sum
end

Except I can't put in the parentheses:

#!/usr/bin/ruby
my_array = ["alpha", "beta", "gamma"]
puts (my_array.collect do
        >word>
        word.capitalize
end)

Output:
[slitt@mydesk slitt]$ ./test.rb
./test.rb:3: syntax error
./test.rb:6: syntax error

Take out the space between puts and the open paren:

~$ cat test.rb
my_array = ["alpha", "beta", "gamma"]
puts(my_array.collect do
  >word>
  word.capitalize
end)

~$ ruby test.rb
Alpha
Beta
Gamma

Jacob Fugal

···

On 12/8/05, Steve Litt <slitt@earthlink.net> wrote:

Yohanes Santoso wrote:

Joe Van Dyk <joevandyk@gmail.com> writes:

Generally people save do .. end for multiline stuff. Don't think
   
I am not sure why Pickaxe mentioned this convention that is based
on LOC factor rather than one that is based on intent.

Basing it on LOC is silly, IMO. It really is more suitable for
languages that are white-space sensitive.

Consider you wrote:

foo.bar {|a| zoo(a)}

Oh, further down the road you realise that it is valuable to log the
value of a or perhaps you are simply reformatting your code.

foo.bar {|a|
log.debug(a)
zoo(a)
}

Whoops, that's out of the convention. Your eyes are itchy at that, so
you spent some time fixing it like:

foo.bar do |a|
  log.debug(a)
  zoo(a)
end

Later on, you decided that logging the value of a is frivolous, so you
changed it again:

foo.bar do |a| zoo(a) end

That violates the convention as well, so you do yet another do-end to
{} transformation

foo.bar {|a| zoo(a)}

All that works is just for one method call. Imagine if there are more,
and there are likely to be more.

Basing it on intent (return value or side-effect or what-have-you)
seems a more rational guideline. For certain, that would make code
reformatting a more pleasurable exercise.

YS.

In the end doesn't it all come up to a matter of preference? I prefer the curly braces, others prefer do..end. In my book its a matter of versatility of the language. Which in turn is a verry nice feature, IMHO.

Daniel C.

Yohanes-

  I have been using this link[1] for converting between do .. end and {..} in vim and it works great. Thought I would share.

Cheers-
-Ezra Zygmuntowicz
Yakima Herald-Republic
WebMaster

509-577-7732
ezra@yakima-herald.com

[1] http://eigenclass.org/hiki.rb?Ruby+block+conversion+macros+for+Vim

···

On Dec 9, 2005, at 6:59 AM, Yohanes Santoso wrote:

Joe Van Dyk <joevandyk@gmail.com> writes:

Generally people save do .. end for multiline stuff. Don't think

Oops, that first 'i' should be an 'a'.

···

On 12/8/05, Joe Van Dyk <joevandyk@gmail.com> wrote:

On 12/8/05, James Edward Gray II <james@grayproductions.net> wrote:
> On Dec 8, 2005, at 8:13 AM, Joe Van Dyk wrote:
>
> > On 12/8/05, Steve Litt <slitt@earthlink.net> wrote:
> >> Hi all,
> >>
> >> It looks to me like when you use an iterator (each for instance),
> >> you can make
> >> the block either from a do/end pair, or from curly braces. All
> >> things being
> >> equal, I'd greatly prefer to use do/end. Are there any differences
> >> in runtime
> >> speed, capabilities, or Rubyness?
> >
> > Typically,
> >
> > 5.times { |i| puts i }
> >
> > 5.times do |i|
> > puts i
> > end
> >
> > Generally people save do .. end for multiline stuff. Don't think
> > there's a difference in speed.
>
> Another convention some use is that { ... } are for the times when
> you care about the return value and do ... end is for when you're
> interested in the side effects. For example:
>
> sum = [1, 2, 3].inject { |sum, n| sum + n } # return value
>
> File.open("total.txt", "w") do |file| # side effects
> file.puts sum
> end

Good point. And also use { ... } if you want to do crazy chains like

[1, 2, 3].collect { |a| i * a }.each { |a| puts a }

Confirmed! Thanks Jacob. This is the first time I've seen Ruby conflict with
the Rule of Least Surprise (http://www.faqs.org/docs/artu/ch11s01.html\).

Is there any chance of a Ruby change so as not to require the paren to be
flush up against the function name?

Thanks

SteveT

Steve Litt

slitt@troubleshooters.com

···

On Thursday 08 December 2005 06:06 pm, Jacob Fugal wrote:

On 12/8/05, Steve Litt <slitt@earthlink.net> wrote:
> Except I can't put in the parentheses:
>
> #!/usr/bin/ruby
> my_array = ["alpha", "beta", "gamma"]
> puts (my_array.collect do
>
> >word>
>
> word.capitalize
> end)
>
> Output:
> [slitt@mydesk slitt]$ ./test.rb
> ./test.rb:3: syntax error
> ./test.rb:6: syntax error

Take out the space between puts and the open paren:

I find the different precedence useful.

If I have a method call written without parens, which is common
in 'imperative style' ruby, it is very useful to have the do/block
not bind to the last argument. Such as rake tasks:

task :test do
   ruby "test/unittest.rb"
end

···

On Dec 9, 2005, at 10:21 AM, Daniel Cedilotte wrote:

In the end doesn't it all come up to a matter of preference? I prefer the curly braces, others prefer do..end. In my book its a matter of versatility of the language. Which in turn is a verry nice feature, IMHO.

Ezra Zygmuntowicz <ezra@yakimaherald.com> writes:

Yohanes-

  I have been using this link[1] for converting between do
.. end and {..} in vim and it works great. Thought I would share.

Thank you for the thought, although I can't use that as I'm using
emacs, not vim. I also have a similar function that does that in
emacs, but that's beside my point.

My point is, that Pickaxe is recommending a convention that compels
the programmer to do something when the LOC changes, unexpected.

They could have recommended a convention that is not based on LOC.

YS.