Eval and block problems

  • Thread starter Brian Schröder
  • Start date
B

Brian Schröder

Please help me to wrap my mind around this. I want to achieve the following=
:

class A
def self.def_me(cmd, &block)
eval %(
def #{cmd}()
do things
# CALL BLOCK
end
)
end

def_me("foo") do
# access instance of A
end
end

A.new.foo

and have the block from the dynamically created method foo be
evaluated in the binding of the instance of A.

I'm sure this is possible, but I've never really grocked eval,
instance_eval and class_eval.

best regards,

Brian
 
D

David A. Black

--8323328-2093155883-1128275932=:3645
Content-Type: MULTIPART/MIXED; BOUNDARY="8323328-2093155883-1128275932=:3645"

This message is in MIME format. The first part should be readable text,
while the remaining parts are likely unreadable without MIME-aware tools.

--8323328-2093155883-1128275932=:3645
Content-Type: TEXT/PLAIN; charset=X-UNKNOWN; format=flowed
Content-Transfer-Encoding: QUOTED-PRINTABLE

Hi --

Please help me to wrap my mind around this. I want to achieve the followi= ng:

class A
def self.def_me(cmd, &block)
eval %(
def #{cmd}()
do things
# CALL BLOCK
end
)
end

def_me("foo") do
# access instance of A
end
end

A.new.foo

and have the block from the dynamically created method foo be
evaluated in the binding of the instance of A.

I'm sure this is possible, but I've never really grocked eval,
instance_eval and class_eval.

I doubt this is the final word in it but see if this helps:

class A
def self.def_me(cmd, &block)
define_method(cmd) do
puts "Defining method"
block.call(self)
end
end

def_me("foo") do |a|
puts "Here in block"
puts "self is #{self}, a is #{a}"
end
end

A.new.foo


David

--=20
David A. Black
(e-mail address removed)
--8323328-2093155883-1128275932=:3645--
--8323328-2093155883-1128275932=:3645--
 
R

Ryan Leavengood

Please help me to wrap my mind around this. I want to achieve the followi=
ng:
[code snipped]
and have the block from the dynamically created method foo be
evaluated in the binding of the instance of A.

I'm sure this is possible, but I've never really grocked eval,
instance_eval and class_eval.

Good question! Because by researching the answer I learned you can
just pass a block to define_method:

class A
def initialize(x)
@x =3D x
end

def self.def_me(cmd, &block)
define_method(cmd, &block)
end

def_me("foo") do
puts "x is #@x"
end
end

A.new(1).foo
A.new(2).foo
__END__

But strictly speaking in this case the separate def_me method is
redundant since you could just call define_method directly.

Ryan
 
B

Brian Schröder

Hi --

[snip question]

I doubt this is the final word in it but see if this helps:

class A
def self.def_me(cmd, &block)
define_method(cmd) do
puts "Defining method"
block.call(self)
end
end

def_me("foo") do |a|
puts "Here in block"
puts "self is #{self}, a is #{a}"
end
end

A.new.foo


David

Thank you david, I always forget about things like define_method.
Passing self back into the block was one solution I had thought about,
but it is not exactly pretty.

best regards,

Brian
 
B

Brian Schröder

Please help me to wrap my mind around this. I want to achieve the follo=
wing:
[code snipped]
and have the block from the dynamically created method foo be
evaluated in the binding of the instance of A.

I'm sure this is possible, but I've never really grocked eval,
instance_eval and class_eval.

Good question! Because by researching the answer I learned you can
just pass a block to define_method:

class A
def initialize(x)
@x =3D x
end

def self.def_me(cmd, &block)
define_method(cmd, &block)
end

def_me("foo") do
puts "x is #@x"
end
end

A.new(1).foo
A.new(2).foo
__END__

But strictly speaking in this case the separate def_me method is
redundant since you could just call define_method directly.

Ryan

Thank you ryan, it is incredible how fast there come really good
answers here. Combining your proposal and davids I have the following.
If I could get rid of the additional method, that would be perfect.

class A
def self.def_me(cmd, &block)
define_method("__#{cmd}", &block)

private "__#{cmd}"

define_method(cmd) do
puts "Defined method"
send("__#{cmd}")
end
end

def_me("foo") do
puts "Here in block"
puts "self is #{self}"
end
end

A.new.foo

regards,

Brian
 
D

Devin Mullins

Brian said:
and have the block from the dynamically created method foo be
evaluated in the binding of the instance of A.

I'm sure this is possible, but I've never really grocked eval,
instance_eval and class_eval.
=20
Not sure if this'll help, but it's something I'd thrown together awhile=20
back that attempted to the same sorta thing:

module Kernel
def multidef(name,&blk)
Multidef.new(self,name).instance_eval(&blk)
nil
end
end

class Multidef
def initialize(receiver, name)
@receiver =3D receiver
name =3D name.to_s
@name =3D name
@receiver.send:)define_method,name) do |*a|
send(name+a.size.to_s,*a)
end
end
def args arity, &blk
name =3D @name
@receiver.send:)define_method,@name+arity.to_s,&blk) #do |*a|
# if a.size !=3D arity then send(name+a.size.to_s,*a)
# else blk.call(*a) end #can I get this to execute in self.binding?
# end
end
end

multidef :[]=3D do
args 2 do |coord,val|
x,y =3D convert(coord)
self[x,y] =3D val
end
args 3 do |x,y,val|
@thing[x][y] =3D val
end
end

class Foo
multidef :fun do
args 1 do |a|
puts "one: #{a}"
end
args 2 do |a,b|
puts "two: #{a}, #{b}"
fun a
end
args 3 do |a,b,c|
puts "three: #{a}, #{b}, #{c}"
fun a,b
end
end
end

f =3D Foo.new
f.fun(1)
f.fun('a','b','c')
f.fun('hello',/nightmare/)
__END__

Problems:
1. super doesn't work across different arities.
2. Can't take blocks.

Devin
 
R

Robert Klemme

Brian Schröder said:
Please help me to wrap my mind around this. I want to achieve the
following: [code snipped]

and have the block from the dynamically created method foo be
evaluated in the binding of the instance of A.

I'm sure this is possible, but I've never really grocked eval,
instance_eval and class_eval.

Good question! Because by researching the answer I learned you can
just pass a block to define_method:

class A
def initialize(x)
@x = x
end

def self.def_me(cmd, &block)
define_method(cmd, &block)
end

def_me("foo") do
puts "x is #@x"
end
end

A.new(1).foo
A.new(2).foo
__END__

But strictly speaking in this case the separate def_me method is
redundant since you could just call define_method directly.

Ryan

Thank you ryan, it is incredible how fast there come really good
answers here. Combining your proposal and davids I have the following.
If I could get rid of the additional method, that would be perfect.

Just don't use the block for define_method but invoke it from the closure:

class A
def self.def_me(cmd,&block)
define_method(cmd) do
puts "preparation"
instance_eval &block
end
end

attr_accessor :name
end

a=A.new
a.name = "Einstein"

A.def_me:)foo) do
puts @name, self.name
end
preparation
Einstein
Einstein
=> nil

Kind regards

robert
 
B

Brian Schröder

Brian Schr=F6der said:

Just don't use the block for define_method but invoke it from the closure= :

class A
def self.def_me(cmd,&block)
define_method(cmd) do
puts "preparation"
instance_eval &block
end
end

attr_accessor :name
end

a=3DA.new
a.name =3D "Einstein"

A.def_me:)foo) do
puts @name, self.name
end
preparation
Einstein
Einstein
=3D> nil

Kind regards

robert

thanks a lot thats perfect. I have to wrap my mind around all the
different evals and definition methods and have them at hand when
needed. Theres a long way to go.

best regards,

Brian
 
R

Robert Klemme

Brian Schröder said:
Brian Schröder said:

Just don't use the block for define_method but invoke it from the
closure:

class A
def self.def_me(cmd,&block)
define_method(cmd) do
puts "preparation"
instance_eval &block
end
end

attr_accessor :name
end

a=A.new
a.name = "Einstein"

A.def_me:)foo) do
puts @name, self.name
end
preparation
Einstein
Einstein
=> nil

Kind regards

robert

thanks a lot thats perfect. I have to wrap my mind around all the
different evals and definition methods and have them at hand when
needed. Theres a long way to go.

They are not really too complicated IMHO: instance_eval is a variant of eval
that allows a string and a block and just rebinds "self" before evaluating
the string / block. class_eval is an extension of instance_eval which makes
sure that any "def"'s do not apply to the instance itself but to all
instances of the class. eval is the basic method that accepts only a string
but can work with any binding.

Kind regards

robert
 
B

Brian Schröder

[snip]
They are not really too complicated IMHO: instance_eval is a variant of e= val
that allows a string and a block and just rebinds "self" before evaluatin= g
the string / block. class_eval is an extension of instance_eval which ma= kes
sure that any "def"'s do not apply to the instance itself but to all
instances of the class. eval is the basic method that accepts only a str= ing
but can work with any binding.

Kind regards

robert

Ok, I have printed this and will put it on my wall. This should help
me choosing whats right.

thanks,

Brian
 

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
473,769
Messages
2,569,582
Members
45,065
Latest member
OrderGreenAcreCBD

Latest Threads

Top