# Pass block instead of here document?

**URL:** <https://www.ruby-forum.com/t/pass-block-instead-of-here-document/73634>\
**Category:** Ruby\
**Created:** [October 25, 2006, 9:26pm UTC](https://www.ruby-forum.com/t/pass-block-instead-of-here-document/73634 "2006-10-25T21:26:34Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Morton\_G](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/dfb087/32.png) [@Morton\_G](https://www.ruby-forum.com/u/Morton_G)\
**Post date:** [October 25, 2006, 9:26pm UTC](https://www.ruby-forum.com/t/pass-block-instead-of-here-document/73634/1 "2006-10-25T21:26:34Z")

</div>

I have a situation where I want to send many messages, one after the  
other, to single object. Instead of writing, say,

```
foo.eat burger, fries
foo.drink beer
foo.be_merry

```

I want to be able to write something like:

foo.perform { eat burger, fries; drink beer; be\_merry }

I’m not much at meta-programming. The best I’ve been able to come up  
with so far is:

`
#! /usr/bin/env ruby -w
class Foo
def report
defined_here = (methods - Object.methods).join(", ")
puts “#{self.class.name} defines: " + defined_here
end
def say(text)
puts %[#{inspect} says “#{text}”]
end
def eat(*food)
food = food.join(” and ")
say “Downing #{food}. Yum, yum, yum!”
end
def drink(beverage)
say “Chug, chug, chug”
end
def be_merry
say “What, me worry?”
end
end
module Kernel
def tell(obj, to_do)
obj.instance_eval(to_do)
end
end
tell Foo.new, <<TO_DO
report
eat ‘burger’, ‘fries’
drink ‘beer’
be_merry
TO_DO
`

Although this works, it offends my sense of programming esthetics.  
I’d rather pass in a block. Is there a way to do that? Something like:

module Kernel def tell(obj, &to\_do) # what goes here? end end

tell Foo.new do  
report  
eat ‘burger’, ‘fries’  
drink ‘beer’  
be\_merry  
end

Instead of a Kernel#tell method, a Foo#perform method would be OK:

Foo.new.perform { report; eat 'burger', 'fries'; drink 'beer'; be\_merry }

Regards, Morton

---

<div class="post-metadata">

**Author:** ![Morton\_G](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/dfb087/32.png) [@Morton\_G](https://www.ruby-forum.com/u/Morton_G)\
**Post date:** [October 25, 2006, 9:40pm UTC](https://www.ruby-forum.com/t/pass-block-instead-of-here-document/73634/2 "2006-10-25T21:40:38Z")

</div>

On 10/25/06, Morton G. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> I have a situation where I want to send many messages, one after the  
> other, to single object. Instead of writing, say,

> Foo.new.perform { report; eat 'burger', 'fries'; drink 'beer'; be\_merry }

class Foo  
def initialize( &block )  
return unless block\_given?  
self.instance\_eval &block  
end

def eat( \*args )  
puts args.inspect  
end

def drink( \*args )  
puts args.inspect  
end  
end

Foo.new do  
eat ‘burger’, ‘fries’  
drink ‘beer’  
end

Is that what you are looking for? You can just as easily create a  
process method (instead of using the initialize method) to do  
something like this …

f = Foo.new  
f.process do  
eat ‘burger’, ‘fries’  
drink ‘beer’  
end

Blessings,  
TwP

---

<div class="post-metadata">

**Author:** ![Morton\_G](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/dfb087/32.png) [@Morton\_G](https://www.ruby-forum.com/u/Morton_G)\
**Post date:** [October 25, 2006, 10:04pm UTC](https://www.ruby-forum.com/t/pass-block-instead-of-here-document/73634/3 "2006-10-25T22:04:40Z")

</div>

On Oct 25, 2006, at 3:39 PM, Tim P. wrote:

> > 
> 
> end  
> end
> 
> Blessings,  
> TwP

It’s the second way that I was looking for. Now that I know that  
Object#instance\_eval will accept a block, I can see how easy it is to  
write Foo#perform

Thanks for your help.

Regards, Morton

---

<div class="post-metadata">

**Author:** ![Morton\_G](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/dfb087/32.png) [@Morton\_G](https://www.ruby-forum.com/u/Morton_G)\
**Post date:** [October 26, 2006, 1:55am UTC](https://www.ruby-forum.com/t/pass-block-instead-of-here-document/73634/4 "2006-10-26T01:55:01Z")

</div>

On 10/25/06, Morton G. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> I have a situation where I want to send many messages, one after the  
> other, to single object. Instead of writing, say,
> 
> ```
> foo.eat burger, fries
> foo.drink beer
> foo.be_merry
> 
> ```
> 
> I want to be able to write something like:
> 
> foo.perform { eat burger, fries; drink beer; be\_merry }

Others have already answered your question, but the above syntax  
reminds me of one thing in Smalltalk which I miss a bit in Ruby.

Smalltalk has very little syntax, but one piece is the use of  
semicolons to do what Smalltalk calls message cascading. As in Ruby  
each method in Smalltalk returns a value and if you write something  
like:

obj msg1 msg2

This sends msg1 to obj, and then sends msg2 to the value returned by  
obj msg1, much like the equivalent ruby syntax:

obj.msg1.msg2

But in Smalltalk if you write:

obj msg1;msg2

the object referenced by obj is sent msg1 and then msg2 in sequence,  
regardless of the value returned by obj msg1.

Since Ruby doesn’ t have such syntax, it’s probably not missed much,  
but since Smalltalk did it was pretty heavily used. Smalltalk also  
had a method in Object called yourself which returned the receiver  
which is commonly used as the last message in such a cascade on the  
right hand side of an assignment.

–  
Rick DeNatale

My blog on Ruby  
[http://talklikeaduck.denhaven2.com/](http://talklikeaduck.denhaven2.com/)

---

<div class="post-metadata">

**Author:** ![Morton\_G](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/dfb087/32.png) [@Morton\_G](https://www.ruby-forum.com/u/Morton_G)\
**Post date:** [October 26, 2006, 6:51am UTC](https://www.ruby-forum.com/t/pass-block-instead-of-here-document/73634/5 "2006-10-26T06:51:32Z")

</div>

Rick DeNatale wrote:  
…

> But in Smalltalk if you write:
> 
> obj msg1;msg2
> 
> the object referenced by obj is sent msg1 and then msg2 in sequence,  
> regardless of the value returned by obj msg1.

Not quite the same, but this is something similar that’s been floating  
around the ml for a while:

class Object  
def then  
yield(self)  
self  
end  
end

hash = Hash.new.  
then do |h| h[1] = 2 end.  
then do |h| h[3] = 4 end

p hash

That’s much clunkier syntactically, but it is actually useful in one  
case: when working with classes whose #new method doesn’t take a block  
that allows further configuration of the new object. For example,  
sockets:

def socket  
@socket ||= UDPSocket.open.then do |s|  
s.setsockopt(Socket::SOL\_SOCKET, Socket::SO\_BROADCAST, true)  
s.connect(“192.168.255.255”, 1234)  
end  
end

It works particularly well with the ||= assignment operator.

Without the #then method you can’t use ||= and it’s just a little  
clunkier:

def socket  
unless @socket  
@socket = UDPSocket.open  
@socket.setsockopt(Socket::SOL\_SOCKET, Socket::SO\_BROADCAST, true)  
@socket.connect(“255.255.255.255”, 1234)  
end  
@socket  
end

---

<div class="post-metadata">

**Author:** ![Morton\_G](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/dfb087/32.png) [@Morton\_G](https://www.ruby-forum.com/u/Morton_G)\
**Post date:** [October 26, 2006, 8:02pm UTC](https://www.ruby-forum.com/t/pass-block-instead-of-here-document/73634/6 "2006-10-26T20:02:32Z")

</div>

Rick DeNatale wrote:

> > Not quite the same, but this is something similar that’s been floating  
> > then do |h| h[1] = 2 end.  
> > @socket ||= UDPSocket.open.then do |s|  
> > s.setsockopt(Socket::SOL\_SOCKET, Socket::SO\_BROADCAST, true)  
> > s.connect(“192.168.255.255”, 1234)  
> > end  
> > end
> 
> Of course this relies on UDPSocket::open returning the new socket  
> rather than something else.

UDPSocket.open is the same as UDPSocket.new, which returns the new  
socket, as is standard for all #new methods.

Actually, UDPSocket _does_ take a block, so you don’t need this  
construct here. It’s for those cases (getting rarer and rarer as ruby  
libs evolve) where someone defines an #initialize method that does not  
take a block (or takes a block but does not yield the object to it).

> > It works particularly well with the ||= assignment operator.
> 
> Which in turn relies on the block evaluating to the socket as well.

Actually, no. The value of the block is discarded, and #then returns the  
receiver. That’s the point of the #then method. It yields self and then  
returns self.

> It’s more of a variation on Smalltalk’s yourself than a cascade.
> 
> Nice nonetheless.

Thanks!

---

<div class="post-metadata">

**Author:** ![Morton\_G](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/dfb087/32.png) [@Morton\_G](https://www.ruby-forum.com/u/Morton_G)\
**Post date:** [October 26, 2006, 6:34pm UTC](https://www.ruby-forum.com/t/pass-block-instead-of-here-document/73634/7 "2006-10-26T18:34:19Z")

</div>

On 10/26/06, Joel VanderWerf [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> around the ml for a while:  
> then do |h| h[3] = 4 end  
> s.connect(“192.168.255.255”, 1234)  
> end  
> end

Of course this relies on UDPSocket::open returning the new socket  
rather than something else.

> It works particularly well with the ||= assignment operator.

Which in turn relies on the block evaluating to the socket as well.

It’s more of a variation on Smalltalk’s yourself than a cascade.

Nice nonetheless.

–  
Rick DeNatale

My blog on Ruby  
[http://talklikeaduck.denhaven2.com/](http://talklikeaduck.denhaven2.com/)

---

<div class="post-metadata">

**Author:** ![Morton\_G](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/dfb087/32.png) [@Morton\_G](https://www.ruby-forum.com/u/Morton_G)\
**Post date:** [October 27, 2006, 1:07am UTC](https://www.ruby-forum.com/t/pass-block-instead-of-here-document/73634/8 "2006-10-27T01:07:11Z")

</div>

Rick DeNatale wrote:

> > construct here. It’s for those cases (getting rarer and rarer as ruby  
> > libs evolve) where someone defines an #initialize method that does not  
> > take a block (or takes a block but does not yield the object to it).
> 
> Or does something else with the block like
> 
> Hash::new
> 
> which captures a block if given and uses it to handle requests for  
> missing keys.

Right. I shouldn’t have suggested that all #initialize methods should  
yield the object for further configuration, since there are plenty of  
other legitimate uses for blocks, such as this one.

---

<div class="post-metadata">

**Author:** ![Morton\_G](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/dfb087/32.png) [@Morton\_G](https://www.ruby-forum.com/u/Morton_G)\
**Post date:** [October 27, 2006, 12:35am UTC](https://www.ruby-forum.com/t/pass-block-instead-of-here-document/73634/9 "2006-10-27T00:35:06Z")

</div>

On 10/26/06, Joel VanderWerf [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Rick DeNatale wrote:

> > Of course this relies on UDPSocket::open returning the new socket  
> > rather than something else.
> 
> UDPSocket.open is the same as UDPSocket.new, which returns the new  
> socket, as is standard for all #new methods.
> 
> Actually, UDPSocket _does_ take a block, so you don’t need this  
> construct here. It’s for those cases (getting rarer and rarer as ruby  
> libs evolve) where someone defines an #initialize method that does not  
> take a block (or takes a block but does not yield the object to it).

Or does something else with the block like

Hash::new

which captures a block if given and uses it to handle requests for  
missing keys.

> > > It works particularly well with the ||= assignment operator.
> > 
> > Which in turn relies on the block evaluating to the socket as well.
> 
> Actually, no. The value of the block is discarded, and #then returns the  
> receiver. That’s the point of the #then method. It yields self and then  
> returns self.

Makes sense.

–  
Rick DeNatale

My blog on Ruby  
[http://talklikeaduck.denhaven2.com/](http://talklikeaduck.denhaven2.com/)
