goer@SOPHIST.UCHICAGO.EDU (Richard qua goer.) (05/05/90)
I wonder if we might do well to accumulate a "frequently-asked questions" list, to make things easier for people starting to learn Icon (presumably a large portion of the Icon-group's membership). I'll just post an entry, and if anyone wants to add to it, I'll simply append their additions to my list. I find that people starting to learn Icon tend to make similar mistakes, and I end up answering the same questions over and over. Not that answering them is difficult or tedious. I just hate to see people have to find out, after hours of debugging, that they have run into a problem that might easily have been avoided through the use of such a list. Take five minutes out, and add to the list! Problem: Why do I get unexpected results when I initialize a table like this: tbl := table([])? What I want is to make all the keys in tbl have empty lists as their initial values. Answer: Tables, sets, and lists in Icon are handled differently than, say, strings, csets, and integers. When you "dereference" a variable whose value is a string, cset, or integer, you get a string, cset or integer (nothing complicated here). In other words, if you say i := 1 j := i j will end up with a value of 1. When the i is dereferenced, it produces the integer 1, and *that* is what gets assigned to j. With structures like lists, however, dereferencing them produces a "pointer" to the structure in question. It does not produce a copy of the structure (for that, you have to use copy()). This is why, if you say l1 := ["hello"] l2 := ["hello"] if l1 === l2 then write("the same") else write("different") you will see "different" written to the screen. In effect, you have created two lists which, although they bear a structural similarity, reside in different places in memory, and therefore are *different lists*. What is the point here? The point is that, if you say tbl := table([]) you are actually setting up tbl so that each time you insert a new key, it will automatically be assigned the value produced by []. If you had said "tbl := table(1)" this would be fine. "1" produces the integer 1. Remember, however, that [] creates a specific structure (an empty list) and produces a pointer to that list. What you'll end up with, therefore, is a table with keys whose values are all pointers to the one list structure! What this does to your program is make it so that if you make any insertions into any key's value (e.g. tbl[key1] |||:= ["hello"] or insert(tbl[key1],"hello")), you will find, suddenly, that *all* of the keys' values have been modified. To make the long story short, you have to initialize the table using &null, tbl := table() # the same as tbl := table(&null) and then, each time you add a key, do this: /tbl[key] := [] # or /tbl[key] := list() The above expression first checks to see whether key has been inserted into tbl yet, and if not, makes its value the empty list (the forward slash tests for the null value, and so if key is already present in the table, and has been assigned a value, tbl[key] := [] will not take place). You can then go about inserting things into this list as expected.