Annotation of researchv10dc/cmd/icon/docs/tr83-3.roff, revision 1.1.1.1

1.1       root        1: .so tmac.tr
                      2: .nr X 1
                      3: .DA "May 13, 1983; last revised May 1, 1986"
                      4: .TR 83-3c
                      5: .Gr
                      6: .GE
                      7: .TL
                      8: An Overview of the Icon Programming Language
                      9: .AU
                     10: Ralph E. Griswold
                     11: .AE
                     12: .tr *\(**
                     13: .NH
                     14: Introduction
                     15: .PP
                     16: Icon is a high-level programming language with extensive facilities for
                     17: processing strings and lists. Icon has several novel features, including
                     18: expressions that may produce sequences of results, goal-directed
                     19: evaluation that automatically searches for a successful result, and
                     20: string scanning that allows operations on strings to be formulated at
                     21: a high conceptual level.
                     22: .PP
                     23: Icon resembles SNOBOL4 [1] in its emphasis on high-level string
                     24: processing and a design philosophy that allows ease of programming
                     25: and short, concise programs. Like SNOBOL4, storage allocation and
                     26: garbage collection are automatic in Icon, and there are few restrictions on the
                     27: sizes of objects. Strings, lists, and other structures are created
                     28: during program execution and their size does not need to be known when
                     29: a program is written.
                     30: Values are converted to expected types automatically; for example,
                     31: numeral strings read in as input can be used in numerical computations
                     32: without explicit conversion.
                     33: Whereas SNOBOL4 has a pattern-matching facility that is separate from
                     34: the rest of the language, string scanning is integrated with the
                     35: rest of the language facilities in Icon.
                     36: Unlike SNOBOL4,
                     37: Icon has an expression-based syntax with reserved words;
                     38: in appearance, Icon programs resemble those of several other conventional programming
                     39: languages.
                     40: .PP
                     41: Examples of the kinds of problems for which Icon is well suited are:
                     42: .in .5i
                     43: .IP \(bu
                     44: text analysis, editing, and formatting
                     45: .IP \(bu
                     46: document preparation
                     47: .IP \(bu
                     48: symbolic mathematics
                     49: .IP \(bu
                     50: text generation
                     51: .IP \(bu
                     52: parsing and translation
                     53: .IP \(bu
                     54: data laundry
                     55: .IP \(bu
                     56: graph manipulation
                     57: .in 0
                     58: .PP
                     59: Version 6 of Icon, the most recent version, is implemented in C [2]. There are \*U implementations
                     60: .Un
                     61: for the Amdahl 580, the AT&T 3B series, the HP 9000, the IBM PC/XT/AT, the PDP-11, the Ridge 32,
                     62: the Sun Workstation, and the VAX-11.
                     63: There also is a VMS implementation for the VAX-11 and a DOS
                     64: implementation for personal computers. Other implementations are in
                     65: progress.
                     66: .PP
                     67: A brief description of some of the representative features of Icon
                     68: is given in the following sections. This description is not rigorous
                     69: and does not include many features of Icon. See [3] for a
                     70: complete description and [4] for a description of recent changes
                     71: to the language.
                     72: .NH
                     73: Strings
                     74: .PP
                     75: Strings of characters may be arbitrarily long, limited only by the
                     76: architecture of the computer on which Icon is implemented. A string
                     77: may be specified literally by enclosing it in double quotation marks,
                     78: as in
                     79: .Ds
                     80: greeting := "Hello world"
                     81: .De
                     82: which assigns an 11-character string to \*Mgreeting\fR, and
                     83: .Ds
                     84: address := ""
                     85: .De
                     86: which assigns the zero-length \fIempty\fR string to \*Maddress\fR.
                     87: The number of characters in a string \*Ms\fR, its size, is given
                     88: by \*M*s\fR. For example, \*M*greeting\fR is 11 and \*M*address\fR
                     89: is 0.
                     90: .PP
                     91: Icon uses the ASCII character set, extended to 256 characters.
                     92: There are escape conventions, similar to those of C, for representing
                     93: characters that cannot be keyboarded.
                     94: .PP
                     95: Strings also can be read in and written out, as in
                     96: .Ds
                     97: line := read()
                     98: .De
                     99: and
                    100: .Ds
                    101: write(line)
                    102: .De
                    103: Strings can be constructed by concatenation, as in
                    104: .Ds
                    105: element := "(" || read() || ")"
                    106: .De
                    107: If the concatenation of a number of strings is to be written
                    108: out, the \*Mwrite\fR function can be used with several arguments
                    109: to avoid actual concatenation:
                    110: .Ds
                    111: write("(",read(),")")
                    112: .De
                    113: .PP
                    114: Substrings can be formed by subscripting strings with range
                    115: specifications that indicate, by position, the desired range of
                    116: characters. For example,
                    117: .Ds
                    118: middle := line\^[10:20]
                    119: .De
                    120: assigns to \*Mmiddle\fR the string of characters of \*Mline\fR between
                    121: positions 10 and 20.
                    122: Similarly,
                    123: .Ds
                    124: write(line\^[2])\fR
                    125: .De
                    126: writes the second character of \*Mline\fR.
                    127: The value 0 is used to refer to the position after the last character
                    128: of a string. Thus
                    129: .Ds
                    130: write(line\^[2:0])
                    131: .De
                    132: writes the substring of \*Mline\fR from the second character to the end, thus
                    133: omitting the first character.
                    134: .PP
                    135: An assignment can be made to the substring of string-valued variable
                    136: to change its value. For example,
                    137: .Ds
                    138: line[2] := "..."
                    139: .De
                    140: replaces the second character of \*Mline\fR by three dots. Note that
                    141: the size of \*Mline\fR changes automatically.
                    142: .PP
                    143: There are many functions for analyzing strings. An example is
                    144: .Ds
                    145: find(s1,\*bs2)
                    146: .De
                    147: which produces the position in \*Ms2\fR at which \*Ms1\fR occurs as
                    148: a substring. For example, if the value of \*Mgreeting\fR is as
                    149: given earlier,
                    150: .Ds
                    151: find("or",\*bgreeting)
                    152: .De
                    153: produces the value 8.
                    154: See Section 4.2 for the handling of situations in which \*Ms1\fR does not
                    155: occur in \*Ms2\fR, or in which it occurs at several different positions.
                    156: .NH
                    157: Character Sets
                    158: .PP
                    159: While strings are sequences of characters, \fIcsets\fR are sets of characters
                    160: in which membership rather than order is significant. Csets are
                    161: represented literally using single enclosing quotation marks, as
                    162: in
                    163: .Ds
                    164: vowels := 'aeiouAEIOU'
                    165: .De
                    166: Two useful built-in csets are \*M&lcase\fR and \*M&ucase\fR, which
                    167: consist of the lowercase and uppercase letters, respectively.
                    168: Set operations are provided for csets. For example,
                    169: .Ds
                    170: letters := &lcase ++ &ucase
                    171: .De
                    172: forms the cset union of the lowercase and uppercase letters and assigns the
                    173: resulting cset to \*Mletters\fR, while
                    174: .Ds
                    175: consonants := letters -- 'aeiouAEIOU'
                    176: .De
                    177: forms the cset difference of the letters and the vowels and assigns the
                    178: resulting cset to \*Mconsonants\fR.
                    179: .PP
                    180: Csets are useful in situations in which any one of a number of characters
                    181: is significant. An example is the string analysis function
                    182: .Ds
                    183: upto(c,\*bs)
                    184: .De
                    185: which produces the position \*Ms\fR at which any character in \*Mc\fR occurs.
                    186: For example,
                    187: .Ds
                    188: upto(vowels,\*bgreeting)
                    189: .De
                    190: produces 2. Another string analysis function that uses csets is
                    191: .Ds
                    192: many(c,\*bs)
                    193: .De
                    194: which produces the position in \*Ms\fR after an initial substring consisting
                    195: only of characters that occur in \*Ms\fR.
                    196: An example of the use of \*Mmany\fR is in locating words. Suppose, for
                    197: example, that a word is defined to consist of a string of letters.
                    198: The expression
                    199: .Ds
                    200: write(line\^[1:many(letters,\*bline)])
                    201: .De
                    202: writes a word at the beginning of \*Mline\fR. Note the use of the
                    203: position returned by a string analysis function to specify the
                    204: end of a
                    205: substring.
                    206: .NH
                    207: Expression Evaluation
                    208: .NH 2
                    209: Conditional Expressions
                    210: .PP
                    211: In Icon there are \fIconditional expressions\fR that may \fIsucceed\fR and
                    212: produce a result, or may \fIfail\fR and not produce any result. An example
                    213: is the comparison operation
                    214: .Ds
                    215: i > j
                    216: .De
                    217: which succeeds (and produces the value of \*Mj\fR) provided that the value
                    218: of \*Mi\fR is greater than the value of \*Mj\fR, but fails otherwise.
                    219: .PP
                    220: The success or failure of conditional operations is used instead of
                    221: Boolean values to drive control structures in Icon. An example is
                    222: .Ds
                    223: if i > j then k := i else k := j
                    224: .De
                    225: which assigns the value of \*Mi\fR to \*Mk\fR if the value of \*Mi\fR
                    226: is greater than the value of \*Mj\fR, but assigns the value of \*Mj\fR to
                    227: \*Mk\fR \%otherwise.
                    228: .PP
                    229: The usefulness of the concepts of success and failure is illustrated by
                    230: \*Mfind(s1,\*bs2)\fR, which fails
                    231: if \*Ms1\fR does not occur as a substring of \*Ms2\fR.
                    232: Thus
                    233: .Ds
                    234: if i := find("or",line) then write(i)
                    235: .De
                    236: writes the position at which \*Mor\fR occurs in \*Mline\fR, if it occurs,
                    237: but does not write a value if it does not occur.
                    238: .PP
                    239: Many expressions in Icon are conditional. An example is \*Mread()\fR,
                    240: which produces the next line from the input file, but fails when the
                    241: end of the file is reached. The following expression is typical of
                    242: programming in Icon and illustrates the integration of conditional
                    243: expressions and conventional control structures:
                    244: .Ds
                    245: while line := read() do
                    246:    write(line)
                    247: .De
                    248: This expression copies the input file to the output file.
                    249: .PP
                    250: If an argument of a function fails, the function is not called,
                    251: and the function call fails as well. This ``inheritance'' of failure allows the
                    252: concise formulation of many programming tasks. Omitting the optional
                    253: \f3do\fR clause in \f3while-do\fR, the previous expression can be
                    254: rewritten as
                    255: .Ds
                    256: while write(read())
                    257: .De
                    258: .NH 2
                    259: Generators
                    260: .PP
                    261: In some situations, an expression may be capable of producing more than
                    262: one result. Consider
                    263: .Ds
                    264: sentence := "Store it in the neighboring harbor"
                    265: find("or",\*bsentence)
                    266: .De
                    267: Here \*Mor\fR occurs in \*Msentence\fR at positions 3, 23, and 33. Most
                    268: programming languages treat this situation by selecting one of the
                    269: positions, such as the first, as the result of the expression. In Icon,
                    270: such an expression is a \fIgenerator\fR and is capable of producing
                    271: all three positions.
                    272: .PP
                    273: The results that a generator produces depend on context. In a situation
                    274: where only one result is needed, the first is produced, as in
                    275: .Ds
                    276: i := find("or",\*bsentence)
                    277: .De
                    278: which assigns the value 3 to \*Mi\fR.
                    279: .PP
                    280: If the result produced by a generator does not lead to the success of
                    281: an enclosing expression, however, the generator is \fIresumed\fR
                    282: to produce another value. An example is
                    283: .Ds
                    284: if (i := find("or",\*bsentence)) > 5 then write(i)
                    285: .De
                    286: Here the first result produced by the generator, 3, is assigned to
                    287: \*Mi\fR, but this value is not greater than 5 and the comparison
                    288: operation fails. At this point, the generator is resumed and
                    289: produces the second position, 23, which is greater than 5. The
                    290: comparison operation then succeeds and the value 23 is written.
                    291: Because of the inheritance of failure and the fact that comparison
                    292: operations return the value of their right argument, this expression
                    293: can be written in the following more compact form:
                    294: .Ds
                    295: write(5 < find("or",\*bsentence))
                    296: .De
                    297: .PP
                    298: Goal-directed evaluation is inherent in the expression evaluation
                    299: mechanism of Icon and can be used in arbitrarily complicated situations.
                    300: For example,
                    301: .Ds
                    302: find("or",\*bsentence1) = find("and",\*bsentence2)
                    303: .De
                    304: succeeds if \*Mor\fR occurs in \*Msentence1\fR at the same position
                    305: as \*Mand\fR occurs in \*Msentence2\fR.
                    306: .PP
                    307: A generator can be resumed repeatedly to produce all its results by
                    308: using the \f3every-do\fR control structure. An example is
                    309: .Ds
                    310: every i := find("or",\*bsentence)
                    311:    do write(i)
                    312: .De
                    313: which writes all the positions at which \*Mor\fR occurs in \*Msentence\fR.
                    314: For the example above, these are 3, 23, and 33.
                    315: .PP
                    316: Generation is inherited like failure, and this expression can be written
                    317: more concisely by omitting the optional \f3do\fR clause:
                    318: .Ds
                    319: every write(find("or",\*bsentence))
                    320: .De
                    321: .PP
                    322: There are several built-in generators in Icon. One of the most frequently
                    323: used of these is
                    324: .Ds
                    325: i to j
                    326: .De
                    327: which generates the integers from \*Mi\fR to \*Mj\fR. This generator can be
                    328: combined with \f3every-do\fR to formulate the traditional \f3for\fR-style
                    329: control structure:
                    330: .Ds
                    331: every k := i to j do
                    332:    f(k)
                    333: .De
                    334: Note that this expression can be written more compactly as
                    335: .Ds
                    336: every f(i to j)
                    337: .De
                    338: .PP
                    339: There are a number of other control structures related to generation.
                    340: One is \fIalternation\fR,
                    341: .Ds
                    342: \*1 | \*2
                    343: .De
                    344: which generates the results of \*1 followed by the results of \*2.
                    345: Thus
                    346: .Ds
                    347: every write(find("or",\*bsentence1) | find("or",\*bsentence2))
                    348: .De
                    349: writes the positions of \*Mor\fR in \*Msentence1\fR followed by
                    350: the positions of \*Mor\fR in \*Msentence2\fR. Again, this sentence can
                    351: be written more compactly by using alternation in the second
                    352: argument of \*Mfind\fR:
                    353: .Ds
                    354: every write(find("or",\*bsentence1 | sentence2))
                    355: .De
                    356: .PP
                    357: Another use of alternation is illustrated by
                    358: .Ds
                    359: (i | j | k) = (0 | 1)
                    360: .De
                    361: which succeeds if any of \*Mi\fR, \*Mj\fR, or \*Mk\fR has the value 0 or 1.
                    362: .NH
                    363: String Scanning
                    364: .PP
                    365: The string analysis and synthesis operations described in
                    366: Sections 2 and 3 work best for relatively simple operations on strings.
                    367: For complicated operations, the bookkeeping involved in keeping track of
                    368: positions in strings becomes burdensome and error prone.
                    369: In such cases, Icon has a string scanning facility that is
                    370: analogous in many respects to pattern matching in SNOBOL4. In string
                    371: scanning, positions are managed automatically and attention is
                    372: focused on a current position in a string as it is examined by a sequence of
                    373: operations.
                    374: .PP
                    375: The string scanning operation has the form
                    376: .Ds
                    377: s ? \*0
                    378: .De
                    379: where \*Ms\fR is the \fIsubject\fR string to be examined and \*0 is an expression that
                    380: performs the examination.
                    381: A position in the subject, which starts at 1, is the focus of examination.
                    382: .PP
                    383: \fIMatching functions\fR change this position.
                    384: One matching function, \*Mmove(i)\fR, moves the position by \*Mi\fR and
                    385: produces the substring of the subject between the previous and new
                    386: positions. If the position cannot be moved by the specified amount
                    387: (because the subject is not long enough), \*Mmove(i)\fR fails. A
                    388: simple example is
                    389: .Ds
                    390: line ? while write(move(2))
                    391: .De
                    392: which writes successive two-character substrings of \*Mline\fR, stopping
                    393: when there are no more characters.
                    394: .PP
                    395: Another matching function is \*Mtab(i)\fR, which sets the position in the
                    396: subject to \*Mi\fR and also returns the substring of the subject between
                    397: the previous and new positions.
                    398: For example,
                    399: .Ds
                    400: line ? if tab(10) then write(tab(0))
                    401: .De
                    402: first sets the position in the subject to 10 and then to the end of the subject, writing
                    403: \*Mline\^[10:0]\fR.
                    404: Note that no value is written if the subject is not long enough.
                    405: .PP
                    406: String analysis functions such as \*Mfind\fR
                    407: can be used in string scanning. In this context, the string that they
                    408: operate on is not specified and is taken to be the subject. For example,
                    409: .Ds
                    410: line ? while write(tab(find("or")))
                    411:    do move(2)
                    412: .De
                    413: writes all the substrings of \*Mline\fR prior to occurrences of \*Mor\fR.
                    414: Note that \*Mfind\fR produces a position, which is then used by \*Mtab\fR
                    415: to change the position and produce the desired substring. The \*Mmove(2)\fR
                    416: skips the \*Mor\fR that is found.
                    417: .PP
                    418: Another example of the use of string analysis functions in scanning is
                    419: .Ds
                    420: line ? while tab(upto(letters)) do
                    421:    write(tab(many(letters)))
                    422: .De
                    423: which writes all the words in \*Mline\fR.
                    424: .PP
                    425: As illustrated in the examples above, any expression may occur in
                    426: the scanning expression. Unlike SNOBOL4, in which the operations that
                    427: are allowed in pattern matching are limited and idiosyncratic, string
                    428: scanning is completely integrated with the rest of the operation
                    429: repertoire of Icon.
                    430: .NH
                    431: Structures
                    432: .PP
                    433: Icon supports several kinds of structures with different organizations
                    434: and access methods. Lists are linear structures that can be accessed
                    435: both by position and by stack and queue functions. Sets are collections
                    436: of arbitrary values with no implied ordering. Tables provide an
                    437: associative lookup mechanism.
                    438: .NH 2
                    439: Lists
                    440: .PP
                    441: While strings are sequences of characters, lists in Icon are sequences
                    442: of values of arbitrary types. Lists are created by enclosing the lists
                    443: of values in brackets. An example is
                    444: .Ds
                    445: car1 := ["buick",\*b"skylark",\*b1978,\*b2450]
                    446: .De
                    447: in which the list \*Mcar1\fR has four values, two of which are strings
                    448: and two of which are integers. Note that the values in a list need not
                    449: all be of the same type. In fact, any kind of value can occur in a list
                    450: \(em even another list, as in
                    451: .Ds
                    452: inventory := [car1,\*bcar2,\*bcar3,\*bcar4]
                    453: .De
                    454: .PP
                    455: Lists also can be created by
                    456: .Ds
                    457: a := list(i,\*bx)
                    458: .De
                    459: which creates a list of \*Mi\fR values, each of which has the value
                    460: \*Mx\fR.
                    461: .PP
                    462: The values in a list can be referenced by position much like the
                    463: characters in a string. Thus
                    464: .Ds
                    465: car1\^[4] := 2400
                    466: .De
                    467: changes the last value in \*Mcar1\fR to 2400.
                    468: A reference that is out of the range of the list fails. For example,
                    469: .Ds
                    470: write(car1\^[5])
                    471: .De
                    472: fails.
                    473: .PP
                    474: The values in a list \*Ma\fR are generated by \*M!a\fR. Thus
                    475: .Ds
                    476: every write(!a)
                    477: .De
                    478: writes all the values in \*Ma\fR.
                    479: .PP
                    480: Lists can be manipulated like stacks and queues. The function
                    481: \*Mpush(a,\*bx)\fR
                    482: adds the value of \*Mx\fR to the left end of the list \*Ma\fR,
                    483: automatically increasing the size of \*Ma\fR by one. Similarly,
                    484: \*Mpop(a)\fR removes the leftmost value from \*Ma\fR, automatically
                    485: decreasing the size of \*Ma\fR by one, and produces the removed value.
                    486: .PP
                    487: A list value in Icon is a pointer (reference) to a structure. Assignment
                    488: of a structure
                    489: in Icon does not copy the structure itself but only the pointer to it. Thus the
                    490: result of
                    491: .Ds
                    492: demo := car1
                    493: .De
                    494: causes \*Mdemo\fR and \*Mcar1\fR to reference the same list. Graphs with
                    495: loops can be constructed in this way. For example,
                    496: .Ds
                    497: node1 := ["a"]
                    498: node2 := [node1,\*b"b"]
                    499: push(node1,\*bnode2)
                    500: .De
                    501: constructs a structure that can be pictured as follows:
                    502: .if \nX .ig
                    503: .Ds
                    504: .ta 1.2i
                    505: .sp 2
                    506: node1  a
                    507: .sp 2
                    508: node2  b
                    509: .sp 2
                    510: .De
                    511: ..
                    512: .if !\nX .ig
                    513: .ne 2i
                    514: .nf
                    515: .in 1i
                    516: .ft H
                    517: .sp 2
                    518: .cs H 20
                    519: node1  .->a--.
                    520:        |     |
                    521:        |     |
                    522: node2  '--b<-'
                    523: .sp 2
                    524: .cs H
                    525: .in 0
                    526: .fi
                    527: ..
                    528: .NH 2
                    529: Sets
                    530: .PP
                    531: Sets are collections of values. A set is obtained from a list by
                    532: \*Mset(a)\fR, where \*Ma\fR contains the members of the set. For example,
                    533: .Ds
                    534: s := set(\^[1,\*b"abc",\*b[\^]\^])
                    535: .De
                    536: assigns to \*Ms\fR a set that contains the integer 1, the string \*M"abc"\fR,
                    537: and an empty list.
                    538: .PP
                    539: The set operations of union, intersection, and difference are provided.
                    540: The function \*Mmember(s,\*bx)\fR succeeds if \*Mx\fR is a member of the
                    541: set \*Ms\fR but fails otherwise. The function \*Minsert(s,\*bx)\fR
                    542: adds \*Mx\fR to the set \*Ms\fR,
                    543: while \*Mdelete(s,\*bx)\fR removes \*Mx\fR from \*Ms\fR. A value only can occur once in
                    544: a set, so \*Minsert(s,\*bx)\fR has no effect if \*Mx\fR is already in
                    545: \*Ms\fR.
                    546: .PP
                    547: The operation \*M*s\fR produces the number of members in \*Ms\fR and
                    548: \*M!s\fR generates the members of \*Ms\fR.
                    549: .PP
                    550: A simple example of the use of sets is given by the following
                    551: segment of code, which lists all the different words that
                    552: appear in the input file:
                    553: .Ds
                    554: words := set(\^[\^])
                    555: while line := read() do
                    556:    line ? while tab(upto(letters)) do
                    557:       insert(words,\*btab(many(letters)))
                    558: every write(!words)
                    559: .De
                    560: .NH 2
                    561: Tables
                    562: .PP
                    563: Icon has a table data type similar to that of SNOBOL4. Tables essentially
                    564: are sets of pairs of values, an \fIentry value\fR and a corresponding
                    565: \fIassigned value\fR. The entry and assigned values may be of any type,
                    566: and the assigned value for any entry value can be looked up automatically.
                    567: Thus tables provide a form of associative access in contrast with the
                    568: positional access to values in lists.
                    569: .PP
                    570: A table is created by an expression such as
                    571: .Ds
                    572: symbols := table(x)
                    573: .De
                    574: which assigns to \*Msymbols\fR a table with the default assigned value
                    575: \*Mx\fR.
                    576: Subsequently, \*Msymbols\fR can be referenced by any entry value, such as
                    577: .Ds
                    578: symbols\^["there"] := 1
                    579: .De
                    580: which assigns the value 1 to the \*Mthere\fRth entry in symbols.
                    581: .PP
                    582: Tables grow automatically as new entry values are added.
                    583: For example, the following program segment produces a
                    584: table containing a
                    585: count of the
                    586: words that appear in the input file:
                    587: .Ds
                    588: words := table(0)
                    589: while line := read() do
                    590:    line ? while tab(upto(letters)) do
                    591:       words\^[tab(many(letters))] +:= 1
                    592: .De
                    593: Here the default assigned value for each word is 0, as given
                    594: in \*Mtable(0)\fR, and \*M+:=\fR is an augmented assignment operation that
                    595: increments the assigned values by one.
                    596: There are augmented assignment operations for all binary operators.
                    597: .PP
                    598: A list can be obtained from a table by the function \*Msort(t,\*b1)\fR.
                    599: The form of the list depends on the value of \*Mi\fR. For example, if
                    600: \*Mi\fR is 3, the list contains alternate
                    601: entry and assigned values of \*Mt\fR.
                    602: For example,
                    603: .Ds
                    604: wordlist := sort(words,\*b3)
                    605: while write(pop(wordlist)," : ",pop(wordlist))
                    606: .De
                    607: writes the words and their counts from \*Mwords\fR.
                    608: .NH
                    609: Procedures
                    610: .PP
                    611: An Icon program consists of a sequence of procedure declarations.
                    612: An example of a procedure declaration is
                    613: .Ds
                    614: procedure max(i,\*bj)
                    615:    if i > j then return i else return j
                    616: end
                    617: .De
                    618: where the name of the procedure is \*Mmax\fR and its formal parameters
                    619: are \*Mi\fR and \*Mj\fR. The \f3return\fR expressions return the value of
                    620: \*Mi\fR or \*Mj\fR, whichever is larger.
                    621: .PP
                    622: Procedures are called like built-in functions. Thus
                    623: .Ds
                    624: k := max(*s1,\*b*s2)
                    625: .De
                    626: assigns to \*Mk\fR the size of the longer of the strings \*Ms1\fR and
                    627: \*Ms2\fR.
                    628: .PP
                    629: A procedure also may suspend instead of returning. In this case, a
                    630: result is produced as in the case of a return, but the procedure
                    631: can be resumed to produce other results. An example is
                    632: the following procedure that generates the words in the input file.
                    633: .Ds
                    634: procedure genword()
                    635:    local line, letters, words
                    636:    letters := &lcase ++ &ucase
                    637:    while line := read() do
                    638:       line ? while tab(upto(letters)) do {
                    639:          word := tab(many(letters))
                    640:          suspend word
                    641:          }
                    642: end
                    643: .De
                    644: The braces enclose a compound expression.
                    645: .PP
                    646: Such a generator is used in the same way that a built-in generator is
                    647: used. For example
                    648: .Ds
                    649: every word := genword() do
                    650:    if find("or",\*bword) then write(word)
                    651: .De
                    652: writes only those words that contain the substring \*Mor\fR.
                    653: .NH
                    654: An Example
                    655: .PP
                    656: The following program sorts graphs topologically.
                    657: .Ds
                    658: .ta 3.5i
                    659: .Px
                    660: procedure main()
                    661:    local sorted, nodes, arcs, roots
                    662:    while nodes := read() do {  # get next node list
                    663:       arcs := read()   # get arc list
                    664:       sorted := ""     # sorted nodes
                    665:        # get nodes without predecessors
                    666:       while *(roots := nodes -- snodes(arcs)) > 0 do {
                    667:          sorted ||:= roots     # add to sorted nodes
                    668:          nodes --:= roots      # delete these nodes
                    669:          arcs := delarcs(arcs,\*broots)        # delete their arcs
                    670:          }
                    671:       if *arcs = 0 then write(sorted)  # successfully sorted
                    672:       else write("graph has cycle")    # cycle if node remains
                    673:    }
                    674: end
                    675: .De
                    676: .Ds
                    677: .Px
                    678: procedure snodes(arcs)
                    679:    local nodes
                    680:    nodes := ""
                    681:    arcs ? while move(1) do {   # predecessor
                    682:       move(2)  # skip "->"
                    683:       nodes ||:= move(1)       # successor
                    684:       move(1)  # skip ";"
                    685:       }
                    686:    return nodes
                    687: end
                    688: .De
                    689: .Ds
                    690: .Px
                    691: procedure delarcs(arcs,\*broots)
                    692:    local newarcs, node
                    693:    newarcs := ""
                    694:    arcs ? while node := move(1) do {   # get predecessor node
                    695:       if many(roots,\*bnode) then move(4)      # delete arc from root node
                    696:       else newarcs ||:= node || move(4)        # else keep arc
                    697:       }
                    698:    return newarcs
                    699: end
                    700: .De
                    701: Graph nodes are represented
                    702: by single characters with a list of the nodes on one input line followed by
                    703: a list of arcs. For example, the graph
                    704: .if \nX .ig
                    705: .Ds
                    706: .ta .75i +.75i +.75i
                    707: \0
                    708: \0
                    709: \0
                    710:        a       b       c
                    711: .sp 2
                    712:        d       e
                    713: .sp 2
                    714: .De
                    715: ..
                    716: .if !\nX .ig
                    717: .nf
                    718: .ft H
                    719: .cs H 20
                    720: .in 1i
                    721: .ne 2i
                    722: .sp 2
                    723:         .---------------.
                    724:         |               |
                    725:         |               \o'v|'
                    726:         a------>b------>c
                    727:         \o'^|'       |       \o'^|'
                    728:         |       |       |
                    729:         |       \o'|v'       |
                    730:         d------>e-------'
                    731: .sp 1
                    732: .cs H
                    733: .fi
                    734: .in 0
                    735: .sp 1
                    736: .ft R
                    737: ..
                    738: is given as
                    739: .Ds
                    740: abcde
                    741: a\*(->b;a\*(->c;b\*(->c;b\*(->e;d\*(->a;d\*(->e;e\*(->c;
                    742: .De
                    743: for which the output is
                    744: .Ds
                    745: dabec
                    746: .De
                    747: .PP
                    748: The nodes are represented by csets and automatic type conversion
                    749: is used to convert strings to csets and vice versa.
                    750: Note the use of augmented assignment operations for concatenation and in the computation of
                    751: cset differences.
                    752: .SH
                    753: Acknowledgement
                    754: .PP
                    755: Icon was designed by the the author in collaboration with Dave Hanson,
                    756: Tim Korb, Cary Coutant, and Steve Wampler. The current implementation is
                    757: largely the work of Cary Coutant and Steve Wampler with recent
                    758: contributions by Bill Mitchell and Janalee O'Bagy.
                    759: Dave Hanson and Bill Mitchell made several helpful suggestions on the presentation
                    760: of material in this paper.
                    761: .SH
                    762: References
                    763: .LP
                    764: .IP 1.
                    765: Griswold, Ralph E., Poage, James F., and Polonsky, Ivan P.
                    766: \fIThe SNOBOL4 Programming Language\fR, second edition.
                    767: Prentice-Hall, Inc., Englewood Cliffs, New Jersey. 1971.
                    768: .IP 2.
                    769: Kernighan, Brian W. and Ritchie, Dennis M. \fIThe C
                    770: Programming Language\fR. Prentice-Hall, Inc.,
                    771: Englewood Cliffs, New Jersey. 1978.
                    772: .IP 3.
                    773: Griswold, Ralph E. and Griswold, Madge T. \fIThe Icon Programming
                    774: Language\fR. Prentice-Hall, Inc., Englewood Cliffs, New Jersey.
                    775: 1983.
                    776: .IP 4.
                    777: Griswold, Ralph E., and Mitchell, William H., and O'Bagy, Janalee.
                    778: \fIVersion 6.0 of
                    779: Icon\fR, Technical Report TR 86-10, Department of Computer Science,
                    780: The University of Arizona. 1986.

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.