Problem with constants

  • Thread starter Kroeger Simon (ext)
  • Start date
K

Kroeger Simon (ext)

I'm puzzled:
-----------------------
class X
A =3D 1
def X.a
A
end
end

class Y < X
A =3D 2
end

class Z < X
A =3D 3
def Z.a
A
end
end

p X.a #=3D> 1
p Y.a #=3D> 1
p Z.a #=3D> 3
-----------------------
(ruby 1.8.2 (2004-12-25) [i386-mswin32])

Shouldn't this yield at least a warning?
Is this a feature?

cheers

Simon
 
H

HaPK

Kroeger said:
I'm puzzled:
-----------------------
class X
A = 1
def X.a
A
end
end

class Y < X
A = 2
end

class Z < X
A = 3
def Z.a
A
end
end

p X.a #=> 1
p Y.a #=> 1
p Z.a #=> 3
-----------------------
(ruby 1.8.2 (2004-12-25) [i386-mswin32])

Shouldn't this yield at least a warning?
Is this a feature?
Since A is not a class variable (it's a local variable) it's saved in
"X.a" closure. In Y class it doesn't exist, so it can't influence on
"X.a" method.

PS I hope my crappy english doesn't mess things too much.
 
P

Pit Capitain

Kroeger said:
I'm puzzled:
-----------------------
class X
A = 1
def X.a
A
end
end

class Y < X
A = 2
end

class Z < X
A = 3
def Z.a
A
end
end

p X.a #=> 1
p Y.a #=> 1
p Z.a #=> 3
-----------------------
(ruby 1.8.2 (2004-12-25) [i386-mswin32])

Shouldn't this yield at least a warning?
Is this a feature?

Yes. Constants are lexically scoped. As I've learned from a recent post
here on ruby-talk, you can change your code to

def X.a
self::A
end

to get the behavior I suppose you're looking for.

Regards,
Pit
 
D

David A. Black

Hi --

Kroeger said:
I'm puzzled:
-----------------------
class X
A = 1
def X.a
A
end
end

class Y < X
A = 2
end

class Z < X
A = 3
def Z.a
A
end
end

p X.a #=> 1
p Y.a #=> 1
p Z.a #=> 3
-----------------------
(ruby 1.8.2 (2004-12-25) [i386-mswin32])

Shouldn't this yield at least a warning?
Is this a feature?
Since A is not a class variable (it's a local variable) it's saved in "X.a"
closure. In Y class it doesn't exist, so it can't influence on "X.a" method.

Actually A is a constant, not a local variable, and method definitions
aren't closures. I'm pretty sure that what's happening is that the
constant references are being resolved at compile-time, so that by the time
Y.a is run, the reference inside X.a has been permanently resolved to
X::A.

See what happens when you make this change:

def X.a
const_get("A")
end

Now the constant is being resolved dynamically, and you'll get 1/2/3
in the output.


David
 
H

HaPK

HaPK said:
Kroeger said:
I'm puzzled:
-----------------------
class X
A = 1
def X.a
A
end
end

class Y < X
A = 2
end

class Z < X
A = 3
def Z.a
A
end
end

p X.a #=> 1
p Y.a #=> 1
p Z.a #=> 3
-----------------------
(ruby 1.8.2 (2004-12-25) [i386-mswin32])

Shouldn't this yield at least a warning?
Is this a feature?
Since A is not a class variable (it's a local variable) it's saved in
"X.a" closure. In Y class it doesn't exist, so it can't influence on
"X.a" method.

PS I hope my crappy english doesn't mess things too much.

Ooops... sorry.. Didn't get you right.

Indeed, seems like a bug with constants assignment.

class X
A = 1
end

class Y < X
A = 2
end

class Z < X
end

X.constants => 'A'
Y.constants => 'A'
Z.constants => 'A' # Z inherits constants from its
parent

X::A = 3
Z::A => 3 # changes in superclass
populated to subclasses

Z::A = 4
X::A => 3 # changes in subclass remains
local to subclass

Seems like assignments are made without lookup in superclasses.
 
T

ts

D> aren't closures. I'm pretty sure that what's happening is that the
D> constant references are being resolved at compile-time, so that by the time
D> Y.a is run, the reference inside X.a has been permanently resolved to
D> X::A.

Well not really : ruby *want* that you think that the constants are resolved
statically

[ruby-talk:32774]

"Those rules provide you the "illusion" of statically scoped constants."


Guy Decoux
 
D

David A. Black

Hi --

Indeed, seems like a bug with constants assignment.

class X
A = 1
end

class Y < X
A = 2
end

class Z < X
end

X.constants => 'A'
Y.constants => 'A'
Z.constants => 'A' # Z inherits constants from its parent

X::A = 3
Z::A => 3 # changes in superclass populated
to subclasses

Z::A = 4
X::A => 3 # changes in subclass remains local
to subclass

Seems like assignments are made without lookup in superclasses.

There's no bug. There's a lookup path for constants. Z finds X::A on
its lookup path. You could also do: Z::String and although you'd get
a warning, Ruby would indeed return the top-level constant String
(because there's no other String to replace it in the lookup path).

When you change X::A (aside from getting a warning :) it's not
exactly that the change is propagated to Z. Rather, the change
affects a constant that is on Z's lookup path -- so, naturally, when Z
sees that constant, it's changed. It's not because Z is a subclass of
X. The change to X::A would be visible from anywhere.

When you assign to Z::A, you're creating a new constant. This has no
effect on X::A; the two are completely unrelated.


David
 
D

David A. Black

Hi --

D> aren't closures. I'm pretty sure that what's happening is that the
D> constant references are being resolved at compile-time, so that by the time
D> Y.a is run, the reference inside X.a has been permanently resolved to
D> X::A.

Well not really : ruby *want* that you think that the constants are resolved
statically

[ruby-talk:32774]

"Those rules provide you the "illusion" of statically scoped constants."

Darn, I thought that by avoiding the word "statically" I was safe :)


David
 
S

Simon Kröger

David A. Black wrote:

[...]
Actually A is a constant, not a local variable, and method definitions
aren't closures. I'm pretty sure that what's happening is that the
constant references are being resolved at compile-time, so that by the time
Y.a is run, the reference inside X.a has been permanently resolved to
X::A.

See what happens when you make this change:

def X.a
const_get("A")
end

Now the constant is being resolved dynamically, and you'll get 1/2/3
in the output.

erm, yes.

true, but i think this makes it entirely weird.

so i call Y::a: self is Y, there is an A in Y but the A from X is used,
right?

if i redefine X.a to

def X.a
self::A
end

it's like i would expect it.

Ok, as this looks still completely odd to me (whatelse if not self would
do as an implicit target?) there has to be a real good reason why it is
this way, right? RIGHT?

(i don't have to call self.const_get:)A), why do i have to use self::A
to get the A from self?)

/me still puzzled

cheers

Simon
 
T

ts

"S" == =?ISO-8859-1?Q?Simon Kr=F6ger?= <ISO-8859-1> writes:

S> /me still puzzled

Well another stupid example

require 'a'

class B < A
X = 24
def b
X
end
end

B::a

do you expect to have `24' when potentially you don't know that the method
A::a use the constant X ?


Guy Decoux
 

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

Forum statistics

Threads
473,989
Messages
2,570,207
Members
46,783
Latest member
RickeyDort

Latest Threads

Top