proc atom x {
    if {[catch {set ::Atom($x)}]} {
        set ::Atom($x) $x
    } else {set ::Atom($x)}
}#-- Testing
% set res {}
% foreach test {foo bar grill bar foo} {lappend res [atom $test]}
% parray Atom
Atom(bar)   = bar
Atom(foo)   = foo
Atom(grill) = grill
% puts $res
foo bar grill bar fooThe test shows that while you see the atom values multiple times, they only appear in the array once.Disadvantage: If used uncritically, the Atom array may grow considerably in long-running apps. Values that are unlikely to occur repeatedly should better not be "atomized". For instance, in a library database application, author or publisher names or years are well worth sharing with atoms, but books' titles probably not.DKF: This is sometimes called "intern"ing the strings. Tk interns many strings internally (as [Tk_Uid]s); this is the most common cause of memory leaks in Tk applications, though in many situations it doesn't matter.DKF: Tcl also effectively interns constants, though less aggressively (and with a more controlled lifespan).escargo - What would be the difference between [catch set ::Atom($x)] and [catch {set ::Atom($x)}]?one does what you expect, and one doesn't. Only the first argument to catch will be executed; in the case of your first example that would be the one-word command "set" - RS: oops - fixed.. :^) - not examining catch results may indeed hide bad bugs...LV Hey, anyone know if there is a functional difference between the atom proc above and this one?
proc atom x {
    if { [info exists ::Atom($x)]} {
        set ::Atom($x)
    } else {
        set ::Atom($x) $x
    }
}The main reason I like this is that the if more clearly specifies why it is executed. - RS: see Tcl performance: catch vs. info.

