AIN - Array In Namespace Directions to find it at [Stu] A simple way to create and fill arrays (in namespaces) with (non)default values. Promotes using arrays to encapsulate data. Somewhat like a glorified [array set]. Not an object system. Almost no overhead - does not keep track of existing ains or overload [proc] or anything like that. It's simply arrays, should not interfere with anything From the distribution, simpleAinTutorial.tcl # Simple AIN (Array In Namespace) tutorial. # Cheeses. # Runnable. # Results noted with #=> # # Stuart Cassoff # January 2007 # # Setup package require ain #=> 0.2 namespace import ::ain::* # We want to keep things nice and tidy, so let's create # a namespace where we'll put our cheeses. set ns ::cheeses namespace eval $ns {} # First we make a 'cheese' ain of __ain_type 'ain' # -prefix and -namespace are the two most important options, # they indicate where the ains will be stored and what they # will be named. # New 'cheese' ains will be created based on the -struct member # with the defaults, unless overridden ainNew ain \ -__ain_type cheese \ -namespace $ns \ -prefix fromage# \ -struct [list name {} country {} hardness firm animal cow] #=> ::ain::ains::ain#1 # The return value from ainNew is the ain which will be used as # the template for any future ains of type 'cheese'. # We don't need this value unless we need to delete # the 'cheese' ain of __ain_type 'ain'. # We can see that an ain of __ain_type 'cheese' is now # available for our use. # [ainAins] returns a list of available ains. ainAins #=> ain cheese # Note that an ain is also an ain! # Apologies, I have yet to master statements like: # "cheese is an ain of type ain which is used to create ains of type cheese" # "ain is an ain of type ain which is used to create ains of type ain" # Moving on ... # Now we can make as much cheese as we want! set c0 [ainNew cheese] #=> ::cheeses::fromage#0 # fromage#0 is an array in the namespace ::cheeses parray $c0 #=> ::cheeses::fromage#0(animal) = cow #=> ::cheeses::fromage#0(country) = #=> ::cheeses::fromage#0(hardness) = firm #=> ::cheeses::fromage#0(name) = # Let's make another cheese, overriding some of the defaults. # We'll even add a new element to our newly created 'cheese' ain. # Notice how elements are given with a leading '-' but are # stored without it. Order of options is not important. set c1 [ainNew cheese -animal goat -name feta -country Greece -texture crumbly] #=> ::cheeses::fromage#1 parray $c1 #=> ::cheeses::fromage#1(animal) = goat #=> ::cheeses::fromage#1(country) = Greece #=> ::cheeses::fromage#1(hardness) = firm #=> ::cheeses::fromage#1(name) = feta #=> ::cheeses::fromage#1(texture) = crumbly # Accessing ain elements. # Since ains are simply arrays, # one would access them using regular array methods. # These all give the same result # The braces in the first statement are needed # due to the '#' in the ain name puts ${::cheeses::fromage#1(texture)} #=> crumbly puts [set ${c1}(texture)] #=> crumbly upvar #0 $c1 arr puts $arr(texture) #=> crumbly # Since ains are fully namespace qualified arrays, they # can be easily passed around and accessed. proc fave_cheese {ch} { upvar 1 $ch cheese puts -nonewline "My favorite cheese is " puts -nonewline $cheese(name) puts -nonewline " because of its " puts -nonewline $cheese(texture) puts " texture!" puts -nonewline [string totitle $cheese(name)] puts -nonewline " often comes from " puts -nonewline $cheese(country) puts "." } fave_cheese $c1 #=> My favorite cheese is feta because of its crumbly texture! #=> Feta often comes from Greece. # Let's try with another cheese! set c2 [ainNew cheese -name cheddar -country England -texture smooth] fave_cheese $c2 #=> My favorite cheese is cheddar because of its smooth texture! #=> Cheddar often comes from England. # We've enjoyed our delicious cheeses, now it's time to get rid of them. # This is essentially the same as [unset -nocomplain] # Some additional work is performed for more complex # cases but not in this tutorial. # Goodbye cheddar, we'll miss you ainDelete $c2 # Note that the ain extension does not keep track of any ains # other than __ain_type 'ain'. # The extension aims to be as lightweight and non-intrusive as possible. # 'Till we meet again, feta ainDelete $c1 # Drop this one, too. ainDelete $c0 # We can clean up completely and remove 'cheese' from the available ains. # This was created way back in the beginnnig of this tutorial ainDelete {::ain::ains::ain#1} # Check ainAins #=> ain # Only 'ain' is left, it can be deleted but that would render the # ain extension useless! # EOF