succint access to constants/class methods?

C

Csaba Henk

One of the things I deeply like in ruby that succintness is an intrinsic
design principle.

Ruby is just the opposite of that what the infamous standard Java
"hello world" encapsulates. In general. But it seems to me that there
are some problem with proper access to constants and class methods and
succintness.

See a naive code:

####

class A
C = 0
def self.bar
""
end
def foo
[A.bar,C]
end
end

class B < A
end

B.new.foo # => ["",0]

####

-- this is succint, and works as it should. But what if we make up our
mind so that B should roll its own?

####

class B
C = 1
def self.bar
"x"
end
end

B.new.foo # => ["",0]
# bummer...

####

If we want the reference to the constant and the class method be
properly dispatched on B (provided B has them), we have to modify
A#foo as follows:

####

class A
def foo
[self.class.bar, self.class::C]
end
end

B.new.foo # => ["x",1]
# that's it!

####

But succintess is lost here. Does anyone know a better way of doing it?

What's extra annoyance that you have to write the longish "self.class",
and not just "class", as this latter would be mistaken with the reserved
word "class". Why is there no an alternative for Object#class which
doesn't collide with a reserved word? (There is Object#type, but that's
deprecated, and you are warned to use Object#class.)

Csaba
 
J

James Britt

Csaba said:
One of the things I deeply like in ruby that succintness is an intrinsic
design principle.

Ruby is just the opposite of that what the infamous standard Java
"hello world" encapsulates. In general. But it seems to me that there
are some problem with proper access to constants and class methods and
succintness.

This may not give you quite the answer you are looking for, but it may
help explain the behavior you are seeing:

http://www.rubygarden.org/ruby?ClassMethodsTutorial


James
 
C

Csaba Henk

This may not give you quite the answer you are looking for, but it may
help explain the behavior you are seeing:

http://www.rubygarden.org/ruby?ClassMethodsTutorial

Yes, I know class methods are just singleton methods of classes, thus
it's quite clear that if I use A.foo then that message "foo" will be
dispatched at A and nobody else.

Contsants are more ambigouos. When you refer to the contsant C in an
instance method just this way, writing a letter C, it's not specified
explicitely whom should be the receiver.

What you get by self.class::C is the desirable behaviour in the 99% of
cases: thus C is visible from subclasses' instances as well, but can be
overridden in a subclass. As one would expect in an object oriented
environment.

How many of you would disagree would disagree with the above paragraph?
And how many of you uses self.class::C in her/his own code, rather than
just the plain simple comfortable C?

And it's such a stupid accident that the method which sets the right
receiver just can't be used without the "self." prefix...

Csaba
 
T

Trans

What you get by self.class::C is the desirable behaviour in the 99% of
cases: thus C is visible from subclasses' instances as well, but can be
overridden in a subclass. As one would expect in an object oriented
environment.

I beleive I agree. I have started to think that the idea of a
_constant_ has no place in Ruby all together. I say, throw the warning
about constant redefinition away.
And it's such a stupid accident that the method which sets the right
receiver just can't be used without the "self." prefix...

Yes, it is kind of silly and I'm suprised it can't be handled. I've
suggested __class__ before as a reserved backup, though that isn't all
that succinct either.

T.
 
C

Csaba Henk

I beleive I agree. I have started to think that the idea of a
_constant_ has no place in Ruby all together. I say, throw the warning
about constant redefinition away.

Btw, redefining a constant in a subclass doesn't trigger that warning.

class A
Foo = 5
end
class B < A
Foo = Foo + 1
# Foo +=1 is also OK
end

[A::Foo,B::Foo] # => [5,6]

What happens here is that at its creation B doesn't have Foo defined in
it. Then, when doing "Foo = Foo + 1", ruby first finds out Foo's value
in the initial context (finds that in A), then adds one to it and
defines a fresh new Foo, exclusively for B, with that value. No constant
has been redefined...

What now I'm wondering about is the following: as I see, there is no way to
reflect to the place of a definition of a constant. That is,

class A
Foo=5
end
class B < A
end

[A::Foo, A.constants, class A; self::Foo; end] #=> [5, ["Foo"], 5]
[B::Foo, B.constants, class B; self::Foo; end] #=> [5, ["Foo"], 5]

You'll only see a difference when you try to assign to Foo in A and in
B's context, which does give a reflection in some sense, but that's quite an
ugly one :)
Yes, it is kind of silly and I'm suprised it can't be handled. I've
suggested __class__ before as a reserved backup, though that isn't all
that succinct either.

Well, I came to the conclusion that I'll add a "cl" instance method to
those classes where it's a concern. (Maybe "_cl", or make it private if
namespace pollution is an issue.)

Csaba
 
C

Csaba Henk

Btw, redefining a constant in a subclass doesn't trigger that warning.
[snip]

defines a fresh new Foo, exclusively for B, with that value. No constant
has been redefined...

To avoid confusion, I should have written:

Btw, "redefining a constant in a subclass" doesn't trigger that warning.

Csaba
 
I

itsme213

Trans said:
can

I beleive I agree. I have started to think that the idea of a
_constant_ has no place in Ruby all together. I say, throw the warning
about constant redefinition away.

Constant = An accessor for a "frozen" instance variable ?
 

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,764
Messages
2,569,566
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top