Enumeration (Ala Pascal, C, Ada)

  • Thread starter James B Crigler
  • Start date
J

James B Crigler

I put together the code that follows in an attempt to emulate (in a
crude way) the "enumeration" types of Ada, C, Pascal, etc.

The two classes reside in the same file and attempt to solve a
problem I had with a process management system I use: The reports
--- a separate file for each change --- list the status of the
particular change. I wanted to be able to go through the reports and
list all the changes for which the status is "less than" (or greater
than or no bigger than or ...) some given status IN TERMS OF THE
CHANGE DOCUMENT'S LIFE CYCLE, where statuses are not in alphabetical
order. (This is a facility that the change management system itself
does not provide.)

The code works within the constraints within which it works. ("I'll
take tautologies for 10, Alex!") I typically use it for composing
command-line queries. E.g., if the possible states of a change doc
are "CUT", "INSERT", "CHEW", "SWALLOW", "DIGEST", "BELCH", then the
StringStatusList is initialized with an array of those strings (in
the given order). Multiple change doc types with disjoint status
sets may be used simultaneously. When a report representing one
change doc is read (and the status attribute is requested), the
StringStatusList object is asked for the StringStatus of a particular
string as read from the report or supplied at the command line. The
StringStatusList object is stored in the change doc's class. This
allows me to write expressions like

$ss = doc.class.status_of("CHEW")
...
doc.status < $ss

and get all the docs that have a status of "CUT" and "INSERT".

Have I reinvented a wheel that already rolls?
--
Jim Crigler

#!/home/jcrigler/bin/ruby -w

# @(#) stringstatus.rb 1.1 2004/07/06 13:07:47 @(#)

class StringStatus < String
attr_reader :vec, :val

def initialize(val, enumVector)
super (enumVector[val])
@Val = val
@vec = enumVector
end

def _checkVec(otherStatus)
if @vec != otherStatus.vec
raise "#{self.class.to_s}: comparing the incomparable"
exit(1)
end
end

def <(otherStatus)
self._checkVec(otherStatus)
@Val < otherStatus.val
end

def ==(otherStatus)
self._checkVec(otherStatus)
@Val == otherStatus.val
end

def <=(otherStatus)
self < otherStatus or self == otherStatus
end

def >(otherStatus)
! (self <= otherStatus)
end

def >=(otherStatus)
! (self < otherStatus)
end

end

class StringStatusList
def initialize(aVec)
@vec = aVec
@h = Hash.new
(0 ... @vec.length).each do |i|
@h[@vec] = StringStatus.new(i, @vec)
end
end

def value(candidate)
raise "#{self.class.to_s}: unusable candidate #{candidate}" \
unless @h.has_key? candidate
@h[candidate]
end
end
 
T

Tim Hunter

James said:
I put together the code that follows in an attempt to emulate (in a
crude way) the "enumeration" types of Ada, C, Pascal, etc.

I don't know if this is exactly what you're looking for, but check out
http://addlib.rubyforge.org/wiki/wiki.pl?EnumClass. This is a class that is
to C enums what Struct is to C structures. I've offered it for inclusion to
the addlib project, but if you think it will be useful you can get it now
by copy'n'pasting the code from the wiki or I'll be glad to email you a
copy.
 
J

James B Crigler

Tim said:
I don't know if this is exactly what you're looking for, but check out
http://addlib.rubyforge.org/wiki/wiki.pl?EnumClass. This is a class that is
to C enums what Struct is to C structures.

Thanks, Tim. I did a copy and paste of the code from the wiki, and it
is very interesting. I hadn't thought of the runtime definition of Enum
subclasses --- that's a very nice touch.

Unfortunately, my problem is a little different. Buried in what I originally
wrote is this statement:
Multiple change doc types with disjoint status sets may be used
simultaneously.

I misstated the case here: The status sets may have a few identical
names, e.g., an Edibles could have a set of statuses like
"CUT", "INSERT", "CHEW", "SWALLOW", "DIGEST"
while a Readables class could have a set of statuses like
"OPEN", "READ", "CONSIDER", "DIGEST", "MEDITATE"

Your Enum solution can't prevent me from comparing these two.
 
P

Paul Brannan

I misstated the case here: The status sets may have a few identical
names, e.g., an Edibles could have a set of statuses like
"CUT", "INSERT", "CHEW", "SWALLOW", "DIGEST"
while a Readables class could have a set of statuses like
"OPEN", "READ", "CONSIDER", "DIGEST", "MEDITATE"

Your Enum solution can't prevent me from comparing these two.

You may find enum.rb from rubycollections more to your liking, then:

http://cvs.sourceforge.net/viewcvs.py/rubycollections/rubycollections/rbc/enum.rb

It has a very similar interface to the one on the addlib wiki (not
entirely an accident, since Tim's enum is based off my RCR and my RCR
was based off my implementation of enum :).

Differences between Tim's enum and the one in rubycollections:

- Tim's enum doesn't work on 1.6.x; mine does (probably not an issue
unless you work in a production environment where you are slow to
upgrade, as we are where I work)
- constants in Tim's enum are all the same class (Enum::Enumerator);
rbc enum creates a new type whenever you call Enum.new.
- Tim's enum has all the math operators that mine lacks (so you can
easily replace code that uses the integer constants for doing bit
operations with code that uses enums instead)
- Tim's enum restricts you to using integers (not entirely a bad
thing); mine allows the use of other types, such as strings (I've
only rarely found a use for this; a hash would probably have done as
well)
- When inspected, Tim's enum prints both the name and the value of the
enum, a very nice feature.

Also, something I didn't mention in the RCR but which would be nice is
the ability to create an enum from either a hash or an array, e.g.:

Foo = Enum.new:)A, :B, :C)
Bar = Enum.new:)A, 1, :B, 5, :C)
Baz = Enum.new:)A => 1, :B => 5, :C => 6)

Paul
 

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
474,139
Messages
2,570,805
Members
47,356
Latest member
Tommyhotly

Latest Threads

Top