Singleton Class Constants

David Black wrote in Ruby For Rails (page 341):

(There’s also a subtle difference between these two approaches to
defining a singleton method, involving the scope of constants, but that’s an
arcane point. For the most part, you can treat them as equivalent.)

The subject of singleton methods and constants has recently gotten me
into trouble. Here is a simplified example:

module ExtendMeFirst
BAR = 3
end

module ExtendMeSecond
def print_bar
puts BAR
end
end

class A
extend ExtendMeFirst
extend ExtendMeSecond
end

A.print_bar #=> NameError: uninitialized constant ExtendMeSecond::BAR

Now, I somewhat understand why this doesn’t work - the constants are in
different scopes. The challenge is to get around this problem and use
the constant BAR from ExtendMeFirst in module ExtendMeSecond. We
discovered that what we needed to was access the singleton class’s
constants, but there is basically no easy way to do this, since there
is no “singleton_class” method in Object/Kernel (which has been
discussed a long time ago on this list). We eventually added one:

class Object
def singleton_class
class << self; self; end
end
end

And then doing this allowed us to get to the constant:

module ExtendMeSecond
def print_bar
puts singleton_class::BAR
end
end

Is there a better way to do this? What is the “arcane point” about
singleton methods and constants?

On Thu, 12 Oct 2006 [email protected] wrote:

class Object
def singleton_class
class << self; self; end
end
end

fyi. i prefer

class Object
def singleton_class &block
sc = class << self; self; end
block ? sc.module_eval(&block) : sc
end
end

for it allows

class C
singleton_class{
attr ‘a’
alias_method ‘b’, ‘a’
}
end

regards.

-a

Hi –

On Thu, 12 Oct 2006, [email protected] wrote:

David Black wrote in Ruby For Rails (page 341):

(There’s also a subtle difference between these two approaches to
defining a singleton method, involving the scope of constants, but that’s an
arcane point. For the most part, you can treat them as equivalent.)

For the answer to your last question:

What is the “arcane point” about singleton methods and constants?

see the recent thread on ‘“def self.method” vs “class << self; def
method”’. (It’s the example with the top-level vs. class-specific
contants.)

end
different scopes. The challenge is to get around this problem and use
end

And then doing this allowed us to get to the constant:

module ExtendMeSecond
def print_bar
puts singleton_class::BAR
end
end

Is there a better way to do this?

I don’t think there’s any way that doesn’t involve some kind of
coupling, since you’re basically printing one module’s constant from
another module (using “module” as class-or-module). The way you’ve
done it presupposes that ExtendMeSecond will indeed be mixed in to a
singleton class subsequent to the mixing in of ExtendMeFirst. You
could, instead, cut out one leg of the journey and just say:

def print_bar
puts ExtendMeFirst::BAR
end

which is a different kind of coupling, but really isn’t inherently
worse than calling Math::PI or any other constant from another module.

David

which is a different kind of coupling, but really isn’t inherently
worse than calling Math::PI or any other constant from another module.

David

This problem originally arose from trying to extend/alter some
functionality of Rails in a plugin, and needing access to some
constants defined in a ClassMethods module that uses the:

def self.append_features(base) # :nodoc:
  super
  base.extend ClassMethods
  ...

idiom that is used frequently in rails. To me, the “mixin” concept
creates some weird decisions to make with repsect to coupling. In some
other OOP languages, extending the functionality might be done by
creating a new class that derives from ActiveRecord, and then
overriding the functions in question to provide new behavior.

In Ruby/Rails however, especially with plugins, it seems to be much
more common to use the include and extend functionality to bring new
functions into an existing class, or override them. When you do this,
you’re frequently going to want to make assumptions about your context
in the new mixin since you know where it’s going, however, conceptually
a mixin should be somewhat context ignorant, should it not?

Hi –

On Thu, 12 Oct 2006, [email protected] wrote:

singleton_class{
attr ‘a’
alias_method ‘b’, ‘a’
}
end

I prefer it without that, since that makes it deviate from the #class
method, which it’s otherwise precisely parallel to. I’d rather that
singleton_class work like class than that it work like class_eval.
Otherwise you’ve got a situation where all classes except singleton
classes have to call class_eval, and I don’t see any grounds for
granting that privilege.

(I know we’ve hashed through this before, and don’t agree; I just
wanted to summarize the dissident position :slight_smile:

David

On Oct 11, 2006, at 3:13 PM, [email protected] wrote:

I prefer it without that, since that makes it deviate from the #class
method, which it’s otherwise precisely parallel to. I’d rather that
singleton_class work like class than that it work like class_eval.
Otherwise you’ve got a situation where all classes except singleton
classes have to call class_eval, and I don’t see any grounds for
granting that privilege.

I agree with David’s point about the discrepancy but couldn’t that
be also resolved by changing the standard #class method to behave like
Ara’s proposed #singleton_class ?

Gary W.

Hi –

On Thu, 12 Oct 2006, [email protected] wrote:

be also resolved by changing the standard #class method to behave like
Ara’s proposed #singleton_class ?

Yes, but that seems awfully magic and hidden. I don’t see what there
is about querying an object for its class that suggests a context for
an implied class_eval.

David

Hi –

On Thu, 12 Oct 2006, [email protected] wrote:

wanted to summarize the dissident position :slight_smile:

with

def foobar
class.class_eval{ attr ‘added_a_class_attr’ }
end

one word, i realize, but open{} only saves a close too - they add up!

Well… it has to be self.class :slight_smile: But in any case, though I’m a big
fan of Ruby’s expressive power, I don’t think it’s rooted in pruning
away method calls as an end in itself. open is an operation with
extent in time, and a block is good at meshing with that. class_eval
is also such an operation – but just retrieving the name of a class
isn’t.

(I’m not saying that “extent in time” is the only block-worthy thing,
but I just can’t see how obj.class suggests any kind of segue to a
blockwise operation.)

David

On Thu, 12 Oct 2006 [email protected] wrote:

I prefer it without that, since that makes it deviate from the #class
method, which it’s otherwise precisely parallel to. I’d rather that
singleton_class work like class than that it work like class_eval.
Otherwise you’ve got a situation where all classes except singleton
classes have to call class_eval, and I don’t see any grounds for
granting that privilege.

(I know we’ve hashed through this before, and don’t agree; I just
wanted to summarize the dissident position :slight_smile:

hmm. i don’t disagree completely - i would just say that those other
methods,
‘class’ for example, should take blocks. blocks are 25% of the reason
ruby is
so beautiful and clean looking. compare

def foobar
class{ attr ‘added_a_class_attr’ }
end

with

def foobar
class.class_eval{ attr ‘added_a_class_attr’ }
end

one word, i realize, but open{} only saves a close too - they add up!

cheers.

-a

On Thu, 12 Oct 2006 [email protected] wrote:

Ara’s proposed #singleton_class ?

Yes, but that seems awfully magic and hidden. I don’t see what there
is about querying an object for its class that suggests a context for
an implied class_eval.

the same thing that implies one for class creation

Class.new{

}

we could easily just do

Class.new.class_eval{

}

i might add that any of them is less esoteric than

class << self

 :wtf

end

implying ducking into an object’s singleton class

for that matter, why should

class PreExistingClass

 :at_least_this_makes_sense

end

do a class_eval, rather than clobber a class?

it also seems POLS - when has anyone every wanted a singleton_class
except
to evaluated code it in. plus, what other meaningful semantic would
passing a
block to a class do?

i love being devil’s advocate :wink:

-a

Hi –

On Thu, 12 Oct 2006, [email protected] wrote:

I agree with David’s point about the discrepancy but couldn’t that

}

we could easily just do

Class.new.class_eval{

}

I’ve actually always thought that new-with-block was a bit of a
stretch :slight_smile:

i might add that any of them is less esoteric than

class << self

:wtf

end

implying ducking into an object’s singleton class

I don’t think that’s esoteric; it’s just the way the class keyword
works: it takes either a constant, or a “<< object” expression (which
might be verbalized as “from this object” or something like that).

for that matter, why should

class PreExistingClass

:at_least_this_makes_sense

end

do a class_eval, rather than clobber a class?

It doesn’t exactly do a class_eval, from the scoping perspective. But
in any case it’s a bit far afield. Let’s say (argumentum ex concessis
:slight_smile: that class PreExistingClass not clobbering a class made no
sense. How would it follow that it’s a good idea for #class to take a
block?

it also seems POLS - when has anyone every wanted a singleton_class
except to evaluated code it in. plus, what other meaningful
semantic would passing a block to a class do?

POLS is so 2002 :slight_smile: But anyway – you’re not passing the block to a
class, exactly; you’re supplying the block to a method that returns a
class. The question is how the block pertains to the work of the
method. That’s where I don’t see the relevance.

i love being devil’s advocate :wink:

NOW you tell me?! :slight_smile: I have to say, as much as I don’t see the logic
of obj.class taking a block, I’d certainly rather have #class and [the
hopefully future] #singleton_class behave the same as each other in
that respect, whatever the behavior is.

David

On Thu, 12 Oct 2006 [email protected] wrote:

i love being devil’s advocate :wink:

NOW you tell me?! :slight_smile: I have to say, as much as I don’t see the logic
of obj.class taking a block, I’d certainly rather have #class and [the
hopefully future] #singleton_class behave the same as each other in
that respect, whatever the behavior is.

we’ll miss you at rubyconf david - only beer would solve this!

-a

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs