Prevent ruby constant variables from changing?

Hi,

I understand that ruby constant variables are declared by using
uppercase letter. However, the constant variable can still be
reassigned even though a warning is issued.

Is there a way I can fix the value that is initially assigned to the
constant variable?

Thanks

George W. wrote:

However, the constant variable can still be
reassigned even though a warning is issued.

Am I the only person who thinks that constants should be unchangeable?

Being new to Ruby, it seems weird to me that constants aren’t actually
constant. I’m sure there must be some arcane reason for it, but surely
most people want their constants to remain constant! That’s how it works
in most languages.

Freezing would seem like a good idea but I haven’t actually tried it.
Yet.

From: George W. [mailto:[email protected]]

Is there a way I can fix the value that is initially assigned to the

constant variable?

arggh, ruby constants are global vars that croaks when you modify them
:slight_smile:

i too had this problem, and the closest i can get is to wrap the
constants in a module and then freeze the module.

eg,

botp@botp-desktop:~$ irb

irb(main):001:0> module CONSTANT
irb(main):002:1> X=1
irb(main):003:1> Y=2
irb(main):004:1> Z=“test”
irb(main):005:1> end
=> “test”

irb(main):006:0> CONSTANT.constants
=> [“Z”, “Y”, “X”]

irb(main):008:0> CONSTANT::X
=> 1

irb(main):009:0> CONSTANT::X = 100
(irb):9: warning: already initialized constant X
=> 100

irb(main):010:0> CONSTANT::X
=> 100

irb(main):011:0> CONSTANT.freeze
=> CONSTANT

irb(main):012:0> CONSTANT::X
=> 100

irb(main):013:0> CONSTANT::X = 99
TypeError: can’t modify frozen module
from (irb):13
from :0

irb(main):014:0> CONSTANT::X
=> 100

it’s a blessing in disguise; i think i may stick to this scheme.
Considering how applications grow and how vars/constants clash, somehow
i feel like i should qualify my constants. It’s safer, and readable too.
(and don’t worry, there is no unfreeze in ruby :wink:

kind regards -botp

On 22.05.2008 13:01, Dave B. wrote:

George W. wrote:

However, the constant variable can still be
reassigned even though a warning is issued.

Am I the only person who thinks that constants should be unchangeable?

Probably not. However, there are more spots like this in Ruby (e.g.
private methods). It is a general feature of the language to not be too
restrictive about such things. For me this was never an issue. YMMV
though. OTOH this makes some things (mostly related to meta
programming) pretty easy that are hard to impossible in other languages.
For example, if you want to write code in Java that modifies arbitrary
private instance variables, you can do it but it’s much more involved
than using #instance_variable_set. It’s probably good that it is not
made too easy in Java - and equally good that it’s the way it is in
Ruby.

Being new to Ruby, it seems weird to me that constants aren’t actually
constant. I’m sure there must be some arcane reason for it, but surely
most people want their constants to remain constant! That’s how it works
in most languages.

Freezing would seem like a good idea but I haven’t actually tried it.
Yet.

Freezing does something else: freezing prohibits assigning to and
creation of instance variables. This helps if you want to use an
instance of an otherwise mutable class as constant.

I agree with Pena that the safest approach is probably the one he
demonstrated.

Kind regards

robert

On 22.05.2008 13:38, Florian G. wrote:

If you noticed, class names are constants. As you can change classes
at runtime, constants must be changable.

No, not necessarily: you can change a class without reassignment to the
constant.

Actually overwriting Constants emits a warning. A you should program
warnings-free, that should be no problem :).

At least it’s a good guiding rule to follow.

Kind regards

robert

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On May 22, 2008, at 1:01 PM, Dave B. wrote:

in most languages.

Freezing would seem like a good idea but I haven’t actually tried it.
Yet.

Posted via http://www.ruby-forum.com/.

If you noticed, class names are constants. As you can change classes
at runtime, constants must be changable.
Actually overwriting Constants emits a warning. A you should program
warnings-free, that should be no problem :).

Regards,
Florian G.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.8 (Darwin)

iEYEARECAAYFAkg1WvgACgkQJA/zY0IIRZYmkQCeJvyw4XwGA2+sYWN8RdYt+F/7
1pkAn3pRTl129HoSddfetPJhyji3gBg/
=8BGR
-----END PGP SIGNATURE-----

On Thu, May 22, 2008 at 1:38 PM, Florian G. [email protected]
wrote:

Posted via http://www.ruby-forum.com/.

If you noticed, class names are constants.
Not necessarily.
c = Class::new { def … }
As you can change classes at
runtime, constants must be changable.
Not at all, you can always change the object a constant points to,
unless it is frozen.
Robert

http://ruby-smalltalk.blogspot.com/


Whereof one cannot speak, thereof one must be silent.
Ludwig Wittgenstein

On May 22, 2008, at 7:12 AM, Florian G. wrote:

So how does the creation of an anonymous class hurt the argument
that class names are constants?

it’s not not anonymous, it’s held in a variable, just as normal
classes are

c = Class.new

class C; end

C = Class.new

it’s subtle, but there is no such thing as a ‘class name’, rather
there are classes that a held in variables, often these variables are
constants, but not always, and it is true that ruby give you the
illusion that they are names via a handy Class#name method, but note
that this is really just inspect and not specific to classes:

cfp:~ > ruby -e ‘class C;end; module M;end; p C.name; p C; p
M.name; p M’
“C”
C
“M”
M

the name is not special, just a method:

cfp:~ > ruby -e’ class C;end; Constant = C; p Constant.name; def
Constant.name; “Constant”; end; p Constant.name ’
“C”
“Constant”

regards.

a @ http://codeforpeople.com/

On May 22, 2008, at 1:49 AM, Peña, Botp wrote:

i too had this problem, and the closest i can get is to wrap the
constants in a module and then freeze the module.

i’m sure you’re aware but:

cfp:~ > cat a.rb
(

module Namespace
X = 4
Y = 2
end

).freeze

Object.send :remove_const, :Namespace

Namespace = Module.new
Namespace::X = 2
Namespace::Y = 4

puts Namespace::Y, Namespace::X

cfp:~ > ruby a.rb
4
2

it’s hard to get around the dynamic aspects of ruby (thankfully) :wink:

a @ http://codeforpeople.com/

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On May 22, 2008, at 2:36 PM, Robert D. wrote:

If you noticed, class names are constants.
Not necessarily.
c = Class::new { def … }

So how does the creation of an anonymous class hurt the argument that
class names are constants?
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.8 (Darwin)

iEYEARECAAYFAkg1cSMACgkQJA/zY0IIRZaVYACfYKNZSIRdk1IUeEVSgCAMhto6
vP8An25z7xkB0HzOwszj8U6zlocudryQ
=oNYV
-----END PGP SIGNATURE-----

On Thu, May 22, 2008 at 5:34 PM, ara.t.howard [email protected]
wrote:

it’s subtle, but there is no such thing as a ‘class name’, rather there are
classes that a held in variables, often these variables are constants, but
not always, and it is true that ruby give you the illusion that they are
names via a handy Class#name method, but note that this is really just
inspect and not specific to classes:
Hmm Ara, are you sure?
Is it not the interpreter that “quirks”, as I have put it, the name of
a class when it is assigned to a constant, either via
class Klass
but also via
Klass = Class::new
while it quirks it to “” if we do
c = Class::new

I think it is a mess, after reading your metakoan Rubyquiz I should
never ever have used constants to point to classes anymore, I am a
weakling :wink:
Cheers
Robert

On Thu, May 22, 2008 at 3:12 PM, Florian G. [email protected]
wrote:

c = Class::new { def … }

So how does the creation of an anonymous class hurt the argument that class
names are constants?
I will try to answer your question with another one.
What is the name of the class above? Well it is “”, would you say this
is a constant?
This however is not what was most missleading. It does not matter if a
constant is pointing to a class or not, class names are not constants
at all, there is just this little quirck in Ruby that
X = Class::new
sets X.name to “X” by some magic.
This allows to reopen the class with
class X
instead of writing
c.module_eval

c.module_eval creates faster code though…

Cheers
Robert

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.8 (Darwin)

iEYEARECAAYFAkg1cSMACgkQJA/zY0IIRZaVYACfYKNZSIRdk1IUeEVSgCAMhto6
vP8An25z7xkB0HzOwszj8U6zlocudryQ
=oNYV
-----END PGP SIGNATURE-----


http://ruby-smalltalk.blogspot.com/


Whereof one cannot speak, thereof one must be silent.
Ludwig Wittgenstein

On May 22, 2008, at 9:45 AM, Robert D. wrote:

Hmm Ara, are you sure?
Is it not the interpreter that “quirks”, as I have put it, the name of
a class when it is assigned to a constant, either via
class Klass
but also via
Klass = Class::new
while it quirks it to “” if we do
c = Class::new

heh - point taken. i think we are saying the same thing: the concept
of a class ‘name’ is quite fragile.

I think it is a mess, after reading your metakoan Rubyquiz I should
never ever have used constants to point to classes anymore, I am a
weakling :wink:

lol - well, like many things in ruby it’s quite ‘human’ feeling quite
natural yet containing some internal contradiction. i guess the main
point is that we all seem to find it fairly natural to use - that
counts for something.

cheers.

a @ http://codeforpeople.com/

Robert K. wrote:

It is a general feature of the language to not be too
restrictive about such things.

Maybe we could have the option of generating an error rather than a
warning if a constant is changed. Maybe there’s some way to do this
already (raising an exception)?

On May 22, 2008, at 9:39 AM, Robert D. wrote:

c.module_eval creates faster code though…

really? that’s interesting.

a @ http://codeforpeople.com/

On Thu, May 22, 2008 at 6:05 PM, ara.t.howard [email protected]
wrote:

On May 22, 2008, at 9:39 AM, Robert D. wrote:

c.module_eval creates faster code though…

really? that’s interesting.
You are right I better recheck that …
… indeed I was wrong, I just increased N from 105 to 106 and
that equals out what must have been measurement fluctations caused by
the extremely short runtime.
The performance is equal.

require ‘benchmark’

class A
def a; 42 end
end
a = A.new
B = Class::new
B.module_eval do
def a; 42 end
end
b = B.new

N=100_000

Benchmark::bmbm do |bm|
bm.report( “classic” ) do
N.times do
a.a
end
end
bm.report( “meval” ) do
N.times do
b.a
end
end
end
R.

On May 22, 2008, at 4:38 AM, Florian G. wrote:

If you noticed, class names are constants. As you can change classes
at runtime, constants must be changable.
Actually overwriting Constants emits a warning. A you should program
warnings-free, that should be no problem :).

Sure, you can change classes at runtime, but should you be able to
change which object is referenced by a class name? I haven’t heard of
that before. Do you have a real-world example of someone doing that?
Just curious.

///ark

On Thu, May 22, 2008 at 04:49:32PM +0900, Pe??a, Botp wrote:

From: George W. [mailto:[email protected]]

i too had this problem, and the closest i can get is to wrap the constants in
a module and then freeze the module.

Interesting new knowledge for me when I test this out. I didn’t know
that what
is returned from the end of a class … end and module … end block is
NilClass.

% cat x.rb
module C
X = 42
end.freeze

puts “C::X => #{C::X}”
C::X = 99

puts “C::X => #{C::X}”
C.freeze
C::X = 42

puts “C::X => #{C::X}”

% ruby x.rb
C::X => 42
x.rb:6: warning: already initialized constant X
C::X => 99
x.rb:10: can’t modify frozen module (TypeError)

Hmm… lets look at what is returned by the end of a module and a class

% cat c.rb
c = class C; end
puts c.inspect

m = module M; end
puts m.inspect

% ruby c.rb
nil
nil

You learn something new every day.

enjoy,

-jeremy

Class names are strings.

The name of an anonymous class is an empty string.

The first time a class is assigned to a constant gets its name from
the constant identifier.

That happens automatically behind the scenes the first time you say
class Foo.

Once a class gets its name the container where the class object lives
is irrelevant, the name is set in stone.

Normally constant User holds a class named “User”, but technically it
could store a class named “Project”.

Apart from those rules, constants and class objects are kind of
decoupled because they are just basic pieces of Ruby put together.

Jeremy H. wrote:

I didn’t know that what
is returned from the end of a class … end and module … end block is
NilClass.

It’s not. A class/module … end block returns the value of the last
expression in it. So
module C
X = 42
end.freeze
calls freeze on 42

HTH,
Sebastian