Annotation of researchv10dc/cmd/icon/docs/tr83-3.roff, revision 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.