Icon
- Appeared in:
- 1977
- Paradigm:
- Typing discipline:
- File extensions:
- .icn
- Versions and implementations (Collapse all | Expand all):
Icon is a high-level general-purpose programming language suited for tasks that involve strings and data structures.
Icon was created in 1977 at the University of Arisona. It has objectives and capabilities similar to those of SNOBOL, but doesn’t really resemble it. Note that the language was developed much earlier than graphical user interfaces were invented, let alone became popular, so the name is not associated with this meaning of word “icon”.
Icon is a procedural language with strong dynamic typing. Its key features are:
- mechanism of expression evaluation which uses goal-oriented evaluation and backtracking.
-
generators — expressions which produce more than one result. All expressions and imperative constructs of the language are potential generators. A special control structure
every-do
allows to process all results returned by a generator. - string scanning: a mechanism of processing strings in a convenient way by binding a string to an expression and scanning it with string matching functions.
- support for several types of data structures: lists (linear collection which allows access both by element position and by stack/queue-style functions), sets (collections without any particular ordering) and tables (associative lookup collections).
- high-level window-based graphic facilities.
- automated garbage collection.
- integers with arbitrary precision.
- the original language is not object-oriented; in 1996 an object-oriented extension was developed which late became Unicon.
Elements of syntax:
Inline comments | # |
---|---|
Variable assignment | := or <- (reversable at backtracking) |
Block | { ... } |
Physical (shallow) equality | = (numbers) or == (strings) |
Physical (shallow) inequality | ~= (numbers) or ~== (strings) |
Deep equality | === |
Deep inequality | ~=== |
Comparison | < > <= >= << >> <<= >>= |
Function definition | procedure f(p1, p2, ...) ... end |
Function call | f(a, b, ...) |
Function call with no parameters | f() |
Sequence | ; |
If - then | if condition then ... |
If - then - else | if condition then ... else ... |
Loop forever | loop ... |
While condition do | while condition do ... |
For each value in a numeric range, 1 increment | every i := 1 to 10 do ... |
For each value in a numeric range, 1 decrement | every i := 10 to 1 by -1 do ... |
Icon logo
Links:
Examples:
Hello, World!:
Example for versions iconc 9.4procedure main ()
write ("Hello, world!")
end
Factorial:
Example for versions iconc 9.4This example uses recursive factorial definition. 0 to 16
is a generator which returns all integers between 0 and 16, inclusive. every ... do
allows to fetch every result returned by the generator and process it (calculate factorial and perform write
).
procedure factorial (n)
if n = 0 then
return 1
else if n > 0 then
return n * factorial (n - 1)
end
procedure main ()
local i
every i := 0 to 16 do
write (i, "! = ", factorial (i))
end
Factorial:
Example for versions iconc 9.4This example uses iterative factorial definition written in short form. every j *= 1 to i
multiplies j
by all values returned by the generator 1 to i
. The expression in braces calculates factorial by multiplying j by all values between 1 and i and returns it. The outer expression calculates and prints factorials of all numbers returned by the generator 0 to 16
.
procedure main ()
local i, j
every write (i := 0 to 16, "! = ", { j := 1; every j *:= 1 to i; j })
end
Fibonacci numbers:
Example for versions iconc 9.4This example uses recursive calculation of Fibonacci numbers with memoization.
global fib_memo
procedure fib (n)
if n >= 0 then
return ((/fib_memo [n] := fib (n - 2) + fib (n - 1)) | fib_memo [n])
end
procedure main ()
local i
fib_memo := table ()
fib_memo [0] := 0; fib_memo [1] := 1
every i := 1 to 16 do {
writes (fib (i) || ", ")
}
write("...")
end
Quadratic equation:
Example for versions iconc 9.4procedure main ()
A := read();
if A = 0 then {
write("Not a quadratic equation.");
return;
}
B := read();
C := read();
D := B*B - 4*A*C;
if D = 0 then {
write("x = ", -B/2/A);
return;
}
if D > 0 then {
write("x1 = ", (-B+sqrt(D))/2/A);
write("x2 = ", (-B-sqrt(D))/2/A);
} else {
write("x1 = (", -B/2/A, ",", sqrt(-D)/2/A, ")");
write("x2 = (", -B/2/A, ",", -sqrt(-D)/2/A, ")");
}
end
CamelCase:
Example for versions iconc 9.4First of all the program reads the string to process and adds a space to its end (||
is concatenation operator). After this text
variable is scanned. ?
is an operator which binds a string to the expression, so that all string matching functions in the expression are performed on this string.
Commands ReFind
and ReMatch
from regular expressions library regexp
both find all sequences of symbols which match the given regex, but ReFind
returns the index of sequence start, and ReMatch
— the index of the first character after sequence end. In one iteration ReFind
finds the start of the next sequence of non-letter characters. Command tab
moves current position pointer to this position and returns part of the string from previous position of the pointer to the new position — a word. After this the word is converted to proper case and concatenated to the resulting string. *word
is a function which returns length of the string. map
replaces all characters of its first argument which are present in its second argument with corresponding characters from its third argument (in this case — switch case of characters; &lcase
and &ucase
are built-in constants which contain lowercase and uppercase alphabet). Finally, one more call of tab
moves the pointer past the sequence of non-letter characters to the start of next word.
link regexp
procedure main ()
text := read() || " ";
cc := "";
text ? {
while j := ReFind("[^a-zA-Z]+") do {
word := tab(j);
cc ||:= map(word[1],&lcase,&ucase) || map(word[2:*word+1],&ucase,&lcase);
tab(ReMatch("[^a-zA-Z]+"));
}
}
write (cc);
end
Comments
]]>blog comments powered by Disqus
]]>