cascading message sends

P

Paul MG

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!
 
J

Joel VanderWerf

Paul said:
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.
 
D

Dan Doel

Joel said:
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
 
G

Guillaume Marcais

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 :
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
 
G

Gennady

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.

Le 31 janv. 04, à 16:19, Mark J. Reed a écrit :
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
 
P

Paul MG

Mark J. Reed said:
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
 

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,142
Messages
2,570,819
Members
47,367
Latest member
mahdiharooniir

Latest Threads

Top