Eval and block problems

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

···

--
http://ruby.brian-schroeder.de/

Stringed instrument chords: http://chordlist.brian-schroeder.de/

Hi --

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.

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

···

On Mon, 3 Oct 2005, [ISO-8859-1] Brian Schröder wrote:

--
David A. Black
dblack@wobblini.net

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

···

On 10/2/05, Brian Schröder <ruby.brian@gmail.com> wrote:

Brian Schröder wrote:

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.

Not sure if this'll help, but it's something I'd thrown together awhile 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 = receiver
    name = name.to_s
    @name = name
    @receiver.send(:define_method,name) do |*a|
      send(name+a.size.to_s,*a)
    end
  end
  def args arity, &blk
    name = @name
    @receiver.send(:define_method,@name+arity.to_s,&blk) #do |*a|
# if a.size != 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 := do
  args 2 do |coord,val|
    x,y = convert(coord)
    self[x,y] = val
  end
  args 3 do |x,y,val|
    @thing[y] = 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 = 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

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

···

On 02/10/05, David A. Black <dblack@wobblini.net> wrote:

Hi --

On Mon, 3 Oct 2005, [ISO-8859-1] Brian Schröder wrote:

> [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

--
David A. Black
dblack@wobblini.net

--
http://ruby.brian-schroeder.de/

Stringed instrument chords: http://chordlist.brian-schroeder.de/

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

···

On 02/10/05, Ryan Leavengood <leavengood@gmail.com> wrote:

On 10/2/05, Brian Schröder <ruby.brian@gmail.com> wrote:
> 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

--
http://ruby.brian-schroeder.de/

Stringed instrument chords: http://chordlist.brian-schroeder.de/

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

a.foo

preparation
Einstein
=> nil

Kind regards

    robert

···

Brian Schröder <ruby.brian@gmail.com> wrote:

On 02/10/05, Ryan Leavengood <leavengood@gmail.com> wrote:

On 10/2/05, Brian Schröder <ruby.brian@gmail.com> wrote:

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

···

On 02/10/05, Robert Klemme <bob.news@gmx.net> wrote:

Brian Schröder <ruby.brian@gmail.com> wrote:
> [snip]

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

>> a.foo
preparation
Einstein
Einstein
=> nil

Kind regards

    robert

--
http://ruby.brian-schroeder.de/

Stringed instrument chords: http://chordlist.brian-schroeder.de/

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

···

Brian Schröder <ruby.brian@gmail.com> wrote:

On 02/10/05, Robert Klemme <bob.news@gmx.net> wrote:

Brian Schröder <ruby.brian@gmail.com> wrote:

[snip]

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

a.foo

preparation
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.

> [snip]
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

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

thanks,

Brian

···

--
http://ruby.brian-schroeder.de/

Stringed instrument chords: http://chordlist.brian-schroeder.de/