This comes up every so often on '''comp.lang.tcl''': Chris Nelson wrote: > For example, whereas I might write C like: > > struct s { > int foo > char bar > float grill > } > > s.foo = 1; > s.bar = 'c'; > s.grill = 3.14159; ====== proc struct { name thingys } { foreach thing $thingys { uplevel set $name.$thing \[ list \] } } struct s { foo bar grill } set s.foo 1 set s.bar c set s.grill 3.14159 ====== Of course, you probably dont just want to init the "struct" to nulls, but to reasonable values: ====== proc struct { name thingys } { foreach { key value } $thingys { uplevel set $name.$key $value } } struct s { foo 1 bar c grill 3.14159 } ====== Tcl has no types, but if you want to create a typing convention and then use types in your struct it is only a matter of adding ''type'' to the foreach that now iterates ''key'' and ''value'' over ''$thingys''. '''-PSE''' ---- How about this--values are optional; and there's a variable that lists all the fields in the structure: ====== proc struct {name fields} { upvar $name srec foreach fld $fields { set fldn [lindex $fld 0] set fldv [lindex $fld 1] lappend srec $fldn uplevel set $name.$fldn [list $fldv] } } struct s { foo {bar 1} {pi 3.1415926} } foreach fld $s {upvar 0 s.$fld field; puts "s.$fld: '$field'"} ====== '''HJ''' 10-12-2002 [escargo]: I have my own clumsy implementation of something like this; there are some properties that I found desirable for such structures to have: 1. Each structure can tell you its type. 1. Each structure can tell you the names of its fields. 1. It is possible to determine if the structure has a field with a specific name. 1. There are ways to set and get each field from the structure by name. 1. The structure is a value that does not depend on being assigned to a variable with a particular name. Is there a C struct analog that has these properties? ---- So how do I create a linked list, as I would in C? [Ro]: Well if you just want a list of objects you could just make a regular tcl list - they grow dynamically. Each element in the list could be a reference to an object... what are you trying to represent? [RS]: [List]s we have. The purpose of linked lists is often to allow insertion or deletion of elements, which our flat lists allow with [linsert], [lreplace] and (probably most often wanted), [lappend]. You could simulate a linked list with an array, e.g., ====== set a(1,content) "hello world" set a(1,prev) 0 ;# "pointer" to previous set a(1,next) 2 ;# "pointer" to next element ====== ... but I doubt whether that's more efficient than linsert/lreplace... [escargo]: This does beg the question of how you would do a ''circular'' linked list using a tcl list, which is easy enough to do in C (or other language with pointers or references). [RS]: Indeed, that's the strongest point against(?) flat lists, which is occasionally also raised in favor of Lisp. But iterating over a circular list may get you nowhere... However, to ''cycle'' over a list is easy in Tcl, and that is a frequent use for circular lists: ====== proc cycle listName { upvar 1 $listName list set first [lindex $list 0] set list [concat [lrange $list 1 end] [list $first] set first } ====== '''Lars H''': Even better would be ====== proc cycle listName { upvar 1 $listName list set first [lindex $list 0] set list [lreplace $list [set list 0] 0] lappend list $first set first } ====== since it (usually) allows the original object of the list to be modified in place and thus avoids allocating new storage for the list. '''yajiang''': in side tcllib '''struct::record''' usage above are all covered in this package struct::record. maybe you guys wanner take a look http://tcllib.sourceforge.net/doc/record.html <> Arts and crafts of Tcl-Tk programming | Category Data Structure