Problems creating a method to define a class with its method

Discussion in 'Ruby' started by Benny, Jul 12, 2004.

  1. Benny

    Benny Guest

    Dear list,

    I want to create a method that creates certain kinds of classes for me.
    The following doesn't work:

    ### start pseudo code
    module My_Module
    class Bigclass
    attr_accessor :test
    def Bigclass.run(para)
    @test = para
    puts "your parameter is " + @test
    end
    def Bigclass.check
    puts "I'm here"
    end
    end

    def My_Module.subclass(name, &code)
    eval <<-EOS
    class #{name} < Bigclass
    def #{name}.run(p)
    super(p)
    #{code.call}
    end
    end
    EOS
    end
    end

    My_Module::subclass("Newclass"){
    puts "doesn't work" + @test.to_s
    check()
    }

    My_Module::Newclass.run("my parameter")
    ### end pseudo code

    the problem is that the #{code.call} is executed before
    the class is defined, so @test isn't filled yet (super(p)
    isn't executed at this time.

    how can I change the code, so that »code« is part of the definition
    of the class (i.e. part of its method »run«)?
    (the code can be very long, so putting it in a string is
    not very comfortable regarding quoting etc. (I also want
    the code to be highlighted in an editor).

    benny
     
    Benny, Jul 12, 2004
    #1
    1. Advertising

  2. On Tue, Jul 13, 2004 at 07:22:27AM +0900, Benny wrote:
    > def My_Module.subclass(name, &code)
    > eval <<-EOS
    > class #{name} < Bigclass
    > def #{name}.run(p)
    > super(p)
    > #{code.call}
    > end
    > end
    > EOS
    > end
    > end

    [...]
    > the problem is that the #{code.call} is executed before
    > the class is defined, so @test isn't filled yet (super(p)
    > isn't executed at this time.
    >
    > how can I change the code, so that »code« is part of the definition
    > of the class (i.e. part of its method »run«)


    batsman@tux-chan:/tmp$ cat ghfdgh54yiyh.rb
    module My_Module
    class Bigclass
    attr_accessor :test
    def Bigclass.run(para)
    @test = para
    puts "your parameter is " + @test
    end
    def Bigclass.check
    puts "I'm here"
    end
    end

    def My_Module.subclass(name, &code)
    k = Class.new(Bigclass)
    class << k; self end.send:)define_method, "run") do |p|
    super(p)
    instance_eval(&code)
    end
    My_Module.const_set(name, k)
    k
    end
    end

    My_Module.subclass("Newclass") do
    puts "does work work now: " + @test.to_s
    check
    end

    My_Module::Newclass.run "blah"
    batsman@tux-chan:/tmp$ ruby ghfdgh54yiyh.rb
    your parameter is blah
    does work work now: blah
    I'm here

    --
    Running Debian GNU/Linux Sid (unstable)
    batsman dot geo at yahoo dot com

    "You, sir, are nothing but a pathetically lame salesdroid!
    I fart in your general direction!"
    -- Randseed on #Linux
     
    Mauricio Fernández, Jul 12, 2004
    #2
    1. Advertising

  3. Benny

    Benny Guest

    Mauricio Fernández wrote:

    > your parameter is blah
    > does work work now: blah
    > I'm here

    whow!! thank you. its seems to be a bit more complicated
    than I thought. I would never have found the solution on my own!!

    now I know for what reason we've got "send", "define_method",
    "instance_eval" and "const_set". can you explain me why "eval" was a
    thought in the wrong direction?

    (btw: the construct with k = Class.new... const_set(name, k) seems less
    elegant than eval("class #{name} < Bigclass..") at first sight)

    benny
     
    Benny, Jul 13, 2004
    #3
  4. On Tue, Jul 13, 2004 at 02:32:22PM +0900, Benny wrote:
    > Mauricio Fernández wrote:
    >
    > > your parameter is blah
    > > does work work now: blah
    > > I'm here

    > whow!! thank you. its seems to be a bit more complicated
    > than I thought. I would never have found the solution on my own!!
    >
    > now I know for what reason we've got "send", "define_method",
    > "instance_eval" and "const_set". can you explain me why "eval" was a
    > thought in the wrong direction?


    Your code was

    def My_Module.subclass(name, &code)
    eval <<-EOS
    class #{name} < Bigclass
    def #{name}.run(p)
    super(p)
    #{code.call}
    end
    end
    EOS
    end

    the basic problem is that you're opening a new scope when you do class X;
    ... end or def foo; ... end, so you cannot access the 'code' variable
    directly; if it were possible to turn it into a literal (that is, if
    it were a number, string, array, etc) you could use #{code.inspect}
    to interpolate the value, but it's not possible in this case since it's
    a Proc. In order to be able to access code from the method definition,
    you have to use a closure, i.e. define_method.

    > (btw: the construct with k = Class.new... const_set(name, k) seems less
    > elegant than eval("class #{name} < Bigclass..") at first sight)


    I tend to avoid eval <<-EOF for a number of reasons:
    * syntax errors aren't caught at load time
    * the editor doesn't indent/highlight the code
    * (when defining classes/methods with class/def) no closures
    * interpolating values in the code feels cheap (and will only work for
    some classes)
    * it's eval :) using it is a bit like recognizing the language wasn't
    powerful enough to express what I wanted 'statically'

    To me, eval'ing a text with lots of #{whatever} seems less elegant, for
    the reasons stated above. I prefer one of the block forms (instance_eval{}
    or module_eval{ }) or define_method when it makes sense.

    --
    Running Debian GNU/Linux Sid (unstable)
    batsman dot geo at yahoo dot com

    Why are there always boycotts? Shouldn't there be girlcotts too?
    -- argon on #Linux
     
    Mauricio Fernández, Jul 13, 2004
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Apple
    Replies:
    3
    Views:
    306
    Apple
    Aug 1, 2005
  2. Francis Hwang
    Replies:
    3
    Views:
    91
    Robert Klemme
    Nov 29, 2004
  3. thunk
    Replies:
    1
    Views:
    315
    thunk
    Mar 30, 2010
  4. thunk
    Replies:
    0
    Views:
    488
    thunk
    Apr 1, 2010
  5. thunk
    Replies:
    14
    Views:
    627
    thunk
    Apr 3, 2010
Loading...

Share This Page