From: Hugh Sasse Staff Elec Eng Date: 2000-03-17T10:03:36+00:00 Subject: [ruby-talk:01963] Re: Enumerations and all that. On 16 Mar 2000, Dave Thomas wrote: > > Well, I've thinking about enumerated types, and was wondering how they > fit in to a typeless language. > > I came to the conclusion that there cannot be such things as free > standing enumerated objects, because the semantics would be all > wrong. If we have > > thing = Enum.new(:red, :green, :blue) > > Then how can we use it? We can have > > thing.set(:red) > > and > > thing.value #-> :red > > but does that help? Not really, because nothing stops you having > > thing = 'wombat' Granted, but we can see that thing.type has changed. I could do better if I could overload the = operator, but then we would need destructors so that variables could be reused. > > > To my mind, the benefit of enumerated types comes from ensuring that > the range of values taken by something is predetermined, and we can't > do that with free variables. > > However, we probably don't want to do it with free variables. Instead, > we want to make sure that the parameter to our Door#setState method is > either :open or :closed. So it seems to make sense to have enumerated > types associated with class attributes. I follow your reasoning but I don't think your conclusion is the only possible one. :-) The hash I create with initialise in mine cannot be modified later, which is the important thing constants give you. > So, I came up with the following. Here's a class Spigot with two > enumerated type attributes: > > class Spigot > > enum :color, [ :red, :green, :blue ] > enum :size, { :small => -1, :medium => 0, :large => 99} this flexibility I like. > > end [...] > The external world can set and query the value of either of these > object attributes: > > s = Spigot.new > > s.color = :red > s.size = :large > > p s.color > p s.size This can only be done for classes which have been given the enum method. Also, this 'looks' like encapsulation is being broken, because s.color is not a method call, but accessing something inside s. > > However, if you try to set an attribute using a value that's not > associated with it, a TypeError is raised: > > s.color = :large #-> TypeError OK, a TypeError was what I needed in mine. Thanks. > > > Finally, within class Spigot, you can get to the internal value of an > attribute using _val. If the size is set to :large, > size_val will return 99. Mine does more or less that, but it uses @_value to hold the number. Being a class, mine can be used without the containing class declaring an enum method. With mine you can "break encapsulation" to get at the values the thing can take, or you can just use strings. I have not thought of a nice way to extend the idea of "enumeration" to things other than numbers, which yours may be better at. (This would use the hash to tie names (or even objects?) to objects other than numbers, but still allow the type only the permitted values.) > > class Spigot > def printState > printf "Internal value of color is #{color_val}\n" > printf "Internal value of size is #{size_val}\n" > end > end > > > I implemented 'enum' by extending class Module. It's a fairly ugly > hack right now, but there's scope for it to be tidied... > > Anyway, here's all the code. It works under 1.5, but I'm not sure if > the new Symbol stuff means it doesn't work under 1.4. Not sure what you mean here, the only "unusual" thing is the id2name but that is in the 1.4 manual. > > I'd be interested in comments. I hope these are of interest, though they are somewhat critical, they are intended positively. There is some cunning stuff in that code I'd like to re-use :-) > > > Dave > > ############################ cut here ############################# Hugh hgs@dmu.ac.uk