[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Kernel#eval and class definition

Bertram Scharpf

1/11/2005 7:12:00 PM

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


11 Answers

Robert Klemme

1/12/2005 9:24:00 AM

0


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

Yukihiro Matsumoto

1/12/2005 9:44:00 AM

0

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.


Bertram Scharpf

1/12/2005 10:37:00 AM

0

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


Florian Gross

1/12/2005 11:57:00 AM

0

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.

Joel VanderWerf

1/12/2005 4:39:00 PM

0

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


Robert Klemme

1/13/2005 9:47:00 AM

0


"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

Pit Capitain

1/13/2005 10:26:00 AM

0

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


ts

1/13/2005 10:36:00 AM

0

>>>>> "R" == Robert Klemme <bob.news@gmx.net> writes:

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

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


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


Robert Klemme

1/13/2005 11:49:00 AM

0


"ts" <decoux@moulon.inra.fr> schrieb im Newsbeitrag
news:200501131036.j0DAa5l16543@moulon.inra.fr...
> >>>>> "R" == Robert Klemme <bob.news@gmx.net> writes:
>
> R> That's better because then you can define methods that deal with
blocks,
> R> which you can't with define_method:
>
> This is because you use strange name like #foo and "bar"and ruby don't
> like it :-)

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

Robert Klemme

1/13/2005 11:50:00 AM

0


"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