Maintainer: julian@webpub.net
License: Same as Tcl (BSD-style)
1.5.2 is a bugfix release.
(enum::bin2i didn't properly account for unsigned values - i.e it was sometimes wrong)
USAGE:
> package require enum ?1.5.2?
> enum create typename namelist
creates a new enumerated type typename mapping the string values in namelist to a corresponding list of integers starting at zero.
e.g
> enum create DAY {mon tue wed thu fri sat sun}
(DAY is capitalized here merely for clarity - this is not a requirement.)
> enum create FRUIT {peach pear cherry mangosteen}
> enum types
return the list of currently defined enumerated types.
e.g
> enum types
DAY FRUIT
> enum typename key
return the name or integer corresponding to key
i.e if key is an integer - return the corresponding name
if key is a name - return the corresponding integer
e.g
> enum DAY wed
2
(note that the list is zero-based - i.e jan is 0 not 1!)
> enum DAY 5
sat
> enum DAY spud
(raises an error: "unknown DAY 'spud'")
> enum DAY 20
(raises an error: "no DAY for '20'")
The above form 'enum typename key' is simple, yet does not always make for the clearest code.
Consider:
> enum DAY $day
It is not immediately apparent whether the above returns a name or a number.
For clarity, and to help catch mistakes; consider using the following forms:
> enum number typename key
e.g
> set day "wed"
> enum number DAY $day
2
> set day 4
> enum number DAY $day
(raises an error: "DAY has no number for '4' - try 'enum nam DAY 4' or another key")
> enum name typename key
e.g
> enum name DAY 4
fri
> enum name DAY sat
(raisesan error: "DAY has no name for 'sat' - try 'enum num DAY sat' or another key")
The shortcuts 'enum nam ...' and 'enum num ..' can also be used
> enum values typename
return the list of names for the type.
e.g
> enum values DAY
mon tue wed thu fri sat sun
> enum diff typename key1 key2
return the positive or negative difference between two keys.
(think of it as subtracting key2 from key1)
e.g
> enum diff DAY fri mon
4
> enum diff DAY mon fri
-4
> enum diff DAY fri 1
3
> enum dist typename key1 key2
similar to diff, but returns only the distance between keys i.e it is unsigned
e.g
> enum dist DAY fri mon
4
> enum dist DAY mon fri
4
> enum next typename key
Acts as if we had called 'enum typename' with the next key above the one supplied.
e.g
> enum next DAY wed
3
> enum next DAY 5
sun
Basic equality tests between two keys can be done with the operators: ==, !=, <, <=, >, >=
> enum typename key1 operator key2
This returns 1 or 0
e.g
> enum DAY fri > mon
1
This format is basically equivalent to something like:
> expr {[enum DAY fri] > [enum DAY mon]}
> enum vnext typename key
Also acts as if we had called 'enum typename' with the next key above the one supplied.
This time the result is the same type as the key
e.g
> enum vnext DAY wed
thu
> enum vnext DAY 5
6
> enum vnext DAY sun
(raises an error: "no next DAY for '6'")
Similarly we have:
> enum prev typename key
and
> enum vprev typename key
When thinking about 'next' vs 'vnext' and 'prev' vs 'vprev'
remember that the most natural purpose of enum to return the opposite type of key to that supplied.
- e.g 'enum months jan' returns 0 while 'enum months 0' returns jan
Therefore it is the 'unusually' named functions vprev & vnext that violate this
and return the same type of key as that which was given.
Note that it is usually not particularly useful to use vnext & vprev with a numeric key, as it could simply be done with expr, except that using these functions will raise an error when the *result* of a call would be outside of an enum's range.
Instead of an enumeration consisting simply of incrementing integers, enum can be used with values that are powers of 2 - suitable for bitmasks.
> enum create typename namelist -bitmask 1
e.g
> enum create DAY {mon tue wed thu fri sat sun} -bitmask 1
> enum DAY fri
16
> enum DAY sat
32
> enum DAY sun
64
You can then use bitwise binary operations to create flags and set & test bits
e.g
> set training [enum DAY mon | wed | sat]
37
Now days can be tested against the training flag using either their name or value
> enum DAY $training & mon
1
> enum DAY $training & tue
0
> enum DAY $training & 64
0
> enum DAY $training & sat
32
A single element can be unset from the flag using the &~ operator:
e.g
> set training [enum DAY $training &~ sat]
5
> enum DAY $training & sat
0
There are some conversion functions available for convenience.
e.g
> enum bits DAY mon | tue | fri | 64
01010011
> enum hex DAY mon | tue | fri | 64
53
> set binstring [enum bin DAY mon | tue | fri | 64]
S
> string length $binstring
1
> enum::bin2i $binstring
83
Note that if you create a bitmasked enumeration of a large number of items, the powers of 2 get somewhat unwieldy.
e.g
for {set i 0} {$i < 100000} {incr i} {
lappend list k$i
}
enum create BIG $list -bitmask 1
> enum BIG k222
> enum destroy typename
remove the enumerated type named typename
This package uses the Tcl >= 8.5 module system
(See http://mini.net/tcl/tcl
modules)
This module was wrapped using the tarpack package and is also a valid tar
archive.
Simply place it in one of the folders on your "Module path". No need to
unarchive. Because it is a simple Tcl-only package, it is stand-alone and you do not require the 'tarpack' package.
To determine your module path folders; type the command "::tcl::tm::list"
in a Tcl interp.
For example, on a windows platform, a folder such as c:\tcl\lib\site-tcl
might be a suitable choice.
If you do choose to unarchive a module on your module path - the 'package
require' operation will in effect be deflected by the .tm file to the
unarchived version.
i.e the unpacked code will take precedence.