Accessing constants from class methods


(Ara.T.Howard) #1

what i would like to accomplish would be something like this:

class Abstract
class << self
def x
# defined?(self::X) ? self::X : nil
end
end
end

class Concrete < Abstract
X = 42
end

p Base.x # => nil

p Derived.x # => 42

does this make sense? in essence i want an abstract class method with the
semantics of “iff a concrete class has defined a certain constant, return it”

the problem is that ‘self::X’ above tries to reference ‘Class::X’, if i
replace ‘self’ with ‘Abstract’ then i will be referencing the incorrect ‘X’…

how does one say ‘the constant of the current class’ from within a class
method?

-a

···

EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
PHONE :: 303.497.6469
ADDRESS :: E/GC2 325 Broadway, Boulder, CO 80305-3328
URL :: http://www.ngdc.noaa.gov/stp/
TRY :: for l in ruby perl;do $l -e “print “\x3a\x2d\x29\x0a””;done
===============================================================================


(David A. Black) #2

Hi –

what i would like to accomplish would be something like this:

class Abstract
class << self
def x
# defined?(self::X) ? self::X : nil
end
end
end

class Concrete < Abstract
X = 42
end

p Base.x # => nil

p Derived.x # => 42

    ^^^^^^^  you mean Abstract/Concrete, I assume :-)

I think this already does what you want, doesn’t it?

$ cat ara.rb
class Abstract
class << self
def x
defined?(self::X) ? self::X : nil
end
end
end

 class Concrete < Abstract
   X = 42
 end

 p Abstract.x
 p Concrete.x

dblack@laptop:~/hacking$ ruby -v ara.rb
ruby 1.6.8 (2002-12-24) [i686-linux-gnu]
nil
42

on the general principle that self will get set to the
receiver (Concrete, in this case) – so, for example:

irb(main):001:0> class A; def A.x; p self; end; end
=> nil
irb(main):002:0> class B < A; end
=> nil
irb(main):003:0> B.x
B

(Or did I misunderstand?)

David

···

On Sat, 14 Feb 2004, Ara.T.Howard wrote:


David A. Black
dblack@wobblini.net


(daz) #3

“Ara.T.Howard” wrote:

···

what i would like to accomplish would be something like this:

class Abstract
class << self
def x
# defined?(self::X) ? self::X : nil
end
end
end

class Concrete < Abstract
X = 42
end

p Base.x # => nil

p Derived.x # => 42

does this make sense? in essence i want an abstract class method with the
semantics of “iff a concrete class has defined a certain constant, return it”

the problem is that ‘self::X’ above tries to reference ‘Class::X’, if i
replace ‘self’ with ‘Abstract’ then i will be referencing the incorrect ‘X’…

how does one say ‘the constant of the current class’ from within a class
method?

#-----

class A
class << self
def x
const_defined?(:X) ? const_get(:X) : nil
end
end
end

class C < A
X = 42
end

p A.x # => nil
p C.x # => 42

#-----

daz


(Robert) #4

“Ara.T.Howard” Ara.T.Howard@noaa.gov schrieb im Newsbeitrag
news:Pine.LNX.4.44.0402131650180.4232-100000@fattire.ngdc.noaa.gov

what i would like to accomplish would be something like this:

class Abstract
class << self
def x
# defined?(self::X) ? self::X : nil
end
end
end

class Concrete < Abstract
X = 42
end

p Base.x # => nil

p Derived.x # => 42

does this make sense? in essence i want an abstract class method with
the
semantics of “iff a concrete class has defined a certain constant,
return it”

the problem is that ‘self::X’ above tries to reference ‘Class::X’, if i
replace ‘self’ with ‘Abstract’ then i will be referencing the incorrect
’X’…

how does one say ‘the constant of the current class’ from within a class
method?

Use instance vars of classes:

class Class
def x
ancestors.each do |cl|
val = cl.instance_variable_get("@x")
return val if val
end

nil

end

def x=(val); @x=val; end
end

class Abstract; end

class Concrete < Abstract
self.x = 42
end

class MostConcrete < Concrete
self.x = "forty two"
end

p Abstract.x
p Concrete.x
p MostConcrete.x

Regards

robert

(Ara.T.Howard) #5

perfect!

-a

···

On Sat, 14 Feb 2004, daz wrote:

Date: Sat, 14 Feb 2004 08:24:08 -0000
From: daz dooby@d10.karoo.co.uk
Newsgroups: comp.lang.ruby
Subject: Re: accessing constants from class methods

“Ara.T.Howard” wrote:

what i would like to accomplish would be something like this:

class Abstract
class << self
def x
# defined?(self::X) ? self::X : nil
end
end
end

class Concrete < Abstract
X = 42
end

p Base.x # => nil

p Derived.x # => 42

does this make sense? in essence i want an abstract class method with the
semantics of “iff a concrete class has defined a certain constant, return it”

the problem is that ‘self::X’ above tries to reference ‘Class::X’, if i
replace ‘self’ with ‘Abstract’ then i will be referencing the incorrect ‘X’…

how does one say ‘the constant of the current class’ from within a class
method?

#-----

class A
class << self
def x
const_defined?(:X) ? const_get(:X) : nil
end
end
end

class C < A
X = 42
end

p A.x # => nil
p C.x # => 42

#-----

daz

EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
PHONE :: 303.497.6469
ADDRESS :: E/GC2 325 Broadway, Boulder, CO 80305-3328
URL :: http://www.ngdc.noaa.gov/stp/
TRY :: for l in ruby perl;do $l -e “print “\x3a\x2d\x29\x0a””;done
===============================================================================


(David A. Black) #6

Hi –

···

On Sat, 14 Feb 2004, Ara.T.Howard wrote:

On Sat, 14 Feb 2004, daz wrote:

Date: Sat, 14 Feb 2004 08:24:08 -0000
From: daz dooby@d10.karoo.co.uk
Newsgroups: comp.lang.ruby
Subject: Re: accessing constants from class methods

“Ara.T.Howard” wrote:

what i would like to accomplish would be something like this:

class Abstract
class << self
def x
# defined?(self::X) ? self::X : nil
end
end
end

class Concrete < Abstract
X = 42
end

p Base.x # => nil

p Derived.x # => 42

does this make sense? in essence i want an abstract class method with the
semantics of “iff a concrete class has defined a certain constant, return it”

the problem is that ‘self::X’ above tries to reference ‘Class::X’, if i
replace ‘self’ with ‘Abstract’ then i will be referencing the incorrect ‘X’…

how does one say ‘the constant of the current class’ from within a class
method?

#-----

class A
class << self
def x
const_defined?(:X) ? const_get(:X) : nil
end
end
end

class C < A
X = 42
end

p A.x # => nil
p C.x # => 42

#-----

daz

perfect!

OK, it’s probably something simple but I’m staring and staring at the
original code, and its output (which is the same as daz’s code), and I
can’t figure out why it wasn’t OK.

Explanations welcome :slight_smile:

David


David A. Black
dblack@wobblini.net


(Mark) #7

David A. Black wrote:

OK, it’s probably something simple but I’m staring and staring at the
original code, and its output (which is the same as daz’s code), and I
can’t figure out why it wasn’t OK.

Explanations welcome :slight_smile:

The origional code defines x as

def x

defined?(self::X) ? self::X : nil

end

while daz’s code says

def x
const_defined?(:X) ? const_get(:X) : nil
end

it uses const_defined and const_get

Best Regards

Mark Sparshatt


(David A. Black) #8

Hi –

···

On Sun, 15 Feb 2004, Mark wrote:

David A. Black wrote:

OK, it’s probably something simple but I’m staring and staring at the
original code, and its output (which is the same as daz’s code), and I
can’t figure out why it wasn’t OK.

Explanations welcome :slight_smile:

The origional code defines x as

def x

defined?(self::X) ? self::X : nil

end

while daz’s code says

def x
const_defined?(:X) ? const_get(:X) : nil
end

it uses const_defined and const_get

Yes, that much I saw :slight_smile: What I didn’t get was what the problem
was to begin with. self::X looked to me like it worked fine.

David


David A. Black
dblack@wobblini.net


(daz) #9

David A. Black wrote:

OK, it’s probably something simple but I’m staring and staring at the
original code, and its output (which is the same as daz’s code), and I
can’t figure out why it wasn’t OK.

Explanations welcome :slight_smile:

Your post didn’t get through to the NG, David.
Ara probably didn’t see it and there appeared to be no replies
when I posted.

http://groups.google.com/groups?hl=en&th=5677a0c1234ad853

I’m wary about the defined? keyword – I can’t find a good
definition of what service it provides.

for i in 0…1 # (avoiding new scope)
puts defined? a
a = 1
puts defined? a
puts ‘-’ * 10
end

#-> nil
#-> local-variable
#-> ----------
#-> nil
#-> local-variable
#-> ----------

Strangely, for constants it works differently.

for i in 0…1
puts defined? X
X = 1
puts defined? X
puts ‘-’ * 10
end

#-> nil
#-> constant
#-> ----------
#-> constant
#-> constant
#-> ----------

The next test made me wonder if I can believe anything, any more.

for i in 0…1
puts defined? Z
const_set Z, 1
puts defined? Z
puts ‘-’ * 10
end

#-> nil
#-> C:/TEMP/rb3273.TMP:17: uninitialized constant Z (NameError)
#-> from C:/TEMP/rb3273.TMP:15:in `each’
#-> from C:/TEMP/rb3273.TMP:15

=begin
--------------------------------------------------------------- Module#const_set
mod.const_set( aSymbol, anObject ) -> anObject

···
 Sets the named constant to the given object, returning that object.
 Creates a new constant if no constant with the given name previously existed.
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 [...]

=end

daz


(Joel VanderWerf) #10

daz wrote:

The next test made me wonder if I can believe anything, any more.

for i in 0…1
puts defined? Z
const_set Z, 1
puts defined? Z
puts ‘-’ * 10
end

The first argument to #const_set should be a symbol or string, and the
receiver of #const_set should be a module.

for i in 0…1
puts defined? Z
Object::const_set :Z, 1
puts defined? Z
puts ‘-’ * 10
end

#-> nil
#-> constant
#-> ----------
#-> constant
#-> constant
#-> ----------

Keep believing…


(Ara.T.Howard) #11

Date: Mon, 16 Feb 2004 06:55:25 -0000
From: daz dooby@d10.karoo.co.uk
Newsgroups: comp.lang.ruby
Subject: Re: accessing constants from class methods

David A. Black wrote:

OK, it’s probably something simple but I’m staring and staring at the
original code, and its output (which is the same as daz’s code), and I
can’t figure out why it wasn’t OK.

Explanations welcome :slight_smile:

Your post didn’t get through to the NG, David.
Ara probably didn’t see it and there appeared to be no replies
when I posted.

http://groups.google.com/groups?hl=en&th=5677a0c1234ad853

yes exactly - sorry david.

I’m wary about the defined? keyword – I can’t find a good
definition of what service it provides.

for i in 0…1 # (avoiding new scope)
puts defined? a
a = 1
puts defined? a
puts ‘-’ * 10
end

#-> nil
#-> local-variable
#-> ----------
#-> nil
#-> local-variable
#-> ----------

Strangely, for constants it works differently.

for i in 0…1
puts defined? X
X = 1
puts defined? X
puts ‘-’ * 10
end

#-> nil
#-> constant
#-> ----------
#-> constant
#-> constant
#-> ----------

The next test made me wonder if I can believe anything, any more.

for i in 0…1
puts defined? Z
const_set Z, 1
puts defined? Z
puts ‘-’ * 10
end

#-> nil
#-> C:/TEMP/rb3273.TMP:17: uninitialized constant Z (NameError)
#-> from C:/TEMP/rb3273.TMP:15:in `each’
#-> from C:/TEMP/rb3273.TMP:15

THIS is the error i was getting but couldn’t seem to reproduce it in response
to an offline question from david. now i see that i could have done something
very subtle to (re)create the bug…

thanks for the warning - i will be catious when using ‘defined?’ in the
future.

-a

···

On Mon, 16 Feb 2004, daz wrote:

===============================================================================

EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
PHONE :: 303.497.6469
ADDRESS :: E/GC2 325 Broadway, Boulder, CO 80305-3328
URL :: http://www.ngdc.noaa.gov/stp/
TRY :: for l in ruby perl;do $l -e “print “\x3a\x2d\x29\x0a””;done
===============================================================================


(daz) #12

“Joel VanderWerf” wrote:

daz wrote:

The next test made me wonder if I can believe anything, any more.

for i in 0…1
puts defined? Z
const_set Z, 1
puts defined? Z
puts ‘-’ * 10
end

The first argument to #const_set should be a symbol or string, and the
receiver of #const_set should be a module.

[…]

Keep believing…

Faith restored, once again :slight_smile:

Cheers,

daz