Alias_method :tap, :affect

Ruby's enumeration message names come directly from its Smalltalk
ancestry. There are also some aliases. Like so:

*method* *alias*
collect map
detect find
select find_all
reject
inject

Ruby 1.9 introduces the K-combinator in the form of the method
Object#tap. I don't get the name #tap at all. So I'm proposing a new
name/alias pair, with a more meaningful name:

*method* *alias*
affect tap

"foo".affect { |s| s << "bar" }
#=> "foobar"

The K-combinator is all about side-effecting the receiver object, so
"affect" seems like a meaningful name for that functionality (whereas
"effect" would be wrong!). "tap" is still cute, and rhymes with "map",
so having both seems like a good Rubyish way to go.

Thoughts?

···

--
Josh Susser
http://blog.hasmanythrough.com
--
Posted via http://www.ruby-forum.com/.

Of course, active-support also defines the same method as Object#returning

I'm not sure how the Smalltalk intro ties in here. I can't recall a
method implementation of the k-combinator in common use in Smalltalk,
in most cases the message cascade syntax ending with an invocation of
#yourself, would serve the cases where the k-combinator is used:

Ruby

   a = MyObject.new.tap do |o| # or returning, or affect
        o.foo = 1
        o.bar = "whatever"
   end

Smalltalk
   a = MyObject.new foo: 1;
                                    bar: "whatever";
                                    yourself

For Rubyists unfamiliar with Smalltalk, the message cascade triggered
by the ; meant send the message after the ; to the receiver of the
last message. Object#yourself was defined to return the receiver, and
was not typically overridden.

···

On Nov 12, 2007 12:58 PM, Josh Susser <josh@hasmanythrough.com> wrote:

Ruby's enumeration message names come directly from its Smalltalk
ancestry. There are also some aliases. Like so:

*method* *alias*
collect map
detect find
select find_all
reject
inject

Ruby 1.9 introduces the K-combinator in the form of the method
Object#tap. I don't get the name #tap at all. So I'm proposing a new
name/alias pair, with a more meaningful name:

*method* *alias*
affect tap

"foo".affect { |s| s << "bar" }
#=> "foobar"

The K-combinator is all about side-effecting the receiver object, so
"affect" seems like a meaningful name for that functionality (whereas
"effect" would be wrong!). "tap" is still cute, and rhymes with "map",
so having both seems like a good Rubyish way to go.

--
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

I remember some of this talk from RubyConf IRC, and I'm still not
convinced about "affect". Personally, I would expect a method called
"affect" to return the receiver with some change, whereas tap returns
the receiver as-is. Your example modifies the receiver in place, so
it's a little confounding.

MenTaLguY has yet to chime in, so I'll beat him to the punch with his
own link. http://moonbase.rydia.net/mental/blog/programming/eavesdropping-on-expressions
has some examples of what Object#tap is (possibly) intended for, and
that makes the name perfectly sensible, as far as I'm concerned. It's
for "tapping into" the line of calls, allowing you to see what's going
on at that point, but not changing anything.

Don't get me wrong, though. I'm all for more methods that end in
"ect".

I also find tap and returning to be for completely different purposes.
The point of the latter is mainly to get away from things like

def some_method
  var = ''
  some_stuff_with(var)
  var += something_else
  var.more_things
  var
end

and instead let you write something like

def some_method
  var = ''
  returning(var) do |x|
    some_stuff_with(x)
    x += something_else
    x.more_things
  end
end

···

On Nov 12, 11:58 am, Josh Susser <j...@hasmanythrough.com> wrote:

Ruby's enumeration message names come directly from its Smalltalk
ancestry. There are also some aliases. Like so:

*method* *alias*
collect map
detect find
select find_all
reject
inject

Ruby 1.9 introduces the K-combinator in the form of the method
Object#tap. I don't get the name #tap at all. So I'm proposing a new
name/alias pair, with a more meaningful name:

*method* *alias*
affect tap

"foo".affect { |s| s << "bar" }
#=> "foobar"

The K-combinator is all about side-effecting the receiver object, so
"affect" seems like a meaningful name for that functionality (whereas
"effect" would be wrong!). "tap" is still cute, and rhymes with "map",
so having both seems like a good Rubyish way to go.

Thoughts?

--
Josh Susserhttp://blog.hasmanythrough.com

--
-yossef

--
Posted viahttp://www.ruby-forum.com/.

Rick Denatale wrote:

The K-combinator is all about side-effecting the receiver object, so
"affect" seems like a meaningful name for that functionality (whereas
"effect" would be wrong!). "tap" is still cute, and rhymes with "map",
so having both seems like a good Rubyish way to go.

Of course, active-support also defines the same method as
Object#returning

Not exatcly. #tap works on the receiver, #returning works on an
argument. #tap is more object-oriented IMO.

returning("foo") { |s| s << "bar" }
"foo".affect { |s| s << "bar" }

I'm not sure how the Smalltalk intro ties in here.

It's just to say how awsome methods that end in "ect" are, and why :slight_smile:

I can't recall a
method implementation of the k-combinator in common use in Smalltalk,
in most cases the message cascade syntax ending with an invocation of
#yourself, would serve the cases where the k-combinator is used:

Ruby

   a = MyObject.new.tap do |o| # or returning, or affect
        o.foo = 1
        o.bar = "whatever"
   end

Smalltalk
   a = MyObject.new foo: 1;
                                    bar: "whatever";
                                    yourself

For Rubyists unfamiliar with Smalltalk, the message cascade triggered
by the ; meant send the message after the ; to the receiver of the
last message. Object#yourself was defined to return the receiver, and
was not typically overridden.

That's exactly right. Cascaded messages were cool, and came right out of
the stack machine nature of Smalltalk's bytecodes. And I've often longed
for a #yourself method in Ruby, but usually only to get to the target of
a proxy object.

···

On Nov 12, 2007 12:58 PM, Josh Susser <josh@hasmanythrough.com> wrote:

--
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

--
Josh Susser
http://blog.hasmanythrough.com

--
Posted via http://www.ruby-forum.com/\.

This is the first I've heard of Object#tap. It seems backward because
you almost always want the result of the block, not the object back
again. All of my ruby scripts use

   class Object
      def as
         yield self
      end
   end

E.g, a recent script of mine does

   platform_audio_files = audio_stems.map { |f|
      f + "." + audio_ext[platform]
   }.as { |t|
      t + audio_basenames
   }.map { |f|
      File.join(audio_dir, f)
   }

I know this could be written

   platform_audio_files = (audio_stems.map { |f|
      f + "." + audio_ext[platform]
   } + audio_basenames).map { |f|
      File.join(audio_dir, f)
   }

but I find that uncouth compared to the former.

If ruby is adding anything, it should be the behavior of Object#as,
not Object#tap.

just as easy to do this though:

a = MyObject.new.instance_eval{
   foo 1
   bar 'whatever'
   self
}

no special methods needed...

returning is, imho, over rated.

cheers.

a @ http://codeforpeople.com/

···

On Nov 12, 2007, at 11:38 AM, Rick DeNatale wrote:

   a = MyObject.new.tap do |o| # or returning, or affect
        o.foo = 1
        o.bar = "whatever"
   end

--
it is not enough to be compassionate. you must act.
h.h. the 14th dalai lama

It would seem Object#tap is for the imperative style and Object#as is
for the functional style. My ruby code is always improved ---
clearer, smaller, more elegant --- when I use a functional style as
much as possible. For example cutting down on side-effects and being
in the mindset of chaining results rather than re-assigning to the
same variable. Please, if you add Object#tap then you must add its
functional equivalent Object#as (call it what you wish).

#tap is the opposite use case - you want to "tap" the object stream,
observing without affecting. It's very handy for debugging, where you
can tap into a chain of method calls, print something out and continue
on your way, e.g.

foo.map(&:bar).tap {|a| p a}.inject...

martin

···

On Nov 12, 2007 11:10 AM, <furtive.clown@gmail.com> wrote:

This is the first I've heard of Object#tap. It seems backward because
you almost always want the result of the block, not the object back
again.

This is the first I've heard of Object#tap. It seems backward because
you almost always want the result of the block, not the object back
again. All of my ruby scripts use

   class Object
      def as
         yield self
      end
   end

I am so glad, I really needed Object#itself in Labrador, somehow I
felt alone with this approach, now it seems i am not that weird after
all.

I however adhere with Ara's POV, what is there that instance_eval
cannot give you?

Cheers
Robert

···

On Nov 12, 2007 8:10 PM, <furtive.clown@gmail.com> wrote:

E.g, a recent script of mine does

   platform_audio_files = audio_stems.map { |f|
      f + "." + audio_ext[platform]
   }.as { |t|
      t + audio_basenames
   }.map { |f|
      File.join(audio_dir, f)
   }

I know this could be written

   platform_audio_files = (audio_stems.map { |f|
      f + "." + audio_ext[platform]
   } + audio_basenames).map { |f|
      File.join(audio_dir, f)
   }

but I find that uncouth compared to the former.

If ruby is adding anything, it should be the behavior of Object#as,
not Object#tap.

--
what do I think about Ruby?
http://ruby-smalltalk.blogspot.com/

ara.t.howard wrote:

   a = MyObject.new.tap do |o| # or returning, or affect
        o.foo = 1
        o.bar = "whatever"
   end

just as easy to do this though:

a = MyObject.new.instance_eval{
  foo 1
  bar 'whatever'
  self
}

no special methods needed...

returning is, imho, over rated.

Really?

There is the scope issue. I use this construct sometimes:

   def socket
     @socket ||= UDPSocket.open.then do |s|
       s.setsockopt(Socket::SOL_SOCKET, Socket::SO_BROADCAST, true)
       s.connect(@svr_addr, @svr_port)
     end
   end

   def initialize
     @svr_addr, @svr_port = ...
   end

   def run
     loop { socket.send(...) }
   end

#instance_eval makes it unnatural to access instance variables of the outer scope (you have to pass them through locals).

(#then is my own personal preference to #tap, which usually makes me start thinking about Spinal Tap, and I have to laugh for a while.)

···

On Nov 12, 2007, at 11:38 AM, Rick DeNatale wrote:

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

This is the first I've heard of Object#tap. It seems backward because
you almost always want the result of the block, not the object back
again. All of my ruby scripts use

   class Object
      def as
         yield self
      end
   end

This can be useful in the right context. Should it be canonized in
Ruby? I'm not sure.

   platform_audio_files = audio_stems.map { |f|
      f + "." + audio_ext[platform]
   }.as { |t|
      t + audio_basenames
   }.map { |f|
      File.join(audio_dir, f)
   }

This method chaining looks ugly to me, but I'm not a CS guy; so, to
each his own.

I know this could be written

   platform_audio_files = (audio_stems.map { |f|
      f + "." + audio_ext[platform]
   } + audio_basenames).map { |f|
      File.join(audio_dir, f)
   }

but I find that uncouth compared to the former.

If ruby is adding anything, it should be the behavior of Object#as,
not Object#tap.

You are suggesting that people add something that probably doesn't
need to be added. I'm halfway convinced, but I think you should
present a couple more use cases for me to sway your way (sorry, folks,
for the poetic language :slight_smile:

Todd

···

On Nov 12, 2007 1:10 PM, <furtive.clown@gmail.com> wrote:

Martin DeMello wrote:

···

On Nov 12, 2007 11:10 AM, <furtive.clown@gmail.com> wrote:

This is the first I've heard of Object#tap. It seems backward because
you almost always want the result of the block, not the object back
again.

#tap is the opposite use case - you want to "tap" the object stream,
observing without affecting. It's very handy for debugging, where you
can tap into a chain of method calls, print something out and continue
on your way, e.g.

foo.map(&:bar).tap {|a| p a}.inject...

martin

That's a great example of a use-case for #tap. (I think I remember that
from the original discussion of the feature.) But the K-combinator style
side-effect is valid too. Just look at all the uses of #returning in
Rails.

--
Posted via http://www.ruby-forum.com/\.

OK I understand Object#tap now. At first I thought the motivation was
to modify the object inside the block, but now I see that it can be a
useful part of functional-style ruby.

So, to throw this out again --- there should also be Object#as which
returns the block result (I like the name 'as' but I am not
particularly attached to it). I can personally attest to its
usefulness, and I can show reams of examples in addition to the above
one I gave.

···

On Nov 12, 2:31 pm, Martin DeMello <martindeme...@gmail.com> wrote:

On Nov 12, 2007 11:10 AM, <furtive.cl...@gmail.com> wrote:

> This is the first I've heard of Object#tap. It seems backward because
> you almost always want the result of the block, not the object back
> again.

#tap is the opposite use case - you want to "tap" the object stream,
observing without affecting.

Well, I don't want a block which is evaluated in the instance's
context. Why would I even risk doing that? What if I want to use the
"self" before the instance_eval? What if I use "self" inside the
block while forgetting that I'm inside an instance_eval? I'd be
screwed for no reason.

The use instance_eval communicates a specific purpose which entirely
different from the purpose of Object#as. I want to take the current
object, name it *as* something, perform some operations on it, and
give the result.

The current object should not be given the name "self", which is a
special name. It should be given a temporary name (e.g. "t") which
communicates its temporal non-specialness. Object#instance_eval is
the former, Object#as is the latter.

···

On Nov 12, 4:06 pm, Robert Dober <robert.do...@gmail.com> wrote:

On Nov 12, 2007 8:10 PM, <furtive.cl...@gmail.com> wrote:

> This is the first I've heard of Object#tap. It seems backward because
> you almost always want the result of the block, not the object back
> again. All of my ruby scripts use

> class Object
> def as
> yield self
> end
> end

I am so glad, I really needed Object#itself in Labrador, somehow I
felt alone with this approach, now it seems i am not that weird after
all.

I however adhere with Ara's POV, what is there that instance_eval
cannot give you?

quite true. still, i personally think such a cozy method as tap/whatever *should* be in the instance scope - otherwise it is just eye candy.

cheers.

a @ http://codeforpeople.com/

···

On Nov 12, 2007, at 2:15 PM, Joel VanderWerf wrote:

Really?

There is the scope issue. I use this construct sometimes:

--
we can deny everything, except that we have the possibility of being better. simply reflect on that.
h.h. the 14th dalai lama

I guess I want to see some more examples, because I'm seriously doubting the usefulness. The example you showed so far was using it to create this:

    platform_audio_files = audio_stems.map { |f|
       f + "." + audio_ext[platform]
    }.as { |t|
       t + audio_basenames
    }.map { |f|
       File.join(audio_dir, f)
    }

instead of:

    platform_audio_files = (audio_stems.map { |f|
       f + "." + audio_ext[platform]
    } + audio_basenames).map { |f|
       File.join(audio_dir, f)
    }

I don't really understand what the problem is with the second version that's shorter and easier for me to understand. If it's the need to introduce some parentheses into the call chain, we can fix that:

    platform_audio_files = audio_stems.map { |f|
       f + "." + audio_ext[platform]
    }.concat(audio_basenames).map { |f|
       File.join(audio_dir, f)
    }

So yes, please send more examples as I remain unconvinced.

James Edward Gray II

···

On Nov 12, 2007, at 2:40 PM, furtive.clown@gmail.com wrote:

So, to throw this out again --- there should also be Object#as which
returns the block result (I like the name 'as' but I am not
particularly attached to it). I can personally attest to its
usefulness, and I can show reams of examples in addition to the above
one I gave.

Understood, I actually just started to grasp the concept of "this", thx.
R.

···

On Nov 12, 2007 10:55 PM, <furtive.clown@gmail.com> wrote:

On Nov 12, 4:06 pm, Robert Dober <robert.do...@gmail.com> wrote:
> On Nov 12, 2007 8:10 PM, <furtive.cl...@gmail.com> wrote:
>
> > This is the first I've heard of Object#tap. It seems backward because
> > you almost always want the result of the block, not the object back
> > again. All of my ruby scripts use
>
> > class Object
> > def as
> > yield self
> > end
> > end
>
> I am so glad, I really needed Object#itself in Labrador, somehow I
> felt alone with this approach, now it seems i am not that weird after
> all.
>
> I however adhere with Ara's POV, what is there that instance_eval
> cannot give you?

Well, I don't want a block which is evaluated in the instance's
context. Why would I even risk doing that? What if I want to use the
"self" before the instance_eval? What if I use "self" inside the
block while forgetting that I'm inside an instance_eval? I'd be
screwed for no reason.

The use instance_eval communicates a specific purpose which entirely
different from the purpose of Object#as. I want to take the current
object, name it *as* something, perform some operations on it, and
give the result.

The current object should not be given the name "self", which is a
special name. It should be given a temporary name (e.g. "t") which
communicates its temporal non-specialness. Object#instance_eval is
the former, Object#as is the latter.

--
what do I think about Ruby?
http://ruby-smalltalk.blogspot.com/

# On Nov 12, 2:31 pm, Martin
# > #tap is the opposite use case - you want to "tap" the object stream,
# > observing without affecting.
# OK I understand Object#tap now. At first I thought the motivation was
# to modify the object inside the block, but now I see that it can be a
# useful part of functional-style ruby.
# So, to throw this out again --- there should also be Object#as which
# returns the block result (I like the name 'as' but I am not
# particularly attached to it). I can personally attest to its
# usefulness, and I can show reams of examples in addition to the above
# one I gave.

(my previous message seems to have lost, so i apologize for a 2nd post)

tap is indispensable for me when it comes to chaining (specially bang methods)..

naive example follows...

~> s
=> "This is a test"

~> s.capitalize!.capitalize!
NoMethodError: undefined method `capitalize!' for nil:NilClass

breaks!

~> s.upcase!.upcase!
=> nil

breaks!

~> s.upcase!.capitalize!
NoMethodError: undefined method `capitalize!' for nil:NilClass

breaks!

~> s.tap(&:upcase!).tap(&:upcase!).tap(&:capitalize!).tap(&:capita
lize!).tap(&:downcase!).tap(&:downcase!)
=> "this is a test"

long chain, no break :slight_smile:

btw, i like the #tap name, it's like tapping a chain so that it wont break. (i'm not an english expert but that is how i usually use the word)..

kind regards -botp

···

From: furtive

# > > This is the first I've heard of Object#tap. It seems
# backward because
# > > you almost always want the result of the block, not the
# object back
# > > again.
# > #tap is the opposite use case - you want to "tap" the object stream,
# > observing without affecting.

···

From: furtive.clown@gmail.com [mailto:furtive.clown@gmail.com]
# On Nov 12, 2:31 pm, Martin DeMello <martindeme...@gmail.com> wrote:
# > On Nov 12, 2007 11:10 AM, <furtive.cl...@gmail.com> wrote:
#
# OK I understand Object#tap now. At first I thought the motivation was
# to modify the object inside the block, but now I see that it can be a
# useful part of functional-style ruby.

~> s
=> "THIS IS A TEST"
~> s.upcase!.capitalize!
NoMethodError: undefined method `capitalize!' for nil:NilClass
...
~> s.tap{|x| x.upcase!}.capitalize!
=> "This is a test"
~> s
=> "This is a test"

C:\ruby1.9\bin>ri Object#tap -T
------------------------------------------------------------- Object#tap
     obj.tap{|x|...} => obj
------------------------------------------------------------------------
     Returns the receiver after executing the block given. Its main
     purpose is to be inserted in the method chain.

kind regards -botp
The essence of knowledge, is having it, to apply it;..

It was only a coincidence that you found an Array method which
corresponded to the operation in the block, namely Array#concat. Your
example breaks down once the operation is nontrivial --- something
more complex than '+'.

We can also introduce temporaries inside the block without causing
distraction in the outer scope. The purpose of the block chain is to
produce a value for platform_audio_files; a flood temporary variables
on the same scope obscures this purpose.

···

On Nov 12, 3:55 pm, James Edward Gray II <ja...@grayproductions.net> wrote:

On Nov 12, 2007, at 2:40 PM, furtive.cl...@gmail.com wrote:

I guess I want to see some more examples, because I'm seriously
doubting the usefulness. The example you showed so far was using it
to create this:

    platform_audio_files = audio_stems.map { |f|
       f + "." + audio_ext[platform]
    }.as { |t|
       t + audio_basenames
    }.map { |f|
       File.join(audio_dir, f)
    }

instead of:

    platform_audio_files = (audio_stems.map { |f|
       f + "." + audio_ext[platform]
    } + audio_basenames).map { |f|
       File.join(audio_dir, f)
    }

I don't really understand what the problem is with the second version
that's shorter and easier for me to understand. If it's the need to
introduce some parentheses into the call chain, we can fix that:

    platform_audio_files = audio_stems.map { |f|
       f + "." + audio_ext[platform]
    }.concat(audio_basenames).map { |f|
       File.join(audio_dir, f)
    }

So yes, please send more examples as I remain unconvinced.