do/end vs braces

S

Steve Litt

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
(e-mail address removed)
 
J

Joe Van Dyk

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 bei= ng
equal, I'd greatly prefer to use do/end. Are there any differences in run= time
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.

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

James Edward Gray II

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

James Edward Gray II
 
J

Joe Van Dyk

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 =3D [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 }

Joe
 
J

Joe Van Dyk

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 =3D [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 }

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

Daniel Schierbeck

Steve said:
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
 
M

Martin DeMello

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

matchit.vim

martin
 
S

Steve Litt

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
 
J

Jacob Fugal

Except I can't put in the parentheses:

#!/usr/bin/ruby
my_array =3D ["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 =3D ["alpha", "beta", "gamma"]
puts(my_array.collect do
|word|
word.capitalize
end)

~$ ruby test.rb
Alpha
Beta
Gamma

Jacob Fugal
 
S

Steve Litt

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:

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
http://www.troubleshooters.com
(e-mail address removed)
 
P

Paul Sanchez

Steve Litt said:
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:

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?

Interestingly, it worked for me with a space or without the parens when
I did the puts as a one-liner:

puts my_array.collect {|word| word.capitalize}

or

puts (my_array.collect {|word| word.capitalize})

--paul
 
S

Steve Litt

Steve Litt said:
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:

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?

Interestingly, it worked for me with a space or without the parens when
I did the puts as a one-liner:

puts my_array.collect {|word| word.capitalize}

or

puts (my_array.collect {|word| word.capitalize})

Hi Paul,

It works as expected with braces, but not with do/end.

Thanks

SteveT

Steve Litt
http://www.troubleshooters.com
(e-mail address removed)
 
M

MenTaLguY

--=-JfNt3LaeWOiqzgRAPbN+
Content-Type: text/plain
Content-Transfer-Encoding: quoted-printable

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

Egh... I think that'd introduce more ambiguities into the grammar...
it's pretty bad that way already.

-mental

--=-JfNt3LaeWOiqzgRAPbN+
Content-Type: application/pgp-signature; name=signature.asc
Content-Description: This is a digitally signed message part

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)

iD8DBQBDmSXrcUNIGiXCc4MRAm9PAJoDQrag9cb9RCLTGy5WwrYyuuxR8gCgr9FE
oFnJfon4c3JZ5685nCJpDqw=
=ps/h
-----END PGP SIGNATURE-----

--=-JfNt3LaeWOiqzgRAPbN+--
 
L

Logan Capaldo

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:

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

Doubtful. Matz. has been trying to move in the opposite direction:
irb(main):003:0> puts ("Hello", "World")
(irb):3: warning: don't put space before argument parentheses
Hello
World
=> nil
 
C

Chad Perrin

Doubtful. Matz. has been trying to move in the opposite direction:
irb(main):003:0> puts ("Hello", "World")
(irb):3: warning: don't put space before argument parentheses
Hello
World
=> nil

I'd be happy with it either way, as long as it's consistent.
 
D

daz

Chad said:
I'd be happy with it either way, as long as it's consistent.


Without space, it's consistent.
It's not always what we want it to mean, though.

Take this example (with which I frequently inconvenience myself):

#-----------------------------------------------------
(0..5).map do |n|
10*n
end
#-----------------------------------------------------

* I want to see the result, so I prepend "p ":

#-----------------------------------------------------
p (0..5).map do |n|
10*n
end
#=> C:/TEMP/rb284.TMP:1: warning: (...) interpreted as grouped expression
# [- Okay, that's what it is.]
#=> [0, 1, 2, 3, 4, 5]
# [- But that's not what I wanted. The block binds to method #p
# - the argument to #p is ((0..5).map) - an Array (in Ruby 1.8.2)
#-----------------------------------------------------

* Remove the space after p

#-----------------------------------------------------
p(0..5).map do |n|
10*n
end
#=> 0..5
# [Oh, no !]
#=> C:/TEMP/rb284.TMP:1: undefined method `map' for nil:NilClass (NoMethodError)
# [Aargh!]
#-----------------------------------------------------

* Parenthesise correctly but "uglily" ;))

#-----------------------------------------------------
p((0..5).map do |n|
10*n
end)
#=> [0, 10, 20, 30, 40, 50] # no problem at all
#-----------------------------------------------------

* But we don't need to do any of those.
* From the initial example, just prepend "<var> = "
and there's no "binding" issue ...

#-----------------------------------------------------
r = (0..5).map do |n|
10*n
end
p r #=> [0, 10, 20, 30, 40, 50]
#-----------------------------------------------------

IMHO, it's our problem, not Ruby's.
The problem could appear in many places but, for me,
it's almost always when prepending p, puts or print.

Things could be a lot worse than this ;)


daz
 
D

Daniel Cedilotte

Yohanes said:
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.
 
G

gwtmp01

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.

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top