Icon Programming

Icon - What is this?
Icon is a modern high-level programming language. It provides many useful features for managing data, generators and much more. It is not object-oriented, but the UN-icon variant, UNICON, is object-oriented as is ObjectIcon (code.google.com/p/objecticon)

Hello world
Here is a tiny but complete Icon program.

procedure main write("Hello world!") end

As you see, the code is very simple. Lines procedure main and end enclose the body of the program. The second line is responsible for printing Hello world! on your standard output (usually screen). Naturally, procedure write prints the string which is given as a parameter. There is a similar procedure read which reads a line from standard input (usually keyboard).

Compiling and running
Save the program from the previous section to file helloworld.icn. Type icont helloworld.icn in linux shell. The executable file named helloworld will be generated. You can run it now.

Basic syntax
The program consists of procedures. Every procedure begins with procedure reserved word followed by the name of the procedure and list of arguments (it can be empty). The procedure ends with end. All the instructions are separated by newline or semicolon.

There must be a main procedure which is called automatically when user runs the program.

procedure p1(arg1, arg2, arg3) instr1 instr2 end procedure p2 instr1; instr2 end procedure main(arg) instr1 instr2 instr3 end

If you want to put a comment into your code, use # character. All the text in the line after that character is discarded by the compiler.

About variables in Icon
Variables in Icon have no type and can contain value of any data type. That means you can for example assign a number to one of your variables and assign a string to it few instructions later.

There is no need to declare variables (except global ones), they are created when they are used for the first time. There is no need to destroy them too, because there is a garbage collector doing it automatically.

Assigning value to variable
To assign value to variable use Pascal-like := operator:

procedure main x := 1                    # assigns 1 to variable x   y := 3                     # assigns 3 to variable y   x := x + y                 # assigns 4 (1+3) to variable x   y := "example string"      # assigns string "example string" to variable y end

Introduction to strings in Icon
A string is a sequence of characters. You can easily put string constants into your code, enclosing them with pair of " characters. For example: str := "abcdefgh" will create a string constant containing 8 characters and assign this string to str variable.

Accessing characters and substrings
Characters in strings are indexed in a very convenient way. As in Pascal, 1 points to the place before the first character, 2 to the place between the first and the second etc. Unlike many other languages, strings are indexed from the end too. 0 points to the place after the last character, -1 to the place before the last character, etc.



To access the part of the string you want, use the brackets [ ] operator: The first method returns a substring placed between points pointed by from and to. If you place only one number in the brackets, it is equivalent to variablename[index:index+1].
 * variablename[from:to]
 * variablename[index]

str := "sample string" str[1:7] := "SAMPLE"   # str := "SAMPLE string" str[3] := "m"          # str := "SAmPLE string" write(str[8:0])        # write("string")

Operators
str := "Hello" || " " || "world"      # str := "Hello world" str ||:= "!" # str := "Hello world!"
 * *str - produces the length of str
 * ?str - produces the random one-character substring of str
 * !str - generates the sequence of one-character substrings of str
 * str1 || str2 - concatenates two strings:
 * strings case-sensitively comparison:
 * str1 == str2 - produces str2 if those strings are equal, fails otherwise
 * str1 ~== str2 - produces str2 if those strings are not equal, fails otherwise
 * str1 << str2 - produces str2 if it is greater than str1, fails otherwise
 * str1 <<= str2 - produces str2 if it is greater or equal than str1, fails otherwise
 * str1 >> str2 - produces str2 if it is less than str1, fails otherwise
 * str1 >>= str2 - produces str2 if it is less or equal than str1, fails otherwise
 * str ? expr - sets str as &subject for expr expression

Overview of lists
Lists are similar to strings, although they are able to contain much more various data. Like strings, lists are indexed from the beginning and from the end (read the Accessing characters and substrings section related to strings).

List creation
You can create list constants enclosing its elements with brackets and separating them with , character. For example: lst := [1, "hello", 44] creates three-element list constant and assigns it to the lst variable. To create empty list do not put anything between brackets: lst := []                    # lst value is now an empty list

There is a special function for creating lists of desired length: i-element list is created and all its elements are initialized with x value. By default i is 0 and x is &null. list(5, 7)           # [7, 7, 7, 7, 7] list(3, "text")      # ["text", "text", "text"] list(6)              # [&null, &null, &null, &null, &null, &null] list               # []
 * list (i,x)

Arrays
There are no arrays in Icon. Use lists instead. If you need multi-dimensional arrays, use lists of lists. matrix := list(3)               # makes a list of 3 rows every !matrix := list(5, 0)     # each a different list of 5 zeroes matrix[2][4] +:= 5              # adds 5 to the element # in 2nd row and 4th column every write(!!matrix)           # writes all the elements

Stack and queue
Very useful functions are given to manage stacks and queues as lists.
 * push(list, elem) - adds elem to the list list at its beginning.
 * pop(list) - produces the first element of list and removes it from list or fails if list is empty.
 * put(list, elem) - adds elem to the end of list.
 * get(list) - produces the first element of list and removes it from list or fails if list is empty, it is identical to pop.
 * pull(list) - produces the last element of list and removes it from list or fails if list is empty.

queue := []                     # creates an empty queue put(queue, 1)                   # puts 1 into the queue put(queue, "it is a string")    # puts "it is a string" into the queue write(get(queue))               # writes 1 write(get(queue))               # writes "it is a string" # queue is now empty stack := []                     # creates an empty stack put(stack, 1)                   # puts 1 into the stack put(stack, "it is a string")    # puts "it is a string" into the stack write(get(stack))               # writes "it is a string" write(get(stack))               # writes 1 # stack is now empty write(*queue)                   # writes length of the queue

Record type declaration
To declare record type use record reserved word, for example: record person(firstname, lastname, age)

Construction of the record variable
When you declare a record, a constructor for it is defined automatically. A constructor is a procedure, which arguments are initial values for record fields and returns the created record. The constructor 's name is the same as record's.

record person(firstname, lastname, age)     # declaration of person record jd := person("John", "Doe", 47)             # create and assign record value

Operators

 * rec.fieldname - produces a value of the fieldname field of the rec record
 * *rec - produces a number of fields of the rec record
 * ?rec - produces a value of a random field of the rec record
 * !rec - generates values of all fields of the rec record

Procedures
A procedure which forms part of the Icon language is conventionally referred to as a "function". A function which is added by the user as part of a program are referred to as a "procedure". A procedure may have a return value by preceding an identifier with the reserved word "return".

Generators
Generators, which are so fundamental to newer languages such as Ruby and Python, were first used in ICON shortly after CLU.

Goal-directed execution
Many ICON expressions are called "conditional expressions" and their evaluation results in success or failure. Three important examples are read(res) find( Str_target, Str_source) match( Str_target, Str_source) Comparison operators form expressions which succeed or fail such as write(count > 0) If count is not greater than zero then the comparison in the conditional expression fails; without an expression, the enclosing expression which is a call to the function write, is never evaluated and in that sense, inherits the failure of the conditional expression. By way of comparison b := "paused" if count > 0 then b := "running" write(b) # will write "paused" Goal-directed execution is not the very basis of Icon as it is in, say, Prolog. Icon is rather more like Oz, where backtracking is an option. In Icon, backtracking is available, but within the limits of a particular context. ICON also has the concept of "data backtracking"