Instance_eval

Hi all,

I am trying to add a method dynamically. I can do the following just fine:

def create
str = "def hello (*args) puts ‘test’ end"
self.instance_eval (str)
end

This adds the hello method. But I want to pass a block to test so that it
executes the block instead of the “puts ‘test’”.

I tried the following after searching some previous posts:

def create (&block)
str = "def hello (*args) block.call end"
self.instance_eval (str)
end

But to be honest I don’t really know what I am doing there. :wink: I realize
that instance_eval can take a block, but what name would the method be?

I will need to create multiple methods with different blocks, so I need them
to have different names.

Anyone have any pointers or places I can look?

TIA
John.

Hi –

Hi all,

I am trying to add a method dynamically. I can do the following just fine:

def create
str = "def hello (*args) puts ‘test’ end"
self.instance_eval (str)
end

This adds the hello method. But I want to pass a block to test so that it
executes the block instead of the “puts ‘test’”.

I tried the following after searching some previous posts:

def create (&block)
str = "def hello (*args) block.call end"
self.instance_eval (str)

I believe that “self.instance_eval” is essentially the same as plain
"eval", because instance_eval effectively sets the value of “self”,
temporarily, to its receiver – so setting it to “self” doesn’t change
anything. (Stay tuned for others pointing out possible subtleties
that I’m overlooking :slight_smile:

Here’s a little example of switching “self” on the fly, just for
contrast:

class Thing
def demo
puts “I am a #{type}” # => I am a Thing
s = "string"
s.instance_eval ‘puts “I am a #{type}”’ # => I am a String
end
end

end

But to be honest I don’t really know what I am doing there. :wink: I realize
that instance_eval can take a block, but what name would the method be?

I’m almost, but not quite, following your description… Which
method do you mean? Could you explain a little more about the
context? I think there might be useful things you could do along the
lines of, maybe, a hash of Proc objects, or something like that, but
I’m not sure what the best fit would be.

David

···

On Sun, 14 Jul 2002, John wrote:


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

“John” nojgoalbyspam@hotmail.com wrote in message news:_x2Y8.11504$Kx3.8405@newsread1.prod.itd.earthlink.net

I tried the following after searching some previous posts:

def create (&block)
str = "def hello (*args) block.call end"
self.instance_eval (str)
end

But to be honest I don’t really know what I am doing there.

I think you’re looking for this:

def create (&block)
self.class.define_method(:hello){block.call}
end

“John” nojgoalbyspam@hotmail.com wrote in message
news:_x2Y8.11504$Kx3.8405@newsread1.prod.itd.earthlink.net

Hi all,

I am trying to add a method dynamically. I can do the following just
fine:

def create
str = "def hello (*args) puts ‘test’ end"
self.instance_eval (str)
end

This adds the hello method. But I want to pass a block to test so that it
executes the block instead of the “puts ‘test’”.

I tried the following after searching some previous posts:

def create (&block)
str = "def hello (*args) block.call end"
self.instance_eval (str)
end

But to be honest I don’t really know what I am doing there. :wink: I realize
that instance_eval can take a block, but what name would the method be?

I will need to create multiple methods with different blocks, so I need
them
to have different names.

Anyone have any pointers or places I can look?

TIA
John.

So, without the define_method feature, I figured out, after re-reading page
47 of PR (for some bedtime reading), what I wasn’t doing.

What I needed to do was capture the block parameter into an instance
variable, and make my newly created method call it. The block parameter is
a proc object.

I don’t see a way to add a call to the block without storing the proc object
into an intermediate variable in the object.

John.

Sun, 14 Jul 2002 16:01:26 +0900, Avi Bryant avi@beta4.com pisze:

def create (&block)
self.class.define_method(:hello){block.call}
end

I think it’s equivalent to
self.class.define_method(:hello, &block)
which is more direct, can pass arguments etc.

···


__("< Marcin Kowalczyk
__/ qrczak@knm.org.pl
^^ http://qrnik.knm.org.pl/~qrczak/

“David Alan Black”

I believe that “self.instance_eval” is essentially the same as plain
"eval", because instance_eval effectively sets the value of “self”,
temporarily, to its receiver – so setting it to “self” doesn’t change
anything. (Stay tuned for others pointing out possible subtleties
that I’m overlooking :slight_smile:

I guess that is what they call hindsight?-) You overlooked that eval
is a private Kernel method that takes a Binding as a second optional
argument …

/Christoph

“David Alan Black” dblack@candle.superlink.net wrote in message
news:Pine.LNX.4.30.0207131952450.9723-100000@candle.superlink.net

Hi –

Hi all,

I am trying to add a method dynamically. I can do the following just
fine:

def create
str = "def hello (*args) puts ‘test’ end"
self.instance_eval (str)
end

This adds the hello method. But I want to pass a block to test so that
it

executes the block instead of the “puts ‘test’”.

I tried the following after searching some previous posts:

def create (&block)
str = "def hello (*args) block.call end"
self.instance_eval (str)

I believe that “self.instance_eval” is essentially the same as plain
"eval", because instance_eval effectively sets the value of “self”,
temporarily, to its receiver – so setting it to “self” doesn’t change
anything. (Stay tuned for others pointing out possible subtleties
that I’m overlooking :slight_smile:

Here’s a little example of switching “self” on the fly, just for
contrast:

class Thing
def demo
puts “I am a #{type}” # => I am a Thing
s = "string"
s.instance_eval ‘puts “I am a #{type}”’ # => I am a String
end
end

end

But to be honest I don’t really know what I am doing there. :wink: I
realize

that instance_eval can take a block, but what name would the method be?

I’m almost, but not quite, following your description… Which
method do you mean? Could you explain a little more about the
context? I think there might be useful things you could do along the
lines of, maybe, a hash of Proc objects, or something like that, but
I’m not sure what the best fit would be.

David


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

I am sorry, my examples were a little off. These should show it better.

Original attempt that works but without a block parameter:

def create (methodName)
str = "def " + methodName + " (*args) puts ‘test’ end"
self.instance_eval (str)
end

My attempt with a block:

def create (methodName, &block)
str = "def " + methodName + " (*args) block.call end"
self.instance_eval (str)
end

I want to call create something like this:

obj.create “newMethod” { puts “I am a new method” }
obj.create “anotherMethod” { puts “I am another method” }

and when I call newMethod it outputs the text “I am a new method”.
and when I call anotherMethod it outputs the text “I am another method”.

I could do this with a hash of proc objects like you suggested, but I would
prefer to do it using the instance_eval method as I think its cleaner (less
member variables), and I also want to learn if there is a way to associated
a block with a new method and name it.

I would also rather not pass a string for the method in to the create call.
I want to pass a block, mainly cause I want to see how to make use of the
block feature.

Make sense?

John.

···

On Sun, 14 Jul 2002, John wrote:

“Avi Bryant” avi@beta4.com wrote in message
news:6e869a6b.0207132252.7de2c70c@posting.google.com

“John” nojgoalbyspam@hotmail.com wrote in message
news:_x2Y8.11504$Kx3.8405@newsread1.prod.itd.earthlink.net

I tried the following after searching some previous posts:

def create (&block)
str = "def hello (*args) block.call end"
self.instance_eval (str)
end

But to be honest I don’t really know what I am doing there.

I think you’re looking for this:

def create (&block)
self.class.define_method(:hello){block.call}
end

Is this a 1.7 feature? Is it going to be in 1.8?

Thanks
John.

I think it's equivalent to
      self.class.define_method(:hello, &block)
which is more direct, can pass arguments etc.

Personnaly I think that #define_method is a *private* method :-)))

Guy Decoux

Is this a 1.7 feature? Is it going to be in 1.8?

1.6.2 feature, if I'm right.

Guy Decoux

By the way, Module#define_method could not define a method which takes
a block. Then I try to write unlimited version of define_method in
Ruby but could not. I found a bug in Ruby 1.6.7 instead.

% ruby -e ‘def a(&block) Proc.new{yield nil}.call(&block) end; a{|x| p x}’
-e:1: [BUG] Segmentation fault
ruby 1.6.7 (2002-05-23) [i386-freebsd4]
zsh: abort (core dumped) ruby -e ‘def a(&block) Proc.new{yield nil}.call(&block) end; a{|x| p x}’

Proc#call seems not being able to take a block. Is it difficult to
implement such function?

% ruby17 -ve 'def a(&block) Proc.new{yield nil}.call(&block) end; a{|x| p x}'
ruby 1.7.2 (2002-07-05) [i386-freebsd4.5]
-e:1: warning: block for Proc#call is useless
-e:1:in a': no block given (LocalJumpError) from -e:1:incall’
from -e:1:in `a’
from -e:1

– Gotoken

···

At Sun, 14 Jul 2002 18:57:11 +0900, ts wrote:

Is this a 1.7 feature? Is it going to be in 1.8?

1.6.2 feature, if I’m right.

“ts” decoux@moulon.inra.fr wrote in message
news:200207140952.g6E9qFh25967@moulon.inra.fr

Is this a 1.7 feature? Is it going to be in 1.8?

1.6.2 feature, if I’m right.

Guy Decoux

Yes, seems Module.define_method was a 1.6.2 feature. I assumed it was not
1.6.* because it was not in Pickaxe. I have since found the “features added
since 1.6.1” page located here :
http://www.pragmaticprogrammer.com/ruby/new_features.html.

I added this information in case someone else wondered about the method.

John.

“ts” decoux@moulon.inra.fr wrote in message
news:200207140952.g6E9qFh25967@moulon.inra.fr

Is this a 1.7 feature? Is it going to be in 1.8?

1.6.2 feature, if I’m right.

Guy Decoux

Yes, seems Module.define_method was a 1.6.2 feature. I assumed it was not
1.6.* because it was not in Pickaxe. I have since found the “features
added
since 1.6.1” page located here :
http://www.pragmaticprogrammer.com/ruby/new_features.html.

I added this information in case someone else wondered about the method.

Very interesting… but I have a question.

It doesn’t actually allow you to define an
arbitrary method, does it?

For example, the method definition syntax
allows:

def mymeth

rescue

ensure

end

Surely you can’t do that with define_method?

Hal Fulton

···

----- Original Message -----
From: “John” nojgoalbyspam@hotmail.com
Newsgroups: comp.lang.ruby
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Sunday, July 14, 2002 4:42 PM
Subject: Re: instance_eval

It doesn't actually allow you to define an
*arbitrary* method, does it?

Like said in [ruby-talk:44519], you can't (I think) give it a block.

def mymeth
...
rescue
...
ensure
...
end

For me this is just a syntactic sugar to

   def mymeth
      begin
      rescue
      ensure
      end
   end

Guy Decoux