Kernel#eval and class definition

B

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
def f ; eval "class C ; end", binding ; end

Thanks for your answers in advance.

Bertram
 
R

Robert Klemme

Bertram Scharpf said:
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
 
Y

Yukihiro Matsumoto

Hi,

In message "Re: Kernel#eval and class definition"

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

Bertram Scharpf

Hi,

Am Mittwoch, 12. Jan 2005, 18:43:42 +0900 schrieb Yukihiro Matsumoto:
In message "Re: Kernel#eval and class definition"

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

Florian Gross

Yukihiro said:
|> 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.
 
J

Joel VanderWerf

Florian said:
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
 
R

Robert Klemme

Joel VanderWerf said:
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
 
P

Pit Capitain

Robert said:
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
 
T

ts

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
 
R

Robert Klemme

ts said:
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
 
R

Robert Klemme

Pit Capitain said:
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
 

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

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,020
Latest member
GenesisGai

Latest Threads

Top