do/end vs braces

Discussion in 'Ruby' started by Steve Litt, Dec 8, 2005.

  1. Steve Litt

    Steve Litt Guest

    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
     
    Steve Litt, Dec 8, 2005
    #1
    1. Advertising

  2. Steve Litt

    Joe Van Dyk Guest

    On 12/8/05, 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 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?
     
    Joe Van Dyk, Dec 8, 2005
    #2
    1. Advertising

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

    > On 12/8/05, 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?

    >
    > 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
     
    James Edward Gray II, Dec 8, 2005
    #3
  4. James Edward Gray II, Dec 8, 2005
    #4
  5. Steve Litt

    Joe Van Dyk Guest

    On 12/8/05, James Edward Gray II <> wrote:
    > On Dec 8, 2005, at 8:13 AM, Joe Van Dyk wrote:
    >
    > > On 12/8/05, 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?

    > >
    > > 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
     
    Joe Van Dyk, Dec 8, 2005
    #5
  6. Steve Litt

    Joe Van Dyk Guest

    On 12/8/05, Joe Van Dyk <> wrote:
    > On 12/8/05, James Edward Gray II <> wrote:
    > > On Dec 8, 2005, at 8:13 AM, Joe Van Dyk wrote:
    > >
    > > > On 12/8/05, 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?
    > > >
    > > > 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'.
     
    Joe Van Dyk, Dec 8, 2005
    #6
  7. 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
     
    Daniel Schierbeck, Dec 8, 2005
    #7
  8. Joe Van Dyk <> 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
     
    Martin DeMello, Dec 8, 2005
    #8
  9. Steve Litt

    Steve Litt Guest

    On Thursday 08 December 2005 10:07 am, Daniel Schierbeck wrote:
    > 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


    > 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
    http://www.troubleshooters.com
     
    Steve Litt, Dec 8, 2005
    #9
  10. Steve Litt

    Jacob Fugal Guest

    On 12/8/05, Steve Litt <> wrote:
    > 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
     
    Jacob Fugal, Dec 8, 2005
    #10
  11. Steve Litt

    Steve Litt Guest

    On Thursday 08 December 2005 06:06 pm, Jacob Fugal wrote:
    > On 12/8/05, Steve Litt <> 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:


    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
     
    Steve Litt, Dec 9, 2005
    #11
  12. Steve Litt

    Paul Sanchez Guest

    In article <>,
    Steve Litt <> wrote:

    > On Thursday 08 December 2005 06:06 pm, Jacob Fugal wrote:
    > > On 12/8/05, Steve Litt <> 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:

    >
    > 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
     
    Paul Sanchez, Dec 9, 2005
    #12
  13. Steve Litt

    Steve Litt Guest

    On Thursday 08 December 2005 08:42 pm, Paul Sanchez wrote:
    > In article <>,
    >
    > Steve Litt <> wrote:
    > > On Thursday 08 December 2005 06:06 pm, Jacob Fugal wrote:
    > > > On 12/8/05, Steve Litt <> 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:

    > >
    > > 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
     
    Steve Litt, Dec 9, 2005
    #13
  14. Steve Litt

    MenTaLguY Guest

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

    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=

    =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+--
     
    MenTaLguY, Dec 9, 2005
    #14
  15. On Dec 8, 2005, at 8:11 PM, Steve Litt wrote:

    > On Thursday 08 December 2005 06:06 pm, Jacob Fugal wrote:
    >> On 12/8/05, Steve Litt <> 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:

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



    > Steve Litt
    > http://www.troubleshooters.com
    >
    >
     
    Logan Capaldo, Dec 9, 2005
    #15
  16. Steve Litt

    Chad Perrin Guest

    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.
     
    Chad Perrin, Dec 9, 2005
    #16
  17. Steve Litt

    daz Guest

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



    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
     
    daz, Dec 9, 2005
    #17
  18. Steve Litt

    Steve Litt Guest

    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
     
    Steve Litt, Dec 9, 2005
    #18
  19. Yohanes Santoso wrote:

    >Joe Van Dyk <> 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.
     
    Daniel Cedilotte, Dec 9, 2005
    #19
  20. Steve Litt

    Guest

    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
     
    , Dec 9, 2005
    #20
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Dustin D.
    Replies:
    0
    Views:
    2,356
    Dustin D.
    Aug 27, 2003
  2. bric

    brackets, braces and arrays

    bric, Jul 5, 2004, in forum: ASP .Net
    Replies:
    4
    Views:
    492
  3. Henrik S. Hansen

    Why braces around try/catch?

    Henrik S. Hansen, Aug 6, 2003, in forum: Java
    Replies:
    52
    Views:
    1,754
    Dale King
    Aug 22, 2003
  4. Geathaa
    Replies:
    1
    Views:
    546
    Martin Honnen
    Sep 12, 2003
  5. Ion Freeman
    Replies:
    7
    Views:
    1,081
    Arne Vajhøj
    Jun 24, 2009
Loading...

Share This Page