Alvin Lo
Professor Ronald Danielson
Coen 171 Principle of Programming Language
Web Project
The content of these web pages is not generated by and does not represent the views of Santa Clara University or any of its departments or organizations.
Much of the material below comes from The Icon Programming Language and History of the Icon Programming Lagrange. (Bibliography)
An Introduction to The Icon Programming Language
Table of Contents
1. Background
4. Operations
6. Data Types
c. File
d. Procedure
f. Null
g. String
h. List
i. Set
j. Table
k. Record
7. Problems
a. Generator
b. Goal-directed Expression Evaluation Mechanism
a. Hello World
10. Online Resources
11. Bibliography
Icon is an imperative, procedural language. The significance of icon is their extensive features in string-manipulations and sophisticated data structures. Icon is not compatible with any existed language for one main reason. The innovation of Icon is academic research, and its goal is to “develop fundamentally new linguistic mechanisms instead of refining and improving the existing ones (Griswold 8). The language designers believed that if they pay too much attention on compatibility, their creativity on the design and implementation of the language would be limited.
Icon was original designs and implementation at The University of Arizona, and was funded primarily by National Science Foundation. The two main developers of Icon are Ralph E. Griswold and David R. Hanson. Griswold had extensive experiences with SNOBOL, and he has brought many ideas from it. In fact, one of the motives behind the development of Icon is to recast some features of SNOBOL4 in more general ways and to provide facilities that SNOBOL4 lacks. SNOBOL5 is another major languages that shaped the design of Icon. The SNOBOL language is designed for non-numerical, and it was widely used in Humanities. Naturally, Icon was often used for the same purpose (Griswold 8).
Icon was first incepted in 1977. From then on, 9 versions of Icon have been released. Some people may misunderstand that Icon is a programming language for making the small icon images in the operating systems, but they are not related in any sense. The name “Icon” does not stand for anything in particular, but the word “iconoclastic” was mention when the name was chosen (Griswold 3). In fact, Icon the programming language was invented first before Xerox used the word “icon” to refer the images
Fortran with the Ratfor preprocessor was first used to implement Icon, but as it turns out, it “required a robust Fortran compiler and considerable computational resource” (Griswold 9). Later, C is used to implement Icon, and the idea is that “an Icon program was translated into virtual machine instructions, which then were interpreted interfacing a run-time system written in C. For this aspect, Icon is somewhat similar to Java; they are hybrid implementation system.
Icon is not a strongly typed language because it provides implicit type conversion. In addition, it also has a limited type-checking in the compile-time. Identifier is not type specific; the type is checked in runtime. Storage management is done automatically; there are no explicit allocation and deallocation. Objects are created during execution, and space is reclaimed by garbage collection when is needed.
Not until Version 3 of Icon separate compilations of program modules and program libraries was supported. As a result, Icon was possible for larger projects
The most significant objective of Icon is the innovation the concept of generators, expressions that can produce a sequence of result by suspension and resumption. In addition, Icon takes a significantly different approach to high-level string analysis in a facility called string scanning.
Many features of Icon have been used or adopted into other language designs. Among these features, the concept of generators is the most influential; languages such as C, Little Smalltalk, Pascal, Leda, and SPLASH have adopted this approach. Icon’s control structures also have influenced languages such as Leichter, Magma, and Grandi. Icon’s string operation and its view have influenced other languages in string handling.
Recent
News about Icon:
Icon version 9 runs on many operation systems, such as UNIX, MS-DOS, and Windows. Icon programs are highly portable, except programs that use graphic facilities. Not all systems support these graphic facilities, and they are vary among the systems for which they are implemented.
Jcon is a new Java-based implementation of the icon programming language. For more information, please visit: http://www.cs.arizona.edu/icon/jcon/
Basics:
The name of a file that contains an Icon source program must end with the suffix .icn.
The Icon compiler is name icont. To compile helloWorld.icn, we just need to type
icont helloWorld.icn
The suffix, icn is assumed if none is given, so we can also type
icont hello
The result is an icode file that can be executed. The name of the icode file depends on the system on which Icon is run.
Each Icon program is composed of one or more procedures. A very simple Icon program, for example,
procedure main()
line
:= “Hello world”
write(line) # comments
end
Icons supports compound expression, which is enclosed by these two characters: { and }. For example,
while line := read() do{
count
:= count+1
if
find(s, line) then write(line)
}
{count :=count+1; if
find(s, line) then write(line)}
Assignment operation is, :=. For example,
line :=
“Hello world”
assigns the value “Hello World” to the identifier line, which is a variable.
Comparison operation is, =. It produces the value of its right argument if succeeds. For example,
write(i=j)
if j and i is equal then j is written out.
Exchanging Value operation is :=:. For example
a := 2
b :=3
a :=: b
after evaluations, the value of a is 3 and the value of b is 2.
There is many augmented assignments, and one of them is incrementing the numerical value of a variable,
a +:=1
Every time this expression is evaluated, a is incremented by 1.
Iteration control structure:
every expr1 do expr2
In this structure expr1 is first evaluated and then repeatedly resumed to produce all its values, and for each of these values, expr2 is evaluated. For example,
every i := find(s1, s2) do
write(i)
writes all the values produced by find(s1, s2).
Alternation control structure:
expr1 |
expr2
The values for expr1 are first produce and then the values for expr2. This structure is similar to the “or” in other programming languages. For example,
if i =
(0|1) then write(“example”)
example is written if the value of i is either 0 or 1.
Conjunction control structure:
expr1 & expr2
which succeeds only if both expr1 and expr2 succeed. This structure is similar to the “and” in other programming languages. For example,
if
find(s1, s2) & find(s1, s3) then write (“succeed”)
writes succeed only if s1 is a sub string of both s2 and s3.
Icon provides two structures that evaluate an expression repeated, depending on the success or failure of a control expression. The first one:
while expr1
do expr2
expr2 is executed only expr1 is succeed. The difference of this structure and the iteration control structure is that iteration control structure does not involve the concept of succeed and failure. The second structure:
until expr1
do expr2
which repeatedly evaluates expr2 unit expr1 succeeds.
A related control structure is
not expr
which fails if expr succeeds, but succeeds if expr fails. As a result,
until expr1
do expr2
is equivalent to
while not expr1
do expr2
The break expression is similar to other languages’ “break” statement; the next expression is similar to the “continue” statement. The break expression terminates the loop that it is in. The next expression skips the control expression, and continues the execution.
There is another looping structure that evaluate repeatedly, regardless of whether it succeeds or fail. The structure,
repeat expr
which is often used with the break expression and if-then-else expression. For example,
repeat{
counter :=
counter+1
if
counter>5 then break
}
The loop structure terminate when counter is bigger than 5.
There are two selection expressions. The first and the most common one is if-then-else expression,
if expr1 then expr2
else expr3
which evaluates expr2 if expr1 succeeds but evaluates expr3 if expr1 fails. The other is case control structure, which provides selection that is based on a control expression. It has the form:
case expr
of {
expr1
: expr2
:
}
The value from expr is compare with expr1, and if the values are the same, the corresponding expr2 is evaluated. If they are not the same, the next case is tried.
There is also an option default case,
If there is no succeed for matching expr and expr1, default case is evaluated.
11
built-in data types:
create
expr
but this expression does not evaluate the expr.
procedure
writepos(s1, s2(
locs
1:= create find (s1)
locs2
:= create find (s2)
end
Here the values assigned to locs1 and locs2 are co-expression corresponding to the expressions find(s1) and find(s2).
vowel := ‘aeiouAEIOU’
Every
write(text? upto(vowel))
writes the positons of every vowel in text, and
text ? {
if
tab(upto(vowel)+1) then
write(tab(0))
}
writes the portion of text after the first instance of a vowel (The Icon Programming Language 35).
c1 ++ c2 |
Union |
c1 ** c2 |
Intersection |
c1 – c2 |
Difference |
-c |
Complement |
procedure name {expr1, expr2…)
local-declarations
initital-clause
procedure-body
end
Function
Syntax |
Description
|
Example |
?i
|
Produce
a random number from the range 1 to i |
#This
expression produce “Head” or “Tail” with equal probability If
?2=1 then “Head” else “Tail” |
iand(a,b) bitwise and of a & b ior(a,b) bitwise inclusive or ixor(a,b) bitwise exclusive or icom(a) bitwise complement ishift(a,b) |
These
are bit operation that produce integers. The
function ishift(a,b) shifts a by b positions; if b is position, the shift is left;
b is negative, the shift is right. |
iand(4,5)
produces 4 ishift(2,3)
produces 16 ishift(2,
-3) produces 0 |
Function
Syntax |
Description
|
Example |
/x |
This
operation succeeds and produces the null value if x produces the null value,
and fail if it produce any other value |
|
\x |
It
succeeds and produces the value of x if that value is any value except the
null value |
|
.
Function
Syntax |
Description
|
Example |
char(i) |
Convert
an integer into one-character string using the ASCII code |
char(65)
produces “A” |
ord(s) |
Convert
a character into the integer representation of ASCII |
ord(“A”)
produces 65 |
*s |
Return
the length of the string |
*”Icon”
produces 4 |
s1
|| s2 |
Concatenate
the two string |
“I
“ || “like “ || “Icon” produces “I like Icon” |
s[i:j] |
Produce
a subString from s bounded by i and j |
“Computer”[3:6]
produces “mpu” |
?s |
Produce
a randomly selected character from s |
?”ABC”
produces “A” or “B” or “C” |
!s |
Generate
a series of one-character string from s |
!”abc”
produces “a”, and then “b”, and then “c”.
This function is a generator. |
s1
<< s2 less than s1
<<= s2 less than or equal s1
>> s2 greater than s1
>>= s2 greater than or equal s1
== s2 equal s1
~== s2 not equal |
Do
lexical comparison: s1 and s2 are converted into integers, and these two
integers are compared |
#
This program finds the biggest and smallest strings in term of their integers
values procedure
main() min := max := read() while line := read() do (max<<:=line) | (min
>>:=line) write(“largest string is::”, max) write(“smallest string is:”, min) end |
right
(s1, i, s2) left
(s1, i, s2) |
For
the right-function: Produce a string with length of i characters, in which s1
is positioned at the right and s2 is used to pad out the remaining characters
to the left. The
left function is just the converse. |
right(“Money”,
12, “$”) produces “$$$$$$Money” left(“Cut_Out_A_Word,
7) produces “Cut_Out” |
reverse(s) |
Produce
a string in reversed order |
Reverse(“computer”)
produces “retupmoc” |
repl(s,i) |
Produce
a string by concatenated s, i times. |
repl(“abc”,3)
produces “abcabcabc” |
map(s1,
s2, s3) |
Produce
a “string resulting from a character mapping of s1 in which each character of
s1 that appears in s2 is replaced by the corresponding character s3 |
map(“Programming
is fun”, “g”, “RE”) produces “ProREramminRE is fun” |
Aggregate Types:
Icon’s provides four aggregate types—set, lists, tables, and records; they can hold values of any type. While numerics, characters sets, and strings are atomic values, meaning that operations on them produce new values, the aggregate types use pointer semantics, meaning that operations on them may change the existing value. The size of strings and aggregates are not fixed; their sizes can change during execution.
These are some of the functions provided by Icon for List manipulation (The Icon Programming Language 66-70)
Function
Syntax |
Description
|
Example |
list(i,
x) |
Create
list a list with i element with value of x |
list(4,1)
produces [1,1,1,1] |
l[i] |
Refer
the ith element in the list l. It is like
array for other programming language. |
name
:= [“a”, “b”, “c”] name[2]
:= “x” change name to: [“a”,”x”,”c”] |
!l |
Produce
a series of element from l. |
!name
produces “a”, and then “b” and then “c” This
function is a generator. |
l1
||| l2 |
Concatenated
l1 and l2. |
name
||| [“f”] produces [“a”, “b”, “c”, “f”] |
l[a,b] |
Create
a sub-list from l with bound a and b |
name
[2,4] produce a list [“b”,.”c”] |
put(L,x) adds x to the right end of L get(L) removes a value from the left end of L push(L,x) adds x to the left end of L pop(L) removes a value from the left end of L |
These
functions are very useful for implementing queue and stack |
put(name,”gg”)
produces [“a”,
“b”, “c”, ”gg”] |
Function
Syntax |
Description
|
Example |
member(S,x) |
The
function succeeds and produces x if x is a member of the S, but fail
otherwise. |
|
insert(S,x) |
Insert
x into Set S and return S |
|
delete(S,x) |
Deletes
the member x from the Set S and return S |
|
S1++S2 union S1**S2 intersection S1-
- S2 difference |
After
each of these operations, a new set is created. |
|
text :=
table(0)
text[“key”]
= element
then every time we called text[“key”], element is return.
Function
Syntax |
Description
|
Example |
?T |
Produces
a randomly selected reference to the table T If
T is empty is empty, ?T fails. |
|
!T |
Generates
the values of elements in T |
|
key(T) |
Generates
the keys in T |
#This
expression prints the key and their corresponding elements every
y :=key(T) do write(y, “’s”, T[y] |
record variable(field1, field…)
record
student(name, age, grade)
and, for Java we can create a student class with the same variables,
class student{
public
student(String name, int age, String grade)
{this.name
= name; this.age = age; this.grade = grade;}
private
String name;
private
int age;
private
String grade;
}
The only different Java’s object and Icon’s record is that Java can make specific method to manipulate the object, but Icon doesn’t support this feature.
Type Determination:
Icon provides the function type(x) to determine the type of a value. This function produces a string that is the name of the type of x.
For example, the value of
type(“Hello world”)
is “string.”
Type Conversion:
Icon allows values of four types be converted values of other types.
Type
in |
Type out |
|||
|
Cset |
integer |
real |
string |
cset |
N/A |
depending
on the value |
depending
on the value |
always
possible |
integer |
always
possible |
N/A |
depending
on the value |
always
possible |
real |
always
possible |
depending
on the value |
N/A |
always
possible |
string |
always
possible |
depending
on the value |
depending
on the value |
N/A |
Implicit Type Conversion:
Implicit conversion occurs in contexts where the type of a value that is expected by an operation is different from the type that is given. For example, in
write(number)
the integer reference by the variable number is converted to a string in order to be written.
Explicit Type Conversion:
Icons provide numbers of function for explicit type-conversion. For example,
s :=
string(x)
converts x to a string and assigns that string value to s. The other explicit type-conversion functions are cset(x), integer(x), and real(x). The function numeric(x) converts strings to their corresponding numeric values.
Comparing Values:
Five of the eleven build-in data types: cset, integer, null, real, and string, have the property of having “unique” value. It means that equivalent values of these types are indistinguishable. For example, csets are converted to strings in string comparison operations. A general value-comparison operation
x===y
unlike string comparison, value comparison fails if x and y do not have the same type. No implicit type conversion is performed. For the types that have unique values, value comparison succeeds if the values are the same; for other types, value comparison succeeds only if the values are identical. For example, this list comparison,
[1]===[1]
fails because the two lists are not identical, even though they are equivalent in size and contents.
The default scooping for local identifiers is one of the potential problems for programmers, especially when we try to compile a program from several files. For example, “A global declaration in one file may change the scope of an otherwise undeclared identifier in another” (Griswold 20).
The concept of success and failure is another problems for most programmers, who had learned Basic and Pascal. These user tend to feel that success and failure are merely Boolean true and false values.
Icon’s pointer semantics for structures is another problem. Because of pointer semantics, unintentional aliasing is a common problem. It occurs “when a structure is the default value for a table and is not replicated when used for different new table keys.
Icon’s low-level string operations and its higher-level string scanning clash, “but programmers nonetheless often mix them; in fact the language provides no alternative to this in some cases. (Griwold 21).”
“The lack of a conversational, interactive interpreter for Icon also is frequently cited as a deficiency. This problem is being addressed by Blachard [1991]. (Griswold 21).”
For most languages, they only support expression that produces an outcome of a single value. For example, x*3 produces the product of x and 3. Icon provides other expression called generator, which produce a sequence of results. There are several built-in generators. For example, x to y by z, which generates the integers from x to y in increment of z. The “by z” is optional; the default for z is 1. An application of such generator is,
every a := 1 to 10 do
write(a^3)
This code writes the cube of integer from 1 to 10. Another generator is !x, which generates all the characters from string x or the element from aggregate x.
Every expression evaluation is “success” if one value if produce; an expression is “fails” if the expression does not produce a value. For example, a > (b | c) first compares a with b. If a is bigger than b, the evaluation is succeeds and the produced value is a. If a is smaller than b, a is compared with c (the next value generated by the subexpression b | c. If a is bigger than c, evaluation is succeeds and the produced value is c. Since b and c are the possible value, so if both of the evolutions- a>c and a>b failed, the expression is considered fail, and no value is produced. This backtracking mechanism is limited to the expression in which it occurs, for example,
min :=min
> a
if a
<(b | c) then write(a)
failure in the second expression does not affect the outcome of the first.
String analyze is one of the many specialties that Icon has because it has numerous built-in procedures and operators that take strings and positions as operands and return strings or position. The general form of a string-scanning expression is
expr1
? expr2
where exp1 provides the subject to be scanned and expr2 does the scanning. The outcome of the expression is the outcome of expr2. One of the string analysis operation is find(s), whose out put is the positions in the subject at which s occurs as a substring. For example,
“I like
computer; I also like programming” ? write(find(I))
prints 1, and 18.
Some other operators are upto(s), which return the position of any of the characters in s, and many(s) returns the position following the longest possible substring containing only characters in s starting at the current position.
There are also some operators called matching function, which produces a portion of the subject while changing the position. An example of marching function is move(s), which advances the position by s characters. If it is successful, move return a substring between the s character and the end of the string. For example,
prints “ “, “i”, “e”, “c”, “m”, “u”, and “e”.
Another matching function is tab(s), which return a substring between the s position to the end of the string.
There are many waiting to write a program that prints “Hellow World” on the screen. These are the few ways:
#
example 1
#
This is the simplest way; we simply use the write function
procedure
main ()
write(“Hello World”)
end
#
example 2
#
This program uses default local identifier to store the string
#”Hello
World”
procedure
main()
greeting := “Hello World”
write(greeting)
end
#
example 3
#
This program uses the main to call printHellow function,
#
which prints “Hello World”).
procedure
main()
printHello()
end
procedure
printHellow()
write(“Hellow World”)
end
#
example 4
#
This program uses parameter passing from the main to
# a
procedure
procedure
main ()
twoString(“Hello”, “World”)
end
procedure
twoString(a, b)
write(a)
write(b)
end
This example is directly copied from:
Ralph E. & Madge T. Griswold. The Programming Language 2nd Edition. New Jersey: Prentice Hall, 1990. (310-314).
This program uses co-expressions to display solution to the n-queens problem on an ANSI-standard terminal. The number of queens is given by a command-line argument. The default is 8. The -s option causes the display to stop after each solution and wait for the user to enter a return to continue. The -a option causes the placement of each queen to be shown during the search for a solution. The -h option provides a help message.
The solutions are printed showing the positions of the queens on the chessboard. The following output is typical:
-----------------------------
|Q | | |
| | | |
|
-----------------------------
| | | |
|Q | | | |
-----------------------------
| | | |
| | | |Q
|
-----------------------------
| | | |
| |Q | |
|
-----------------------------
| | |Q | |
| | | |
-----------------------------
| | | |
| | |Q | |
------------------------------
| |Q | | |
| | | |
-----------------------------
| | | |Q |
| | | |
-----------------------------
____________________________________________________________________________________________
#
vnq.icn
#
author: Steve Wampler
link
options
global
n, nthq, solution, goslow, showall, line border
procedure
main(args)
local i, opts
opts := options(args,
"ahs")
n := integer(get(args)) |
8 #
default is 8 queens
if \opts["s"] then
goslow := "yes"
if \opts["a"] then
showall := "yes"
if \opts["h"] then
helpmesg()
line := repl("|
",n)|| "|"
border :=
repl("----"), n) || "-"
clearscreen()
movexy(1,1)
write()
write(" ", border)
every 1 to n do {
write("
", line)
write("
", border)
}
nthq :=
list(n+2)
# need list of queen placement routines
solution :=
list(n) #
... and a list of column solutions
nthq[1] :=
&main # 1st queen is main routine.
every i := 1 to n
do #
2 to n+1 are real queen placement
nthq[i+1] :=
create q(i) #
routines, one per column.
nthq[n+2] := create
show() # n+2nd queen is display
routine.
write(n, "-Queens.")
@nthq[2] #
start by placing queen in first colm.
movexy(1,2*n+5)
end
#
q(c) - place a queen in column c (this is c+1st routine).
procedure
q(c)
local r
static up, down, rows
initial{
up :=
list(2*n-1,0)
down :=
list(2* n-1, 0)
rows
:= list(n, 0)
}
repeat {
every (0 =
rows[r := 1 to n] = up[n+r-c] = down[r+c-c] &
rows[r]
<- up[n+r-c] <- down[r+c-1] <- 1) do {
solution[c] := r # record placement
if \showall then {
movexy(4
* (r-1) + 5, 2 *c+1)
writes("@")
}
@nthq[c+2]
# try to place next queen
if
\showall then {
movexy(4*
(r-1)+5, 2* c +1)
writes("
")
}
}
@nthq[c]
# tell last
queen placer "try again"
}
end
#
show the solution on a chess board.
procedure
show()
local c
static count, lastsol
initial count := 0
repeat {
if /showall &
\lastsol then {
every c := 1 to n do {
movexy(4*(lastsol[c]-1)
+5, 2*c+1)
writes("
")
}
}
movexy(1, 1)
write("solution:",
right(count +:= 1, 10))
if /showall then {
every c :=
1 to n do{
movexy(4*(solution[c]-1)
+ 5, 2 *c+1)
writes("Q")
}
}
lastsol := copy(solution)
}
if \goslow then {
movexy(1, 2 * n + 4)
writes("Press return to see next solution.")
read() | {
movexy(1 , 2 * n +5)
stop("Aborted.")
}
movexy(1
, 2 * n +4)
clearline()
}
@nthq[n+1] #tell
last queen placer to try again
}
end
procedure
helpmesg()
write(&errout, "Usage
: vnq [-s] [-a] [n]")
write(&errout, "\twhere
-s means to stop after each solution.")
write(&errout,
"\t -a means to show placement of every queen")
write(&errout,
"\t while trying to find a
solution")
write(&errout, "\t
and n is the size of the board (defaults to 8)")
stop()
end
#
Move cursor to x, y
procedure
movexy (x, y)
writes("\^[[", y,
";", x , "H")
return
end
#
Clear the text screen
procedure
clearscreen()
writes("\^[[2J")
return
end
#
Clear the rest of the line
procedure
clearline()
writes("\^[[2K")
return
end
The Icon Programming Language (by the Computer Science Department at Arizona University): http://www.cs.arizona.edu/icon/
The Icon programming Language (by New Mexico Tech): http://www.nmt.edu/tcc/help/lang/icon/
Computer: Programming Language: Icon (by dmoz): http://dmoz.org/Computers/Programming/Languages/Icon/
Icon Programming Language Handbook, by Thomas W. Christopher (Required Adobe Acrobat Reader)
Ralph E. Griswold & Madge T. Griswold. History of the Icon Programming Language. ACM SIGPLAN, Volumn 28, No.3 March 1993.
Ralph E. Griswold & Madge T. Griswold The Programming Language 2nd Edition. New Jersey: Prentice Hall, 1990.