2

Here's a question to bamboozle your noodle.

It seems there's a difference between method declaration and constant declaration in a block that is evaluated using class_eval with a class as the receiver. Here's some code that demonstrates the discrepancy:

module X def save_block(&block) @block = block end end module Y extend X save_block do SOME_CONSTANT = 1 def meth "a method" end end def self.included(m) m.class_eval &@block end end class Z include Y end class W include Y end 

Executing this code, at least in Ruby 1.9.3, results in the following error:

warning: already initialized constant SOME_CONSTANT 

Which I didn't expect. Consider first where meth is located:

Z.instance_methods(false) => [:meth] W.instance_methods(false) => [:meth] 

And Y doesn't have any instance methods:

Y.instance_methods(false) => [] 

This makes sense because the block is executed with Z and W as the receivers of class_eval. However, the constants are different, hence the error message, as shown here:

Y.constants(false) => [:SOME_CONSTANT] Z.constants(false) => [] W.constants(false) => [] 

Here, the constant ends up getting defined in Y (for some bizarre reason) and thus when the block is executed a second time, the constant, SOME_CONSTANT is already defined.

I very much look forward to some enlightenment.

Update (2012/11/19):

As @phoet pointed out below (the the response to my comment to his answer), constants are defined in the lexical scope of the block, that is to say, in the scope where the block is originally defined. In my example, this would be Y.

1 Answer 1

1

as described in this question Accessing a constant constant handling is within it's "lexical scope", meaning the context they are defined, not the context they are executed.

Sign up to request clarification or add additional context in comments.

3 Comments

Constants are definitely not created at parase time. For example, if I execute Y.constants(false) before Z or W are defined, but after Y is defined, then I get the empty array []. The block must be evaluated for the constant to be defined. I'm just not sure why the constant gets attached to Y instead of Z and W individually.
yeah, you are right. it's about scoping: stackoverflow.com/questions/10078744/accessing-a-constant
If you update your answer, to reflect this, I'll accept it (I already added a note to my original question).

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.