Cascading message sends

In Smalltalk, which Ruby is much like in some ways, you can 'cascade’
message sends. That is, call a bunch of methods on the same object
without naming it explicitly over and over. Eg:

 aCollection add: 5; add: 7; add: 'foo' !

calls ‘add’ on ‘aCollection’ 3 times, sending 5, 7, and ‘foo’.

Does Ruby have this syntax?

cheers:)
PMG

···

PS: yes, you can fake it, if you make the method return ‘self’: you
just chain the methods together. In Smalltalk:

 ((aCollection add: 5) add: 7) add: 'foo' !

But the ‘;’ operator is needed for the case when the method returns
something other than ‘self’ - eg for instance, the object just added.
In which case clearly this ‘cheat’ doesn’t work!

Paul MG wrote:

In Smalltalk, which Ruby is much like in some ways, you can ‘cascade’
message sends. That is, call a bunch of methods on the same object
without naming it explicitly over and over. Eg:

 aCollection add: 5; add: 7; add: 'foo' !

calls ‘add’ on ‘aCollection’ 3 times, sending 5, 7, and ‘foo’.

Does Ruby have this syntax?

Here’s one option, not as elegant:

x=
x.instance_eval do
push 1
push 2
push 3
end
p x

Inside the do…end block, “self” is x.

Others have mentioned a couple ways to do this generally, but
I just wanted to point out that you can do this without any
special syntax as long as the methods involved return `self’ -
which many do, including Array#push:

aCollection = []
aCollection.push(5).push(7).push('foo')
[5, 7, "foo"]

Array#<< does, too, and long chains with it have less
syntactic clutter:

aCollection << 4 << 3 << 2
[5, 7, "foo", 4, 3, 2]

-Mark

···

On Sat, Jan 31, 2004 at 11:16:50AM -0800, Paul MG wrote:

In Smalltalk, which Ruby is much like in some ways, you can ‘cascade’
message sends. That is, call a bunch of methods on the same object
without naming it explicitly over and over. Eg:

 aCollection add: 5; add: 7; add: 'foo' !

calls ‘add’ on ‘aCollection’ 3 times, sending 5, 7, and ‘foo’.

Does Ruby have this syntax?

Joel VanderWerf wrote:

Here’s one option, not as elegant:

x=
x.instance_eval do
push 1
push 2
push 3
end
p x

Inside the do…end block, “self” is x.

Note that you can wrap this into a nicer looking syntax, similar to
JavaScript:

module Kernel
def with(o, &blk)
o.instance_eval &blk
end
end

x =

with x do
push 1
push 2
push 3
end

p x

I’m not sure if you can get something that looks like Smalltalk. I’ll
think about it
and see what I can come up with (unless someone beats me to it).

  • Dan

What about this:

[gus@gusmac tmp]$ cat chain.rb
#! /usr/bin/ruby -w

class Chain
def initialize(o)
@o = o
end

def method_missing(msg, *args)
@o.send(msg, *args)
@o
end
end

class Object
def chain
Chain.new(self)
end
end

a = [0, 1, 2, 3]
a.chain.delete_at(2).delete_at(1)
p a

[gus@gusmac tmp]$ ruby chain.rb
[0, 3]

Guillaume.

···

Le 31 janv. 04, à 16:19, Mark J. Reed a écrit :

On Sat, Jan 31, 2004 at 11:16:50AM -0800, Paul MG wrote:

In Smalltalk, which Ruby is much like in some ways, you can ‘cascade’
message sends. That is, call a bunch of methods on the same object
without naming it explicitly over and over. Eg:

 aCollection add: 5; add: 7; add: 'foo' !

calls ‘add’ on ‘aCollection’ 3 times, sending 5, 7, and ‘foo’.

Does Ruby have this syntax?

Others have mentioned a couple ways to do this generally, but
I just wanted to point out that you can do this without any
special syntax as long as the methods involved return `self’ -
which many do, including Array#push:

aCollection = []
aCollection.push(5).push(7).push('foo')
[5, 7, "foo"]

Array#<< does, too, and long chains with it have less
syntactic clutter:

aCollection << 4 << 3 << 2
[5, 7, "foo", 4, 3, 2]

-Mark

“Mark J. Reed” markjreed@mail.com wrote in message news:20040131211520.GA15084@mulan.thereeds.org

I just wanted to point out that you can do this without any
special syntax as long as the methods involved return `self’ -
which many do, including Array#push.

It’s lucky that in Ruby Array#push and Array#<< do return self; unlike
Smalltalk’s Collection>>add: anItem which returns anItem (I believe).

However as I said in the PS to my original post, I was curious about
what can be done in Ruby in the general case.

Aside: The things people have been able to do in suggesting ways to
get this behaviour have really illustrated to me the power of the
language: there seems to be something almost LISP-like in the way you
can extend nearly everything about the language, eg adding methods to
Object, Kernel, etc. Very impressive. I think Python is cute (and i
have to admit to preferring syntactically-significant-indentation to
ruby’s “end” keyword) but Ruby seems to clearly trounce it for sheer
power.

Thanks for everyone’s thoughts!

cheers:)
Paul

What about this:

Nice. A little correction below:

[gus@gusmac tmp]$ cat chain.rb
#! /usr/bin/ruby -w

class Chain
def initialize(o)
@o = o
end

def method_missing(msg, *args)
@o.send(msg, *args)
@o
self

As an o’s method you call may not return o itself (like bang methods).
And this way you can have as long a chain as you need.

end
end

class Object
def chain
Chain.new(self)
end
end

a = [0, 1, 2, 3]
a.chain.delete_at(2).delete_at(1)
p a

[gus@gusmac tmp]$ ruby chain.rb
[0, 3]

Guillaume.

In Smalltalk, which Ruby is much like in some ways, you can ‘cascade’
message sends. That is, call a bunch of methods on the same object
without naming it explicitly over and over. Eg:

 aCollection add: 5; add: 7; add: 'foo' !

calls ‘add’ on ‘aCollection’ 3 times, sending 5, 7, and ‘foo’.

Does Ruby have this syntax?

Others have mentioned a couple ways to do this generally, but
I just wanted to point out that you can do this without any
special syntax as long as the methods involved return `self’ -
which many do, including Array#push:

aCollection = []
aCollection.push(5).push(7).push('foo')
[5, 7, "foo"]

Array#<< does, too, and long chains with it have less
syntactic clutter:

aCollection << 4 << 3 << 2
[5, 7, "foo", 4, 3, 2]

-Mark

Sincerely,
Gennady Bystritsky

···

On Jan 31, 2004, at 14:11, Guillaume Marcais wrote:

Le 31 janv. 04, à 16:19, Mark J. Reed a écrit :

On Sat, Jan 31, 2004 at 11:16:50AM -0800, Paul MG wrote: