[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Re: Pass block instead of here document?

Gavin Kistner

10/25/2006 7:32:00 PM

From: Morton Goldberg [mailto:m_goldberg@ameritech.net]
> I'd rather pass in a block. Is there a way to do that? Something like:
>
> <pseud-code>
> 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
> </pseud-code>

def tell( obj, &to_do )
obj.instance_eval( &to_do )
end

class Foo
def say_hi
p "Hi!"
end
end

tell Foo.new do
say_hi
end
#=> "Hi!"

13 Answers

Morton Goldberg

10/25/2006 7:45:00 PM

0

On Oct 25, 2006, at 3:31 PM, Gavin Kistner wrote:

> From: Morton Goldberg [mailto:m_goldberg@ameritech.net]
>> I'd rather pass in a block. Is there a way to do that? Something
>> like:
>>
>> <pseud-code>
>> 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
>> </pseud-code>
>
> def tell( obj, &to_do )
> obj.instance_eval( &to_do )
> end
>
> class Foo
> def say_hi
> p "Hi!"
> end
> end
>
> tell Foo.new do
> say_hi
> end
> #=> "Hi!"

It's really that easy? Amazing! Ruby makes things so easy compared
with the other languages I've used that I'm constantly inventing hard
ways of doing what is too obvious for me to see.

Thanks for your help.

Regards, Morton



dblack

10/25/2006 7:54:00 PM

0

Morton Goldberg

10/25/2006 8:09:00 PM

0


On Oct 25, 2006, at 3:54 PM, dblack@wobblini.net wrote:

> Hi --
>
> On Thu, 26 Oct 2006, Morton Goldberg wrote:
>
>> On Oct 25, 2006, at 3:31 PM, Gavin Kistner wrote:
>>
>>> From: Morton Goldberg [mailto:m_goldberg@ameritech.net]
>>>> I'd rather pass in a block. Is there a way to do that? Something
>>>> like:
>>>> <pseud-code>
>>>> 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
>>>> </pseud-code>
>>> def tell( obj, &to_do )
>>> obj.instance_eval( &to_do )
>>> end
>>> class Foo
>>> def say_hi
>>> p "Hi!"
>>> end
>>> end
>>> tell Foo.new do
>>> say_hi
>>> end
>>> #=> "Hi!"
>>
>> It's really that easy? Amazing! Ruby makes things so easy compared
>> with the other languages I've used that I'm constantly inventing
>> hard ways of doing what is too obvious for me to see.
>
> It's easy, but it can also be a bit obfuscating. For example:
>
> class C
> def initialize(thing)
> @thing = thing
> end
>
> def tell(&block)
> instance_eval(&block)
> end
> end
>
> c = C.new("Hi")
>
> @thing = "Hello"
> c.tell do
> puts @thing # Hi
> end
>
> So you get some perhaps unwanted variable-shadowing, and similarly
> with method calls.

I would expect that behavior and, in the situation I'm dealing with,
I think it's an acceptable trade-off.

Regards, Morton



James Gray

10/25/2006 8:09:00 PM

0

On Oct 25, 2006, at 2:54 PM, dblack@wobblini.net wrote:

> It's easy, but it can also be a bit obfuscating. For example:
>
> class C
> def initialize(thing)
> @thing = thing
> end
>
> def tell(&block)
> instance_eval(&block)
> end
> end
>
> c = C.new("Hi")
>
> @thing = "Hello"
> c.tell do
> puts @thing # Hi
> end
>
> So you get some perhaps unwanted variable-shadowing, and similarly
> with method calls.

Greg Brown and I were playing around with a solution for the method
call issue at RubyConf. Here's the code we came up with:

class C
def initialize(thing)
@thing = thing
end

attr_reader :thing

def tell(&block)
if block and block.arity == 1
block[self]
else
instance_eval(&block)
end
end
end

def thing; "Hello" end

c = C.new("Hi")

c.tell do
thing # => "Hi"
end

c.tell do |obj|
thing # => "Hello"
obj.thing # => "Hi"
end

I know people frown on the instance_eval() trick, but this seems to
be less of a problem. You can just choose to use the variable when
you need it.

Just a thought.

James Edward Gray II


Joel VanderWerf

10/25/2006 9:39:00 PM

0

James Edward Gray II wrote:
> On Oct 25, 2006, at 2:54 PM, dblack@wobblini.net wrote:
>
>> It's easy, but it can also be a bit obfuscating. For example:
>>
>> class C
>> def initialize(thing)
>> @thing = thing
>> end
>>
>> def tell(&block)
>> instance_eval(&block)
>> end
>> end
>>
>> c = C.new("Hi")
>>
>> @thing = "Hello"
>> c.tell do
>> puts @thing # Hi
>> end
>>
>> So you get some perhaps unwanted variable-shadowing, and similarly
>> with method calls.
>
> Greg Brown and I were playing around with a solution for the method call
> issue at RubyConf. Here's the code we came up with:
>
> class C
> def initialize(thing)
> @thing = thing
> end
>
> attr_reader :thing
>
> def tell(&block)
> if block and block.arity == 1
> block[self]
> else
> instance_eval(&block)
> end
> end
> end
>
> def thing; "Hello" end
>
> c = C.new("Hi")
>
> c.tell do
> thing # => "Hi"
> end
>
> c.tell do |obj|
> thing # => "Hello"
> obj.thing # => "Hi"
> end
>
> I know people frown on the instance_eval() trick, but this seems to be
> less of a problem. You can just choose to use the variable when you
> need it.

I dunno... the presence of "|obj|" changes the semantics of the rest of
the block. It's so easy to comment out the |obj| and then suddenly
methods are handled in a surprising way:

c.tell do |obj|
thing # => "Hello"
end

c.tell do #|obj|
thing # => "Hi"
end

Visually, it doesn't look like anything important has changed.

Seems like a bug magnet.

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

Ken Bloom

10/26/2006 12:44:00 AM

0

On Thu, 26 Oct 2006 04:31:31 +0900, Gavin Kistner wrote:

> From: Morton Goldberg [mailto:m_goldberg@ameritech.net]
>> I'd rather pass in a block. Is there a way to do that? Something like:
>>
>> <pseud-code>
>> 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
>> </pseud-code>
>
> def tell( obj, &to_do )
> obj.instance_eval( &to_do )
> end

Heck. Why bother with tell in the first place? Why not call instance_eval
directly?

--Ken

--
Ken Bloom. PhD candidate. Linguistic Cognition Laboratory.
Department of Computer Science. Illinois Institute of Technology.
http://www.iit.edu...
I've added a signing subkey to my GPG key. Please update your keyring.

dblack

10/26/2006 3:30:00 AM

0

Tim Pease

10/26/2006 3:33:00 AM

0

On 10/25/06, James Edward Gray II <james@grayproductions.net> wrote:
>
> I know people frown on the instance_eval() trick, but this seems to
> be less of a problem. You can just choose to use the variable when
> you need it.
>

James, why do people frown upon instance_eval? I know you cannot speak
for all people, but what are the reasons to avoid it?

My only guess is that it would be slower than calling the block
directly -- block[self] -- as you showed in the code example.

Thoughts?

TwP

Ara.T.Howard

10/26/2006 3:42:00 AM

0

Morton Goldberg

10/26/2006 5:29:00 AM

0

On Oct 25, 2006, at 8:45 PM, Ken Bloom wrote:

> On Thu, 26 Oct 2006 04:31:31 +0900, Gavin Kistner wrote:
>
>> From: Morton Goldberg [mailto:m_goldberg@ameritech.net]
>>> I'd rather pass in a block. Is there a way to do that? Something
>>> like:
>>>
>>> <pseud-code>
>>> 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
>>> </pseud-code>
>>
>> def tell( obj, &to_do )
>> obj.instance_eval( &to_do )
>> end
>
> Heck. Why bother with tell in the first place? Why not call
> instance_eval
> directly?

Syntactic sugar. I guess I have a sweet tooth.

Regards, Morton