[ Jocelyn Ireson-Paine's Home Page | Publications | Dobbs Code Talk Index | Dobbs Blog Version ]

Associative Programming and Snobol's Unusual Indirect-Referencing Operator

In most languages, to "dereference" a pointer is to treat its value as a machine address and look up the data therein. Snobol is different. Strings are one analogue of pointers. And one can go, at run-time, from a string to the variable with the same name. Or even to a label with the same name: a string computed goto.

Snobol does this with the indirect-referencing operator, unary dollar. So suppose the value of variable "dog" is the string "bark". And suppose the value of variable "animal" is the string "dog". Then the value of "$animal" is "bark".

I'll demonstrate with this program:

  dog = "bark"
  cat = "meow"

  animal = "dog"
  output = $animal

  animal = "cat"
  output = $animal

end

Here is its output:

C:\dobbs>\snobol4\SNOBOL4.EXE bark.sno

SNOBOL4+ Version 2.24. 8087 present.
(c) Copyright 1984,1998 Catspaw, Inc., Salida, Colo. All Rights Reserved.

No errors

bark
meow

I took this example from the section 5.1 INDIRECT REFERENCE in Chapter 5 of Mark Emmer's A Snobol4 Tutorial. Here's another program, inspired by his tutorial. It assigns animal and property-name variables, and uses indirect referencing to build a tiny database mapping animal and property names to the property values:

  dog_sound = "bark"
  cat_sound = "meow"

  dog_character = "cupboard-loving"
  cat_character = "independent"

  dog_food = "Pal"
  cat_food = "Kit-e-Kat"

  animal = "dog"
  property = "sound"
  output = "A " animal "'s " property " is: " $(animal "_" property)

  animal = "dog"
  property = "food"
  output = "A " animal "'s " property " is: " $(animal "_" property)

  animal = "cat"
  property = "sound"
  output = "A " animal "'s " property " is: " $(animal "_" property)

  animal = "cat"
  property = "character"
  output = "A " animal "'s " property " is: " $(animal "_" property)

end

This is its output:

C:\dobbs>\snobol4\SNOBOL4.EXE bark2.sno

SNOBOL4+ Version 2.24. 8087 present.
(c) Copyright 1984,1998 Catspaw, Inc., Salida, Colo. All Rights Reserved.

No errors
A dog's sound is: bark
A dog's food is: Pal
A cat's sound is: meow
A cat's character is: independent

I suspect that Snobol's inventors introduced indirect referencing to make it easy for programmers to build data bases. Lisp provided property lists — see The Property List in Guy Steele's Common Lisp the Language, 2nd Edition — for the same purpose. Bertram Raphael used them, for example, in his famous 1960s question-answering program SIR. He describes this in SIR: A Computer Program for Semantic Information Retrieval; his Figure 1 shows a conversation with SIR, where he tells it facts and then asks questions about them.

So I'd not be surprised if the Snobol team had decided to provide Snobol with features that would make such work easier. But indirect referencing is also good because it enables Snobol programmers to pass variable names to functions, as we do pointers in other languages. In my next essay, about the "bal" pattern and the use of failure to provoke backtracking, I'll show an example in which I pass the name of a bound variable to a function that iterates an expression over a list of strings. Snobol does have a special data type to hold such names; indeed, this data type is called "name". One constructs it using the unary dot operator, described in 5.6 THE NAME OPERATOR of Emmer's Snobol4 tutorial. But this is very closely related to dereferencing strings, and probably couldn't work without it.

Incidentally, Snobol also has an associative-array data type, the table. Syntactically, this looks like an array, except that one can use pointed brackets to enclose subscripts. Semantically, subscripts can be strings and indeed — according to Emmer's 5.5 TABLES — any data type.

I'll demonstrate with the program below. It generates the same output as the previous program, but uses a table whose subscripts are animal-property pairs:

  data = table( 10 )

  data< "dog_sound" > = "bark"
  data< "cat_sound" > = "meow"

  data< "dog_character" > = "cupboard-loving"
  data< "cat_character" > = "independent"

  data< "dog_food" > = "Pal"
  data< "dog_food" > = "Kit-e-Kat"

  animal = "dog"
  property = "sound"
  output = "A " animal "'s " property " is: " data<animal "_" property>

  animal = "dog"
  property = "food"
  output = "A " animal "'s " property " is: " data<animal "_" property>

  animal = "cat"
  property = "sound"
  output = "A " animal "'s " property " is: " data<animal "_" property>

  animal = "cat"
  property = "character"
  output = "A " animal "'s " property " is: " data<animal "_" property>

end
For the 1960s, this was remarkably advanced! And, forty-odd years later, it is still more succinct than doing the same in C, C++, or Java...

Variables aren't the only thing that can be accessed by indirect referencing. Labels can too, as I show in the following program. Each label heads a statement that outputs the value of a particular animal-property pair. The statement just before the "end" label is a jump that constructs a string and then jumps to the resulting label:

dog_sound
  output = "bark" :(end)

cat_sound
  output = "meow" :(end)

dog_food
  output = "Pal"
  
cat_food
  output = "Kit-e-Kat"

  animal = "dog"
  property = "sound"
  :( $( animal "_" property ) )

end
This program outputs "bark".

So, as Emmer shows too in the end of his section on 5.1 INDIRECT REFERENCE, Snobol had a kind of string computed goto. But he remarks that:

Indirect referencing may not be used in a statement's label field. Dynamically changing the name of a statement during execution is excessive even by SNOBOL4 standards.