Forum: Ruby do/end vs braces

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
1b62a85b59ccab03b84ee5ec378f75b4?d=identicon&s=25 slitt (Guest)
on 2005-12-08 15:39
(Received via mailing list)
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
38a8230ed3d5c685558b4f0aad3fc74b?d=identicon&s=25 joevandyk (Guest)
on 2005-12-08 15:44
(Received via mailing list)
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.

Sometimes people who use vim use only braces for vim's matching
capabilities, although didn't someone fix that for do..end?
4299e35bacef054df40583da2d51edea?d=identicon&s=25 James Gray (bbazzarrakk)
on 2005-12-08 15:48
(Received via mailing list)
On Dec 8, 2005, at 8:13 AM, Joe Van Dyk wrote:

>
> 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
4299e35bacef054df40583da2d51edea?d=identicon&s=25 James Gray (bbazzarrakk)
on 2005-12-08 15:52
(Received via mailing list)
On Dec 8, 2005, at 8:09 AM, Steve Litt wrote:

> 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/...

Hope that helps.

James Edward Gray II
38a8230ed3d5c685558b4f0aad3fc74b?d=identicon&s=25 joevandyk (Guest)
on 2005-12-08 15:56
(Received via mailing list)
On 12/8/05, James Edward Gray II <james@grayproductions.net> wrote:
> >> in runtime
> > Generally people save do .. end for multiline stuff.  Don't think
> 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
38a8230ed3d5c685558b4f0aad3fc74b?d=identicon&s=25 joevandyk (Guest)
on 2005-12-08 15:56
(Received via mailing list)
On 12/8/05, Joe Van Dyk <joevandyk@gmail.com> wrote:
> > >> equal, I'd greatly prefer to use do/end. Are there any differences
> > >
> >    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'.
5da4c52f43677f395aff5bde775593c2?d=identicon&s=25 Daniel Schierbeck (dasch)
on 2005-12-08 16:08
(Received via mailing list)
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
912c61d9da47754de7039f4271334a9f?d=identicon&s=25 mental (Guest)
on 2005-12-08 16:29
(Received via mailing list)
Quoting Joe Van Dyk <joevandyk@gmail.com>:

> 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. :)

-mental
2cf6d8e639314abd751f83a72e9a2ac5?d=identicon&s=25 martindemello (Guest)
on 2005-12-08 18:29
(Received via mailing list)
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?

matchit.vim

martin
1b62a85b59ccab03b84ee5ec378f75b4?d=identicon&s=25 slitt (Guest)
on 2005-12-08 23:40
(Received via mailing list)
On Thursday 08 December 2005 10:07 am, Daniel Schierbeck wrote:
>    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
Cff9eed5d8099e4c2d34eae663aae87e?d=identicon&s=25 lukfugl (Guest)
on 2005-12-09 00:09
(Received via mailing list)
On 12/8/05, Steve Litt <slitt@earthlink.net> wrote:
> [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
1b62a85b59ccab03b84ee5ec378f75b4?d=identicon&s=25 slitt (Guest)
on 2005-12-09 02:11
(Received via mailing list)
On Thursday 08 December 2005 06:06 pm, Jacob Fugal wrote:
> > 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
slitt@troubleshooters.com
B699ba171b16324e5d1aa4bde8e62a24?d=identicon&s=25 paul (Guest)
on 2005-12-09 02:44
(Received via mailing list)
In article <200512082012.03896.slitt@earthlink.net>,
 Steve Litt <slitt@earthlink.net> wrote:

> > >         word.capitalize
> 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
1b62a85b59ccab03b84ee5ec378f75b4?d=identicon&s=25 slitt (Guest)
on 2005-12-09 03:24
(Received via mailing list)
On Thursday 08 December 2005 08:42 pm, Paul Sanchez wrote:
> > > >
> > > Take out the space between puts and the open paren:
>
> 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
slitt@troubleshooters.com
912c61d9da47754de7039f4271334a9f?d=identicon&s=25 mental (Guest)
on 2005-12-09 07:36
(Received via mailing list)
On Fri, 2005-12-09 at 10:11 +0900, Steve Litt wrote:
> Is there any chance of a Ruby change so as not to require the paren to be
> 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
E34b5cae57e0dd170114dba444e37852?d=identicon&s=25 logancapaldo (Guest)
on 2005-12-09 09:02
(Received via mailing list)
On Dec 8, 2005, at 8:11 PM, Steve Litt wrote:

>>>         word.capitalize
> conflict with
>
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
Fd22ee3cfc7dac283ce8e451af324f7d?d=identicon&s=25 perrin (Guest)
on 2005-12-09 09:14
(Received via mailing list)
On Fri, Dec 09, 2005 at 05:00:13PM +0900, Logan Capaldo wrote:
>
> 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.

--
Chad Perrin [ CCD CopyWrite | http://ccd.apotheon.org ]

unix virus: If you're using a unixlike OS, please forward
this to 20 others and erase your system partition.
Dce0999389d102f9a313af625375304c?d=identicon&s=25 dooby (Guest)
on 2005-12-09 11:54
(Received via mailing list)
Chad Perrin wrote:
> 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
1b62a85b59ccab03b84ee5ec378f75b4?d=identicon&s=25 slitt (Guest)
on 2005-12-09 13:37
(Received via mailing list)
On Friday 09 December 2005 03:12 am, Chad Perrin wrote:
> On Fri, Dec 09, 2005 at 05:00:13PM +0900, Logan Capaldo wrote:
> > 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.

Yes, at least the warning would get me out of the habit ast.

SteveT

Steve Litt
http://www.troubleshooters.com
slitt@troubleshooters.com
B000982a23d5c6a34292902caf225dd7?d=identicon&s=25 ysantoso-rubytalk (Guest)
on 2005-12-09 16:00
(Received via mailing list)
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.
5a5dbce467c5b43ad8fc81209db607b3?d=identicon&s=25 daniel.cedilotte (Guest)
on 2005-12-09 16:24
(Received via mailing list)
Yohanes Santoso wrote:

>
>foo.bar {|a|
>end
>foo.bar {|a| zoo(a)}
>
>
>
>
>
>
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.
E7559e558ececa67c40f452483b9ac8c?d=identicon&s=25 gwtmp01 (Guest)
on 2005-12-09 17:38
(Received via mailing list)
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.

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
45196398e9685000d195ec626d477f0e?d=identicon&s=25 transfire (Guest)
on 2005-12-09 17:58
(Received via mailing list)
I've sometimes thought, "man wouldn't it be tight if we had some sort
of vertical brackets?"

  task :test .--.
    ruby "test/unittest.rb"
  '--'

:-) T.
3c155ef399326d533efc2eb91ac992e5?d=identicon&s=25 neil (Guest)
on 2005-12-09 18:11
(Received via mailing list)
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
Fd22ee3cfc7dac283ce8e451af324f7d?d=identicon&s=25 perrin (Guest)
on 2005-12-09 19:26
(Received via mailing list)
On Fri, Dec 09, 2005 at 07:52:36PM +0900, daz wrote:
> * I want to see the result, so I prepend "p ":
> #-----------------------------------------------------
> #  [Aargh!]
> #-----------------------------------------------------

There's a problem of understanding there, not of consistency.  When you
butt the parentheses up against a method like that, you're basically
saying that the method's parameters are exactly what's in the
parentheses -- no more and no less.  At least, that's what seems logical
to me.  When you separate it with a space, parentheses make for a great
way to set precedence within the larger statement while still allowing
the whole thing to be your set of method parameters (or, perhaps more
accurately, let the whole thing return your method parameter(s)).

The problem that arises for me isn't that the meaning of an arrangement
of character on the screen is different from another arrangement: it's
that you can have the parentheses flush with the method or not and it
works the same either way, unless it doesn't.  It just seems to me that,
for consistency's sake, what you use as block delimiters shouldn't
affect whether parentheses for method parameters have to be flush with
the method name itself.

I can do just fine with the way it is, but it seems that it shouldn't
require such a convoluted understanding of how the language behaves.
Ruby, in other ways, conforms very well to the "rule of least surprise";
why should that change in this one instance?

Then again, maybe that's just me.

--
Chad Perrin [ CCD CopyWrite | http://ccd.apotheon.org ]

unix virus: If you're using a unixlike OS, please forward
this to 20 others and erase your system partition.
8e44c65ac5b896da534ef2440121c953?d=identicon&s=25 ezra (Guest)
on 2005-12-09 19:26
(Received via mailing list)
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
>
>

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
http://yakimaherald.com
509-577-7732
ezra@yakima-herald.com


[1] http://eigenclass.org/hiki.rb?Ruby+block+conversio...
B000982a23d5c6a34292902caf225dd7?d=identicon&s=25 ysantoso-rubytalk (Guest)
on 2005-12-09 20:48
(Received via mailing list)
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.
Cff9eed5d8099e4c2d34eae663aae87e?d=identicon&s=25 lukfugl (Guest)
on 2005-12-09 22:17
(Received via mailing list)
On 12/9/05, Chad Perrin <perrin@apotheon.com> wrote:
> ...  It just seems to me that,
> for consistency's sake, what you use as block delimiters shouldn't
> affect whether parentheses for method parameters have to be flush with
> the method name itself.

1) Choice of block delimiters has no more influence on whether
parentheses for method parameters have to be flush with the method
name itself than choosing 'and' vs. '&&' does... and that is none.

In my ruby (1.8.2, 2005-04-11, i386-linux) I don't even get the
warning about not putting spaces in. As far as I can tell, putting a
space between the method and the open parenthesis is equivalent to not
parenthesizing your argument list; the parentheses that had been an
argument list marker are now only a precedence operation. On that
assumption, the warning is either newer or older, and only serves to
chastise (ie. *warn*) those that are making the mistake of thinking
their parens are marking the parameter list when they really aren't.

2) With regards to implicit method parameters, the effect of choosing
do/end over braces is no different than the choice of 'and' over '&&'
-- or 'or' over '||'. Example:

  puts(false) or true # explicit, or => prints false, returns true
  puts(false) || true # explicit, || => prints false, returns true
  puts false  or true # implicit, or => prints false, returns true
  puts false  || true # implicit, || => prints true,  returns nil

Both explicit method calls know their arguments exactly. The implicit
method calls, however, get different argument lists depending on the
*precedence*. The || operator binds higher than the implicit method
call, but the 'or' operator does not.

Similarly, the {} block syntax binds higher than the implicit method
call. The 'do ... end' block syntax does not:

  def foo
    block_given?
  end

  def bar( arg )
    puts arg
    block_given?
  end

  bar(foo) do ; end # explicit, do/end => prints false, returns true
  bar(foo) {  ;   } # explicit, braces => prints false, returns true
  bar foo  do ; end # implicit, do/end => prints false, returns true
  bar foo  {  ;   } # implicit, braces => prints true,  returns false

That's it. That's the difference between do/end and braces. Period.
Any other difference is only convention and personal preference.

Jacob Fugal
Fd22ee3cfc7dac283ce8e451af324f7d?d=identicon&s=25 perrin (Guest)
on 2005-12-09 22:46
(Received via mailing list)
On Sat, Dec 10, 2005 at 06:14:21AM +0900, Jacob Fugal wrote:

[lots of stuff]

Thanks for the clarification.  I blame my momentary lapse on lack of
sleep.

. . . and unfortunately largely superficial familiarity with Ruby.

--
Chad Perrin [ CCD CopyWrite | http://ccd.apotheon.org ]

unix virus: If you're using a unixlike OS, please forward
this to 20 others and erase your system partition.
7264fb16beeea92b89bb42023738259d?d=identicon&s=25 chneukirchen (Guest)
on 2005-12-10 12:46
(Received via mailing list)
"Trans" <transfire@gmail.com> writes:

> I've sometimes thought, "man wouldn't it be tight if we had some sort
> of vertical brackets?"
>
>   task :test .--.
>     ruby "test/unittest.rb"
>   '--'

Cuuute.  Imagine the possibilities, e.g. vertical XHTML:

/\
html
xmlns="http://www.w3.org/1999/xhtml"
\/
/\
title
\/
What a pervert idea!
/\
\
 \
title
\/
/\
\
 \
html
\/

You get a nice "overview" by turning your head 270°. :-)
This topic is locked and can not be replied to.