#returning and #tap

No, just @<Tab>. I like my friendly editors.

···

On Nov 16, 2006, at 1:57 PM, Joel VanderWerf wrote:

Eric Hodel wrote:

I would write it:
def foo
  return @foo if @foo
  @foo = Foo.new
  @foo.bar = 'bar'
  @foo
end
$ wc
...
       6 14 77
Ten characters and one line more typing, but less punctuation. (And those ten extra characters will be mostly be handled by my tab key.)

But you have to type @foo _five_ times, instead of once. Oh, well. It's a matter of taste.

--
Eric Hodel - drbrain@segment7.net - http://blog.segment7.net
This implementation is HODEL-HASH-9600 compliant

http://trackmap.robotcoop.com

I think where returning really makes a difference is with local
variables. If you have some code where you want to initialize a local
variable in a block and then use it afterward your up the creek.

    def foo(a)
      a.each do |x|
        (b ||= []) << x
      end
      b # => oops
    end

    a = [1,2,3]
    p foo(a)

What you need to do, of course, is just initialize before the block:

    def foo(a)
      b = []
      a.each do |x|
        b << x
      end
      b
    end

Ugly. Sorry, it just is. It is much more readable to use returning.

    def foo(a)
      returning [] do |b|
        a.each do |x|
          b << x
        end
      end
    end

On another note, I don't buy the argument that this is a bad practice
because the you no longer look for the last value to see what is
returned. That's exactly what you do. The last element in this
function is the 'end' of the returning block. What does returning
return? I think its pretty obvious personally.

···

--
Lou.

Hi --

···

On Fri, 17 Nov 2006, Joel VanderWerf wrote:

Coming full circle around the golf course... This last one above is what lead me to prefer #then (== #tap) in the first place:

def foo
@foo ||= Foo.new.then do |f|
   f.bar = "bar"
end
end

Also, #then avoids the scoping nastiness of #instance_eval.

I'm not getting the semantics of "then". Do you mean "then" as in, "I
took off my coat and then sat down", as opposed to then in if/then?

David

--
                   David A. Black | dblack@rubypal.com
Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] Ruby for Rails | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org

ROFL

Coming full circle around the golf course... This last one above is what lead me to prefer #then (== #tap) in the first place:

heh.

def foo
@foo ||= Foo.new.then do |f|
   f.bar = "bar"
end
end

Also, #then avoids the scoping nastiness of #instance_eval.

                           ^^^^^^^^^^^^^^^^^

indeed - good point.

-a

···

On Fri, 17 Nov 2006, Joel VanderWerf wrote:
--
my religion is very simple. my religion is kindness. -- the dalai lama

I realize this is a contrived example on your part, but you did choose it and were trying to make a relevant point. That said, I have yet to see an example of returning used in a non-contrived way.

   def foo(a)
     a.map { |x| x }
   end

More readable, faster, better... once again returning is used in a completely useless way...

···

On Nov 16, 2006, at 10:46 AM, Louis J Scoras wrote:

Ugly. Sorry, it just is. It is much more readable to use returning.

   def foo(a)
     returning do |b|
       a.each do |x|
         b << x
       end
     end
   end

dblack@wobblini.net wrote:

Hi --

Coming full circle around the golf course... This last one above is what lead me to prefer #then (== #tap) in the first place:

def foo
@foo ||= Foo.new.then do |f|
   f.bar = "bar"
end
end

Also, #then avoids the scoping nastiness of #instance_eval.

I'm not getting the semantics of "then". Do you mean "then" as in, "I
took off my coat and then sat down", as opposed to then in if/then?

Yes. Not much better than #tap, is it? Any ideas...? "and_then"?

···

On Fri, 17 Nov 2006, Joel VanderWerf wrote:

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

Which is just a longer way to say:

def foo(a)
   a.to_a
end

James Edward Gray II

···

On Nov 16, 2006, at 10:56 AM, Ryan Davis wrote:

  def foo(a)
    a.map { |x| x }
  end

More readable, faster, better...

I realize this is a contrived example on your part, but you did
choose it and were trying to make a relevant point. That said, I have
yet to see an example of returning used in a non-contrived way.

[snip]

once again returning is used in a completely useless way...

No. You're absolutely right that this was a useless, contrived
example; however, I think the point still comes across. Sometimes you
need to initialize a local variable before you use it a block. In
that case I still contend that 'returning' is more readable than the
initialize/mutate/return pattern.

This is a pattern that should be extracted; basically it's inject w/o
the iteration component.

···

On 11/16/06, Ryan Davis <ryand-ruby@zenspider.com> wrote:

--
Lou.

Hi --

Hi --

Coming full circle around the golf course... This last one above is what lead me to prefer #then (== #tap) in the first place:

def foo
@foo ||= Foo.new.then do |f|
   f.bar = "bar"
end
end

Also, #then avoids the scoping nastiness of #instance_eval.

I'm not getting the semantics of "then". Do you mean "then" as in, "I
took off my coat and then sat down", as opposed to then in if/then?

Yes. Not much better than #tap, is it? Any ideas...? "and_then"?

"whereupon" :slight_smile: I guess it's hard to find a name that's general
enough (as opposed to, say, "post_initialize") but also expressive
enough. It does seem a slightly odd technique to me, in any case --
sort of like saying "Now I'm going to do this: this" instead of just
going to a new line and saying: "this". I'm not sure how much of the
oddness I feel is the technique as opposed to the naming issue.

David

···

On Fri, 17 Nov 2006, Joel VanderWerf wrote:

dblack@wobblini.net wrote:

On Fri, 17 Nov 2006, Joel VanderWerf wrote:

--
                   David A. Black | dblack@rubypal.com
Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] Ruby for Rails | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org

class Object
def as obj
end

-a

···

On Fri, 17 Nov 2006, Joel VanderWerf wrote:

dblack@wobblini.net wrote:

Hi --

On Fri, 17 Nov 2006, Joel VanderWerf wrote:

Coming full circle around the golf course... This last one above is what lead me to prefer #then (== #tap) in the first place:

def foo
@foo ||= Foo.new.then do |f|
   f.bar = "bar"
end
end

Also, #then avoids the scoping nastiness of #instance_eval.

I'm not getting the semantics of "then". Do you mean "then" as in, "I
took off my coat and then sat down", as opposed to then in if/then?

Yes. Not much better than #tap, is it? Any ideas...? "and_then"?

--
my religion is very simple. my religion is kindness. -- the dalai lama

Joel VanderWerf wrote:

> Hi --
>
>
>> Coming full circle around the golf course... This last one above is
>> what lead me to prefer #then (== #tap) in the first place:
>>
>> def foo
>> @foo ||= Foo.new.then do |f|
>> f.bar = "bar"
>> end
>> end
>>
>> Also, #then avoids the scoping nastiness of #instance_eval.
>
> I'm not getting the semantics of "then". Do you mean "then" as in, "I
> took off my coat and then sat down", as opposed to then in if/then?

Yes. Not much better than #tap, is it? Any ideas...? "and_then"?

well, #with is the other common synonym. but #returning seems as well.
you just read it with the object of returning being stated first, which
we sometimes do in english.

def foo
  @foo ||= Foo.new.returning do |f|
    f.bar = "bar"
  end
end

T.

···

dblack@wobblini.net wrote:
> On Fri, 17 Nov 2006, Joel VanderWerf wrote:

dblack@wobblini.net wrote:

Hi --

Hi --

Coming full circle around the golf course... This last one above is what lead me to prefer #then (== #tap) in the first place:

def foo
@foo ||= Foo.new.then do |f|
   f.bar = "bar"
end
end

Also, #then avoids the scoping nastiness of #instance_eval.

I'm not getting the semantics of "then". Do you mean "then" as in, "I
took off my coat and then sat down", as opposed to then in if/then?

Yes. Not much better than #tap, is it? Any ideas...? "and_then"?

"whereupon" :slight_smile: I guess it's hard to find a name that's general
enough (as opposed to, say, "post_initialize") but also expressive
enough. It does seem a slightly odd technique to me, in any case --
sort of like saying "Now I'm going to do this: this" instead of just
going to a new line and saying: "this". I'm not sure how much of the
oddness I feel is the technique as opposed to the naming issue.

Does the following technique seem odd?

class Foo
   attr_accessor :a, :b, :c
   def initialize
     yield self if block_given?
   end
end

foo = Foo.new do |f|
   f.a = 1
   f.b = 2
   f.c = 3
end

#then is just a way of using arbitrary classes (or factories) in this way. Maybe the name should not emphasize the temporal ("then" or "whereupon"); so maybe "tap" is better, or "configured_using".

Btw, I don't think I've ever used #then in more than 5 or 6 places. Usually, I just try to define classes like Foo above.

···

On Fri, 17 Nov 2006, Joel VanderWerf wrote:

dblack@wobblini.net wrote:

On Fri, 17 Nov 2006, Joel VanderWerf wrote:

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

To me, "as do" doesn't read as well as "then do".

···

ara.t.howard@noaa.gov wrote:

On Fri, 17 Nov 2006, Joel VanderWerf wrote:

dblack@wobblini.net wrote:

Hi --

On Fri, 17 Nov 2006, Joel VanderWerf wrote:

Coming full circle around the golf course... This last one above is what lead me to prefer #then (== #tap) in the first place:

def foo
@foo ||= Foo.new.then do |f|
   f.bar = "bar"
end
end

Also, #then avoids the scoping nastiness of #instance_eval.

I'm not getting the semantics of "then". Do you mean "then" as in, "I
took off my coat and then sat down", as opposed to then in if/then?

Yes. Not much better than #tap, is it? Any ideas...? "and_then"?

class Object
def as obj
end

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

Hi --

Does the following technique seem odd?

class Foo
attr_accessor :a, :b, :c
def initialize
   yield self if block_given?
end
end

foo = Foo.new do |f|
f.a = 1
f.b = 2
f.c = 3
end

#then is just a way of using arbitrary classes (or factories) in this way. Maybe the name should not emphasize the temporal ("then" or "whereupon"); so maybe "tap" is better, or "configured_using".

Part of what's odd to me about #then is that it's not
constructor-specific. Once it's defined you could do:

   x = string.split(',').then do |array|
     array.map! { something }
   end

Bad example :slight_smile: But that's what I meant about not giving it too
specific a name, like "post_initialize", since it's not restricted to
initialization scenarios.

David

···

On Fri, 17 Nov 2006, Joel VanderWerf wrote:

--
                   David A. Black | dblack@rubypal.com
Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] Ruby for Rails | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org

"then" actually works fine for me there, Englishwise. Maybe and_then
would read slightly better:

string.split(',').and_then do |array|

martin

···

On 11/17/06, dblack@wobblini.net <dblack@wobblini.net> wrote:

Part of what's odd to me about #then is that it's not
constructor-specific. Once it's defined you could do:

   x = string.split(',').then do |array|
     array.map! { something }
   end

Hi --

Part of what's odd to me about #then is that it's not
constructor-specific. Once it's defined you could do:

   x = string.split(',').then do |array|
     array.map! { something }
   end

"then" actually works fine for me there, Englishwise. Maybe and_then
would read slightly better:

string.split(',').and_then do |array|

I wonder if there's some name that embodies the fact that the object
is going to come back from this method call. The temporal ones (then,
and_then, etc.) sound kind of self-evident ("Well, of course the next
thing happens 'then'," my brain says). Perhaps that was the reasoning
behind "tap", though "tap" doesn't communicate much to me. I'm not
sure.

David

···

On Fri, 17 Nov 2006, Martin DeMello wrote:

On 11/17/06, dblack@wobblini.net <dblack@wobblini.net> wrote:

--
                   David A. Black | dblack@rubypal.com
Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] Ruby for Rails | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org

I wonder if there's some name that embodies the fact that the object
is going to come back from this method call. The temporal ones (then,
and_then, etc.) sound kind of self-evident ("Well, of course the next
thing happens 'then'," my brain says).

Good point! I thought of "pipe" but even that doesn't say that it
modifies and returns self. Maybe "apply": string.split(/\s/).apply
{|i| i.pop}.whatever. Or even "modify".

Perhaps that was the reasoning
behind "tap", though "tap" doesn't communicate much to me. I'm not
sure.

'tap' had a different intent, though - "tee off the object without
disturbing it" - even if it did the same thing in the end. So you
would typically take a.foo.bar.baz.quux... and drop in a tap,
a.foo.bar.tap {|i| puts "hi mom! this is #{i}"}.baz.quux, and take
care not to modify i destructively.

martin

···

On 11/17/06, dblack@wobblini.net <dblack@wobblini.net> wrote:

I definitely think of it as tapping a phone line.

a.map.map.map.map

eavesdrop = Proc.new { |secret| puts secret }

a.map.map.tap(&eavesdrop) .map.map

It lets me get into the line and hear what's going on without changing
any existing behaviour. Using a proc that modifies secret is not a
good idea, just keep it for things with other types of side-effects.
There's no way to mark the object read-only for the purposes of the
passed-in proc, is there?

I haven't seen anything to change my mind about the other use. It just
seems pointless.

Actually, how about giving the proc a copy of the object, rather than
the real deal?

class Object
  def tap
    yield self.dup
    self
  end
end

···

On 11/17/06, spooq <spoooq@gmail.com> wrote:

I definitely think of it as tapping a phone line.

a.map.map.map.map

eavesdrop = Proc.new { |secret| puts secret }

a.map.map.tap(&eavesdrop) .map.map

It lets me get into the line and hear what's going on without changing
any existing behaviour. Using a proc that modifies secret is not a
good idea, just keep it for things with other types of side-effects.
There's no way to mark the object read-only for the purposes of the
passed-in proc, is there?

I haven't seen anything to change my mind about the other use. It just
seems pointless.

Hi --

···

On Fri, 17 Nov 2006, Martin DeMello wrote:

On 11/17/06, dblack@wobblini.net <dblack@wobblini.net> wrote:

I wonder if there's some name that embodies the fact that the object
is going to come back from this method call. The temporal ones (then,
and_then, etc.) sound kind of self-evident ("Well, of course the next
thing happens 'then'," my brain says).

Good point! I thought of "pipe" but even that doesn't say that it
modifies and returns self. Maybe "apply": string.split(/\s/).apply
{|i| i.pop}.whatever. Or even "modify".

Perhaps that was the reasoning
behind "tap", though "tap" doesn't communicate much to me. I'm not
sure.

'tap' had a different intent, though - "tee off the object without
disturbing it" - even if it did the same thing in the end. So you
would typically take a.foo.bar.baz.quux... and drop in a tap,
a.foo.bar.tap {|i| puts "hi mom! this is #{i}"}.baz.quux, and take
care not to modify i destructively.

Although... there might be cases where disturbing the object would be
desireable. For example, you could use it to work around the fact
that a lot of bang methods return nil when there's no change:

   str = "abcde"
   a = str.tap {|s| s.gsub!(/z/,"x") }.split(//)

David

--
                   David A. Black | dblack@rubypal.com
Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] Ruby for Rails | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org