'''Is there a mechanism whereby I can create [constants] or even better, enumerated types within Tcl?''' ---- ''KBK:'' In Tcl, everything is a string, so you can simply use your names as constants. If you want to assign numeric values, you can do something like: set fruits { apple blueberry cherry date elderberry } set i 0 foreach fruit $fruits { set fruit_number($fruit) $i incr i } proc fruit_to_number { fruit } { variable fruit_number if { [catch { set fruit_number($fruit) } number] } { return -code error "$fruit: no such fruit" } else { return $number } } proc number_to_fruit { number } { variable fruits if { [catch { if { $number < 0 || $number >= [llength $fruits] } { error {out of range} lindex $fruits $number } fruit] } { return -code error "no fruit with number $number" } else { return $fruit } } ---- ''DKF adds: I reckon it is easier to just load up a pair of arrays to map in each direction, and then use them directly, which we can dress up like this...'' proc makeEnum {type identifiers} { upvar #0 ${type}_number a1 number_${type} a2 set n 0 foreach id $identifiers { incr n set a1($id) $n set a2($n) $id } proc ${type}_to_number $type " upvar #0 ${type}_number ary if {\[catch {set ary(\$$type)} num\]} { return -code error \"unknown $type \\\"\$$type\\\"\" } return \$num " proc number_to_${type} {number} " upvar #0 number_${type} ary if {\[catch {set ary(\$number)} $type\]} { return -code error \"no $type for \\\"\$number\\\"\" } return \$$type " } makeEnum fruit {apple blueberry cherry date elderberry} ---- ''KBK:'' I like the 'makeEnum' syntax, but [[lindex]] is faster than an array search, at least in Tcl 8.3.2. Also, was there a reason you switched from zero-based to one-based indexing? ''(DKF: no, it just came out that way. :^)'' Consider the alternative implementation: proc makeEnumKBK {type identifiers} { upvar #0 ${type}_number a1 set n 0 foreach id $identifiers { set a1($id) $n lappend list $id incr n } proc ${type}_to_number $type " upvar #0 ${type}_number ary if {\[catch {set ary(\$$type)} num\]} { return -code error \"unknown $type \\\"\$$type\\\"\" } return \$num " proc number_to_${type} {number} " if { \[catch { if { \$number < 0 || \$number >= [llength $list] } { error {out of range} } lindex [list $list] \$number } $type\] } { return -code error \"no $type for \\\"\$number\\\"\" } return \$$type " } makeEnumKBK froot {apple blueberry cherry date elderberry} Running comparative timings on my machine shows that the array+list implementation is significantly faster, mostly because it avoids the cost of the [[upvar]]: Time (us; 550 MHz PIII) Action Two arrays Array + list ------------------------------------------------------------ Convert enum to number 23 23 Try to convert nonexistent enum to number 80 81 Convert number to enum 23 13 Try to convert out-of-range number to enum 79 60 Try to convert non-number to enum 80 65 ------------------------------------------------------------ ---- [RS] has this variation, based on a little codelet in [Complex data structures]: proc makeEnum {name values} { interp alias {} $name: {} lsearch $values interp alias {} $name@ {} lindex $values } % makeEnum fruit {apple blueberry cherry date elderberry} fruit@ % fruit: date 3 % fruit@ 2 cherry Gives you sweet little mappers symbol -> number, and back. No error checking, but no global variables either - and no backslashes in code ;-)