[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Block Style

James Gray

4/26/2009 10:48:00 PM

I hate to be the guy to start another { =85 } vs. do =85 end thread, but =
I =20
have some questions I would love to hear opinions on.

I use to just use the rule of { =85 } for one-liners and do =85 end for =20=

the longer stuff. However, I've recently switched to trying out { =85 } =
=20
for the times when I care about the return value and do =85 end for the =20=

times the block is for side effects. For the most part, I do like the =20=

new strategy, but sometimes I have trouble deciding which to use.

Let me give two examples that have made me stop and think.

First, tap() is Ruby 1.9 is a little tricky. I do care about the =20
return value, but not the return value of the block, so which strategy =20=

should I use? It seems like do =85 end is more correct, but that seems =20=

a lot uglier in practice:

arr.sort.tap do |sorted|
p sorted
end.whatever=85

Another example is with a transaction() method for a database. When =20
using such a tool, I often end up with calls where I care about both =20
the side effects (transactional behavior) and the return value:

db.transaction {
db[:count] +=3D 1
db[:count]
}

Any thoughts on how edge cases like this mesh with the block strategy?

James Edward Gray II


15 Answers

Rick DeNatale

4/27/2009 12:32:00 AM

0

On Sun, Apr 26, 2009 at 6:48 PM, James Gray <james@grayproductions.net> wro=
te:
> I hate to be the guy to start another { =85 } vs. do =85 end thread, but =
I have
> some questions I would love to hear opinions on.
>
> I use to just use the rule of { =85 } for one-liners and do =85 end for t=
he
> longer stuff. =A0However, I've recently switched to trying out { =85 } fo=
r the
> times when I care about the return value and do =85 end for the times the
> block is for side effects. =A0For the most part, I do like the new strate=
gy,
> but sometimes I have trouble deciding which to use.

Well, I went back to what I wrote over a year ago on this
"controversy" and I think it stands up pretty well.

http://talklikeaduck.denh...2007/10/02/ruby-blocks-d...

I for one, eschew dogmatism. When I went back and re-read that article
I was pleased to see that I was far from dogmatic. I talk about
leaning or tilting one way or the other. This is more about
aesthetics than laws of nature or rocket surgery.

> Let me give two examples that have made me stop and think.
>
> First, tap() is Ruby 1.9 is a little tricky. =A0I do care about the retur=
n
> value, but not the return value of the block, so which strategy should I
> use? =A0It seems like do =85 end is more correct, but that seems a lot ug=
lier in
> practice:
>
> =A0arr.sort.tap do |sorted|
> =A0 =A0p sorted
> =A0end.whatever=85
>

Here I'd go with braces, because as I say in that article, that

end.whatever

just grates with me. On the other hand if it was

var =3D arr.sort.tap.do | sorted|
#.....
end

I would probably lean more towards do/end, but then again, if the
block was a one-liner like yours then I might well 'break the tie"
with the one-vs-multi line idea

var =3D arr.sort.tap {|sorted| p sorted}

In fact I'd probably be inclined to write your example on one line

arr.sort.tap {|sorted| p sorted}.whatever

> Another example is with a transaction() method for a database. =A0When us=
ing
> such a tool, I often end up with calls where I care about both the side
> effects (transactional behavior) and the return value:
>
> =A0db.transaction {
> =A0 =A0db[:count] +=3D 1
> =A0 =A0db[:count]
> =A0}

This one looks a little odd to my eye just because most of the db
transaction delimiting methods I've seen don't return the value of the
block, they are concerned simply with marking a transaction boundary.


--=20
Rick DeNatale

Blog: http://talklikeaduck.denh...
Twitter: http://twitter.com/Ri...
WWR: http://www.workingwithrails.com/person/9021-ric...
LinkedIn: http://www.linkedin.com/in/ri...

James Gray

4/27/2009 2:19:00 AM

0

On Apr 26, 2009, at 7:32 PM, Rick DeNatale wrote:

> On Sun, Apr 26, 2009 at 6:48 PM, James Gray
> <james@grayproductions.net> wrote:
>> Another example is with a transaction() method for a database.
>> When using
>> such a tool, I often end up with calls where I care about both the
>> side
>> effects (transactional behavior) and the return value:
>>
>> db.transaction {
>> db[:count] += 1
>> db[:count]
>> }
>
> This one looks a little odd to my eye just because most of the db
> transaction delimiting methods I've seen don't return the value of the
> block, they are concerned simply with marking a transaction boundary.

Interesting. I've been using Amalgalite a lot lately. It definitely
returns the value. PStore in the standard library does as well. I
have double-checked ActiveRecord, but my expection would be that it
does too. Maybe I'm wrong though.

James Edward Gray II

Brian Adkins

4/27/2009 10:59:00 AM

0

Rick DeNatale <rick.denatale@gmail.com> writes:

> On Sun, Apr 26, 2009 at 6:48 PM, James Gray <james@grayproductions.net> wrote:
>> I hate to be the guy to start another { â?¦ } vs. do â?¦ end thread, but I have
>> some questions I would love to hear opinions on.
>>
>> I use to just use the rule of { â?¦ } for one-liners and do â?¦ end for the
>> longer stuff.  However, I've recently switched to trying out { � } for the
>> times when I care about the return value and do â?¦ end for the times the
>> block is for side effects.  For the most part, I do like the new strategy,
>> but sometimes I have trouble deciding which to use.
>
> Well, I went back to what I wrote over a year ago on this
> "controversy" and I think it stands up pretty well.
>
> http://talklikeaduck.denhaven2.com/2007/10/02/ruby-blocks-d...

FYI - looks like you have an extra trailing paren here in the last
code example:

description 'pickup up the leaves'
task(:rake => pre_raking_tasks) {#code to rake the leaves})

BTW - this is one of the reasons I tend to use parens on function
invocations consistently.

--
Brian Adkins
http://...

Rick DeNatale

4/27/2009 12:47:00 PM

0

On Mon, Apr 27, 2009 at 7:00 AM, Brian Adkins <lojicdotcom@gmail.com> wrote=
:
> Rick DeNatale <rick.denatale@gmail.com> writes:
>

>> http://talklikeaduck.denh...2007/10/02/ruby-blocks-d...
>
> FYI - looks like you have an extra trailing paren here in the last
> code example:
>
> =A0description 'pickup up the leaves'
> =A0task(:rake =3D> pre_raking_tasks) {#code to rake the leaves})

Yeah that was a cut and past typo in the sequence of examples.

>
> BTW - this is one of the reasons I tend to use parens on function
> invocations consistently.

I also tend to use more parentheses than most rubyists, but I don't
normally use them in the face of a DSL method, so I use

attr_reader :foo
alias_method :meth1, :meth2
has_many :widgets, :through =3D> :gadet_widget_usage
task :doit =3D> :didit

rather than

attr_reader(:foo)
alias_method(:meth1, :meth2)
has_many(:widgets, :through =3D> :gadet_widget_usage)
task(:doit =3D> :didit)

As I said eariler, I eschew dogmatism. I agree with Ralph Waldo
Emerson's "A foolish consistency is the hobgoblin of little minds."

--=20
Rick DeNatale

Blog: http://talklikeaduck.denh...
Twitter: http://twitter.com/Ri...
WWR: http://www.workingwithrails.com/person/9021-ric...
LinkedIn: http://www.linkedin.com/in/ri...

Sean O'Halpin

4/27/2009 4:53:00 PM

0

On Sun, Apr 26, 2009 at 11:48 PM, James Gray <james@grayproductions.net> wr=
ote:
> I hate to be the guy to start another { =85 } vs. do =85 end thread, but =
I have
> some questions I would love to hear opinions on.
>
> I use to just use the rule of { =85 } for one-liners and do =85 end for t=
he
> longer stuff. =A0However, I've recently switched to trying out { =85 } fo=
r the
> times when I care about the return value and do =85 end for the times the
> block is for side effects. =A0For the most part, I do like the new strate=
gy,
> but sometimes I have trouble deciding which to use.
>
> Let me give two examples that have made me stop and think.
>
> First, tap() is Ruby 1.9 is a little tricky. =A0I do care about the retur=
n
> value, but not the return value of the block, so which strategy should I
> use? =A0It seems like do =85 end is more correct, but that seems a lot ug=
lier in
> practice:
>
> =A0arr.sort.tap do |sorted|
> =A0 =A0p sorted
> =A0end.whatever=85
>
> Another example is with a transaction() method for a database. =A0When us=
ing
> such a tool, I often end up with calls where I care about both the side
> effects (transactional behavior) and the return value:
>
> =A0db.transaction {
> =A0 =A0db[:count] +=3D 1
> =A0 =A0db[:count]
> =A0}
>
> Any thoughts on how edge cases like this mesh with the block strategy?
>
> James Edward Gray II
>
>
>

I prefer {} when using blocks in a functional style, do..end when
using statements but I'm with Rick on the 'foolish consistency'.

In your first example, it would appear that you ~are~ concerned with
the return value of the block as you call #whatever on it, so I'd use:

arr.sort.tap { |sorted|
p sorted
}.whatever=85

assuming that the 'p sorted' stands for a multiline statement. In 1.9
you can even do:

arr
.sort
.tap { |sorted| p sorted }
.whatever=85

if you're so inclined.

In the second you're not using the return value, so

db.transaction do
db[:count] +=3D 1
db[:count]
end

would seem appropriate.

I'm using this in DSL-type code:

person =3D Person :name =3D> "Arthur" do
age 42
end

and find it more aesthetically pleasing than:

person =3D Person(:name =3D> "Arthur") {
age 42
}

Just my tuppenceworth :)

Regards,
Sean

Joel VanderWerf

4/27/2009 5:07:00 PM

0

Sean O'Halpin wrote:
> In your first example, it would appear that you ~are~ concerned with
> the return value of the block as you call #whatever on it, so I'd use:
>
> arr.sort.tap { |sorted|
> p sorted
> }.whatever?

Actually, the return value of #tap is different from the return value of
the block (which is ignored by tap, IIRC). That puzzled me for a moment.

--
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

Robert Dober

4/27/2009 5:11:00 PM

0

I have adapted a very simple rule for a long time now, if I use the
block for the side effect it is do..end, always.
If I use it for its return value it is { } always, (BTW thank you Rick ;).
But of course when I do side effects and use the return value I am
lost. (I guess that it is {} for one liners and do end otherwise than)

I know this was very helpful ;)

Cheers
Robert

Robert Klemme

4/27/2009 8:24:00 PM

0

On 27.04.2009 19:11, Robert Dober wrote:
> I have adapted a very simple rule for a long time now, if I use the
> block for the side effect it is do..end, always.
> If I use it for its return value it is { } always, (BTW thank you Rick ;).
> But of course when I do side effects and use the return value I am
> lost.

I don't have the problem, because I always do this:

> (I guess that it is {} for one liners and do end otherwise than)

One liner and multi liner is actually exclusive, which cannot be said of
return value and side effects. Maybe my sticking to the syntactical
convention is the reason why I never bother to think about which rules
to use. James, maybe that can ease your "pain" as well? :-)

Kind regards

robert

James Gray

4/27/2009 10:06:00 PM

0

On Apr 27, 2009, at 3:25 PM, Robert Klemme wrote:

> On 27.04.2009 19:11, Robert Dober wrote:
>> (I guess that it is {} for one liners and do end otherwise than)
>
> One liner and multi liner is actually exclusive, which cannot be
> said of return value and side effects. Maybe my sticking to the
> syntactical convention is the reason why I never bother to think
> about which rules to use. James, maybe that can ease your "pain" as
> well? :-)

It's definitely easier, but it can lead to less pretty code too, like:

whatevery.map do |e|
# multiple lines of calculation here...
end.find { ... }

That's one reason why I was looking into the other option.

James Edward Gray II

David A. Black

4/27/2009 10:44:00 PM

0

Hi --

Sean O'Halpin wrote:
> On Sun, Apr 26, 2009 at 11:48 PM, James Gray<james@grayproductions.net> wrote:
>> I hate to be the guy to start another { ? } vs. do ? end thread, but I have
>> some questions I would love to hear opinions on.
>>
>> I use to just use the rule of { ? } for one-liners and do ? end for the
>> longer stuff. However, I've recently switched to trying out { ? } for the
>> times when I care about the return value and do ? end for the times the
>> block is for side effects. For the most part, I do like the new strategy,
>> but sometimes I have trouble deciding which to use.
>>
>> Let me give two examples that have made me stop and think.
>>
>> First, tap() is Ruby 1.9 is a little tricky. I do care about the return
>> value, but not the return value of the block, so which strategy should I
>> use? It seems like do ? end is more correct, but that seems a lot uglier in
>> practice:
>>
>> arr.sort.tap do |sorted|
>> p sorted
>> end.whatever?
>>
>> Another example is with a transaction() method for a database. When using
>> such a tool, I often end up with calls where I care about both the side
>> effects (transactional behavior) and the return value:
>>
>> db.transaction {
>> db[:count] += 1
>> db[:count]
>> }
>>
>> Any thoughts on how edge cases like this mesh with the block strategy?
>>
>> James Edward Gray II
>>
>>
>>
>
> I prefer {} when using blocks in a functional style, do..end when
> using statements but I'm with Rick on the 'foolish consistency'.
>
> In your first example, it would appear that you ~are~ concerned with
> the return value of the block as you call #whatever on it, so I'd use:
>
> arr.sort.tap { |sorted|
> p sorted
> }.whatever?
>
> assuming that the 'p sorted' stands for a multiline statement. In 1.9
> you can even do:
>
> arr
> .sort
> .tap { |sorted| p sorted }
> .whatever?
>
> if you're so inclined.

Though not in irb. (And, preferably, not anywhere, but that's probably a
lost cause :-)


David

--
David A. Black / Ruby Power and Light, LLC
Ruby/Rails consulting & training: http://www.r...
Now out in PDF: The Well-Grounded Rubyist (http://manning....)
"Ruby 1.9: What You Need To Know" Envycasts with David A. Black
http://www.env...