how to do "do" blocks

D

Daniel Talsky

How come this works:

collection_of_objects = []
10.times do
collection_of_objects << MyObject.create
end

But this doesn't:

collection_of_objects = []
10.times do { collection_of_objects << MyObject.create }

I didn't understand there was ANY difference between the two syntaxes
really. Can someone explain to me the finer points?
 
J

Jesús Gabriel y Galán

How come this works:

collection_of_objects = []
10.times do
collection_of_objects << MyObject.create
end

But this doesn't:

collection_of_objects = []
10.times do { collection_of_objects << MyObject.create }

I didn't understand there was ANY difference between the two syntaxes
really. Can someone explain to me the finer points?

The reason is that "do" starts a block, and then inside the block the
{} are parsed as a hash literal:

irb(main):001:0> collection_of_objects = []
=> []
irb(main):002:0> 10.times do { collection_of_objects << MyObject.create }
irb(main):003:1> end
SyntaxError: compile error
(irb):2: odd number list for Hash
from (irb):3
from :0

You have to use only one form of block, either do...end or {}. The
convention seems to be to use do...end for multiline blocks, while {}
is used for one-liners.

irb(main):005:0> 10.times { collection_of_objects << Array.new }
=> 10
irb(main):006:0> collection_of_objects
=> [[], [], [], [], [], [], [], [], [], []]

Regards,

Jesus.
 
D

Daniel Talsky

Well thanks fellas... that makes good sense.
You have to use only one form of block, either do...end or {}. The
convention seems to be to use do...end for multiline blocks, while {}
is used for one-liners.

However, there's some lines of thought on the internet that have a
different idea. What do you think of the idea that it's not "one line
vs. multiline" but "returns a value vs. doesn't return a value".

Here's the two posts I'm talking about:
http://objo.com/2007/6/28/ruby-style-ruby-do-end-versus
http://onestepback.org/index.cgi/Tech/Ruby/BraceVsDoEnd.rdoc

In the first post, one of the commenters asks:
As for using {} only when returning a value, doesn’t every statement return a
value (in your example, the array with it’s elements capitalised and reversed)?

And although he's wrong, the code in question:
i.capitalize!
is in-place changing the variable of course... but his point is still
valid. Anyone want to weigh in on this?
 
J

Jesús Gabriel y Galán

However, there's some lines of thought on the internet that have a
different idea. What do you think of the idea that it's not "one line
vs. multiline" but "returns a value vs. doesn't return a value".

Here's the two posts I'm talking about:
http://objo.com/2007/6/28/ruby-style-ruby-do-end-versus
http://onestepback.org/index.cgi/Tech/Ruby/BraceVsDoEnd.rdoc

In the first post, one of the commenters asks:

And although he's wrong, the code in question:
i.capitalize!
is in-place changing the variable of course... but his point is still
valid. Anyone want to weigh in on this?

I'm fairly new to Ruby, and still trying to accomodate my style
(coming from java it's taking me a while to use do...end, my fingers
type the { automatically :), but I'm pretty sure I've read many times
here what I said above, and those articles also imply that's the more
widely accepted answer to that question.

I can't comment on other people's uses of this. Maybe more
knowledgeable people here could chime in?

Jesus.
 
B

Bertram Scharpf

Hi,

Am Freitag, 28. Sep 2007, 17:20:40 +0900 schrieb Tom Metge:
Take the "do" out of the statement when passing a block in {}:

10.times {collection_of_objects << MyObject.create}

Yet another opportunity to mention that {} has higer
precedence than do..end.

def f
puts "((("
yield if block_given?
puts ")))"
end
def g x
puts "[[[#{x}|"
yield if block_given?
puts "]]]"
end
g f { puts "x" } (((
x
)))
[[[|
]]]
g f do puts "x" end
(((
)))
[[[|
x
]]]


Not a very intuitive example I admit.

Bertram
 
S

Simon Mullis

I posted this earlier, but it didn't get through... (see my other post
"Ac Cautionary Tale").

hehe

SM

---------- Forwarded message ----------
From: Simon Mullis <[email protected]>
Date: Sep 28, 2007 10:32 AM
Subject: Re: how to do "do" blocks
To: (e-mail address removed)


Hey

The "do..end" and "{..}" are almost equivalent (although "{..}" has
higher precedence).

So,

collection_of_objects = []
10.times do
collection_of_objects << MyObject.create
end

Is the equivalent to:

collection_of_objects = []
10.times {
collection_of_objects << MyObject.create
}


But (from the Ruby Cookbook), you may need to look at precedence.

So,

1.upto 3 do |x|
puts x
end

is ok.

But,

1.upto 3 { |x|
puts x
end

is not, as the code block binds to the 3, not the function call.

So, it would have to be:

1.upto(3) { |x|
puts x
end

Hope this helps!

SM

How come this works:

collection_of_objects = []
10.times do
collection_of_objects << MyObject.create
end

But this doesn't:

collection_of_objects = []
10.times do { collection_of_objects << MyObject.create }

I didn't understand there was ANY difference between the two syntaxes
really. Can someone explain to me the finer points?
 
J

John Joyce

However, there's some lines of thought on the internet that have a
different idea. What do you think of the idea that it's not "one line
vs. multiline" but "returns a value vs. doesn't return a value".

All Ruby blocks (and methods) return a value. They return the value
of the last statement in the block.
But only if you explicitly use it.
Assign it to something, or use return if you want it to be obvious.

The convention is simply
{} for one-line
do-end for multi-line

You don't have to follow these rules. It is up to you.
 
R

Rick DeNatale

Well thanks fellas... that makes good sense.


However, there's some lines of thought on the internet that have a
different idea. What do you think of the idea that it's not "one line
vs. multiline" but "returns a value vs. doesn't return a value".

Here's the two posts I'm talking about:
http://objo.com/2007/6/28/ruby-style-ruby-do-end-versus
http://onestepback.org/index.cgi/Tech/Ruby/BraceVsDoEnd.rdoc

In the first post, one of the commenters asks:

And although he's wrong, the code in question:
i.capitalize!
is in-place changing the variable of course... but his point is still
valid. Anyone want to weigh in on this?

http://talklikeaduck.denhaven2.com/articles/2007/10/02/ruby-blocks-do-or-brace
 
D

David A. Black

Hi --

Hi,

Am Freitag, 28. Sep 2007, 17:20:40 +0900 schrieb Tom Metge:
Take the "do" out of the statement when passing a block in {}:

10.times {collection_of_objects << MyObject.create}

Yet another opportunity to mention that {} has higer
precedence than do..end.

def f
puts "((("
yield if block_given?
puts ")))"
end
def g x
puts "[[[#{x}|"
yield if block_given?
puts "]]]"
end
g f { puts "x" } (((
x
)))
[[[|
]]]
g f do puts "x" end
(((
)))
[[[|
x
]]]


Not a very intuitive example I admit.

Here's one I've stumbled on in real life:

irb(main):001:0> a = [1,2,3,4]
=> [1, 2, 3, 4]
irb(main):002:0> puts a.map {|e| e * 10 }
10
20
30
40
=> nil
irb(main):003:0> puts a.map do |e| e * 10 end
1
2
3
4
=> nil


David

--
Upcoming training from Ruby Power and Light, LLC:
* Intro to Ruby on Rails, Edison, NJ, October 23-26
* Advancing with Rails, Edison, NJ, November 6-9
Both taught by David A. Black.
See http://www.rubypal.com for more info!
 

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
474,266
Messages
2,571,342
Members
48,018
Latest member
DelilahDen

Latest Threads

Top