Kernel#eval and class definition

Hi,

I try to understand more deeply what Ruby does.
Why here is the first line forbidden, the second allowed?

    def f ; class C ; end ; end
    def f ; eval "class C ; end", binding ; end

Thanks for your answers in advance.

Bertram

···

--
Bertram Scharpf
Stuttgart, Deutschland/Germany
http://www.bertram-scharpf.de

"Bertram Scharpf" <lists@bertram-scharpf.de> schrieb im Newsbeitrag
news:20050111144155.GA19812@homer.bertram-scharpf...

Hi,

I try to understand more deeply what Ruby does.
Why here is the first line forbidden, the second allowed?

    def f ; class C ; end ; end

This is a syntax error. The construct "class ... end" is simply
syntactically not allowed in a method. IMHO it doesn't make much sense
also, but that's another story.

    def f ; eval "class C ; end", binding ; end

Well eval "..." is just an expression and "eval" evaluates everyhing it
get's that's syntactically correct. The ruby code in the string
expression is not syntactically located in method f. It's parsed at
runtime while the line above is completely evaluated at compile time.

HTH

    robert

···

Thanks for your answers in advance.

Bertram

--
Bertram Scharpf
Stuttgart, Deutschland/Germany
http://www.bertram-scharpf.de

Hi,

···

In message "Re: Kernel#eval and class definition" on Wed, 12 Jan 2005 18:26:23 +0900, "Robert Klemme" <bob.news@gmx.net> writes:

    def f ; class C ; end ; end
    def f ; eval "class C ; end", binding ; end

Well eval "..." is just an expression and "eval" evaluates everyhing it
get's that's syntactically correct. The ruby code in the string
expression is not syntactically located in method f. It's parsed at
runtime while the line above is completely evaluated at compile time.

Thanks for explanation. class definition in the method is prohibited
by syntax just to detect errors. And class definition in eval is
allowed as a back door. Besides, scope management also is a reason,
but it's an implementation matter.

              matz.

Hi,

···

Am Mittwoch, 12. Jan 2005, 18:43:42 +0900 schrieb Yukihiro Matsumoto:

In message "Re: Kernel#eval and class definition" > on Wed, 12 Jan 2005 18:26:23 +0900, "Robert Klemme" <bob.news@gmx.net> writes:

>> def f ; class C ; end ; end
>> def f ; eval "class C ; end", binding ; end
>
>The ruby code in the string
>expression is not syntactically located in method f.

class definition in the method is prohibited
by syntax just to detect errors.

Ah, thank you both.

Bertram

--
Bertram Scharpf
Stuttgart, Deutschland/Germany
http://www.bertram-scharpf.de

Yukihiro Matsumoto wrote:

>> def f ; class C ; end ; end
>> def f ; eval "class C ; end", binding ; end
>
>Well eval "..." is just an expression and "eval" evaluates everyhing it
>get's that's syntactically correct. The ruby code in the string
>expression is not syntactically located in method f. It's parsed at
>runtime while the line above is completely evaluated at compile time.

Thanks for explanation. class definition in the method is prohibited
by syntax just to detect errors. And class definition in eval is
allowed as a back door. Besides, scope management also is a reason,
but it's an implementation matter.

There's also Class.new which will create an anonymous class. You can assign that to a constant via Module#const_set if you need to have a named class for some reason. That might be a bit better than using eval() depending on the use case.

Florian Gross wrote:

Yukihiro Matsumoto wrote:

>> def f ; class C ; end ; end
>> def f ; eval "class C ; end", binding ; end
>
>Well eval "..." is just an expression and "eval" evaluates everyhing it
>get's that's syntactically correct. The ruby code in the string
>expression is not syntactically located in method f. It's parsed at
>runtime while the line above is completely evaluated at compile time.

Thanks for explanation. class definition in the method is prohibited
by syntax just to detect errors. And class definition in eval is
allowed as a back door. Besides, scope management also is a reason,
but it's an implementation matter.

There's also Class.new which will create an anonymous class. You can assign that to a constant via Module#const_set if you need to have a named class for some reason. That might be a bit better than using eval() depending on the use case.

Better, in the sense that it takes a block (see below). But evaling a string to define the body of the class allows you to interpolate.

def f(arg)
   Class.new do
     define_method :g do arg end
   end
end

puts f("hello").new.g # ==> hello

"Joel VanderWerf" <vjoel@PATH.Berkeley.EDU> schrieb im Newsbeitrag
news:41E55294.2040102@path.berkeley.edu...

Florian Gross wrote:
> Yukihiro Matsumoto wrote:
>
>> >> def f ; class C ; end ; end
>> >> def f ; eval "class C ; end", binding ; end
>> >
>> >Well eval "..." is just an expression and "eval" evaluates everyhing

it

>> >get's that's syntactically correct. The ruby code in the string
>> >expression is not syntactically located in method f. It's parsed at
>> >runtime while the line above is completely evaluated at compile

time.

>>
>> Thanks for explanation. class definition in the method is prohibited
>> by syntax just to detect errors. And class definition in eval is
>> allowed as a back door. Besides, scope management also is a reason,
>> but it's an implementation matter.
>
>
> There's also Class.new which will create an anonymous class. You can
> assign that to a constant via Module#const_set if you need to have a
> named class for some reason. That might be a bit better than using
> eval() depending on the use case.

Better, in the sense that it takes a block (see below). But evaling a
string to define the body of the class allows you to interpolate.

def f(arg)
   Class.new do
     define_method :g do arg end
   end
end

puts f("hello").new.g # ==> hello

You can even use the def syntax:

irb(main):001:0> cl = Class.new do
irb(main):002:1* def foo() "bar" end
irb(main):003:1> end
=> #<Class:0x10186208>
irb(main):004:0> cl.new.foo
=> "bar"

That's better because then you can define methods that deal with blocks,
which you can't with define_method:

irb(main):005:0> cl = Class.new do
irb(main):006:1* def foo() yield "bar" end
irb(main):007:1> end
=> #<Class:0x10172468>
irb(main):008:0> cl.new.foo {|x| p x}
"bar"
=> nil

Kind regards

    robert

Robert Klemme schrieb:

"Joel VanderWerf" <vjoel@PATH.Berkeley.EDU> schrieb im Newsbeitrag
news:41E55294.2040102@path.berkeley.edu...

Better, in the sense that it takes a block (see below). But evaling a
string to define the body of the class allows you to interpolate.

def f(arg)
  Class.new do
    define_method :g do arg end
  end
end

puts f("hello").new.g # ==> hello

You can even use the def syntax:

irb(main):001:0> cl = Class.new do
irb(main):002:1* def foo() "bar" end
irb(main):003:1> end
=> #<Class:0x10186208>
irb(main):004:0> cl.new.foo
=> "bar"

That's better because then you can define methods that deal with blocks,
which you can't with define_method:

irb(main):005:0> cl = Class.new do
irb(main):006:1* def foo() yield "bar" end
irb(main):007:1> end
=> #<Class:0x10172468>
irb(main):008:0> cl.new.foo {|x| p x}
"bar"
=> nil

The def syntax lets you define methods with blocks, but it doesn't let you use objects from the defining scope, as Joel has been doing in his example. Note that he passes an object into the defining method and accesses this very object from the new class. You can't do that with the def syntax AFAIK.

Regards,
Pit

That's better because then you can define methods that deal with blocks,
which you can't with define_method:

This is because you use strange name like #foo and "bar"and ruby don't
like it :slight_smile:

uln% cat b.rb
#!./ruby
cl = Class.new do
   define_method(:alpha) do |&block|
      block["beta"]
   end
end

cl.new.alpha {|x| p x}
uln%

uln% b.rb
"beta"
uln%

Guy Decoux

"ts" <decoux@moulon.inra.fr> schrieb im Newsbeitrag
news:200501131036.j0DAa5l16543@moulon.inra.fr...

> That's better because then you can define methods that deal with

blocks,

> which you can't with define_method:

This is because you use strange name like #foo and "bar"and ruby don't
like it :slight_smile:

Must be a new version of Ruby that doesn't like #foo and #bar - my 1.8.1
has no problems with them. :-))

uln% cat b.rb
#!./ruby
cl = Class.new do
   define_method(:alpha) do |&block|
      block["beta"]
   end
end

cl.new.alpha {|x| p x}
uln%

uln% b.rb
"beta"
uln%

Is this Ruby 1.9?

    robert

"Pit Capitain" <pit@capitain.de> schrieb im Newsbeitrag
news:41E64CD5.6010703@capitain.de...

Robert Klemme schrieb:
> "Joel VanderWerf" <vjoel@PATH.Berkeley.EDU> schrieb im Newsbeitrag
> news:41E55294.2040102@path.berkeley.edu...
>>Better, in the sense that it takes a block (see below). But evaling a
>>string to define the body of the class allows you to interpolate.
>>
>>def f(arg)
>> Class.new do
>> define_method :g do arg end
>> end
>>end
>>
>>puts f("hello").new.g # ==> hello
>
>
> You can even use the def syntax:
>
> irb(main):001:0> cl = Class.new do
> irb(main):002:1* def foo() "bar" end
> irb(main):003:1> end
> => #<Class:0x10186208>
> irb(main):004:0> cl.new.foo
> => "bar"
>
> That's better because then you can define methods that deal with

blocks,

> which you can't with define_method:
>
> irb(main):005:0> cl = Class.new do
> irb(main):006:1* def foo() yield "bar" end
> irb(main):007:1> end
> => #<Class:0x10172468>
> irb(main):008:0> cl.new.foo {|x| p x}
> "bar"
> => nil

The def syntax lets you define methods with blocks, but it doesn't let

you use

objects from the defining scope, as Joel has been doing in his example.

Note

that he passes an object into the defining method and accesses this very

object

from the new class. You can't do that with the def syntax AFAIK.

Yeah, true. So then both have their pros and cons. Thanks for the
reminder!

Kind regards

    robert

Is this Ruby 1.9?

yes,

Guy Decoux