Introduction edit

Icon - What is this? edit

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 edit

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 edit

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 edit

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.

Variables edit

About variables in Icon edit

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 edit

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

Global variables edit

Numbers edit

Strings edit

Introduction to strings in Icon edit

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 edit

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:

  • variablename[from:to]
  • variablename[index]

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].

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

Special characters edit

Operators edit

  • *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:
str := "Hello" || " " || "world"       # str := "Hello world"
str ||:= "!"                           # str := "Hello world!"
  • 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

String scanning edit

Lists edit

Overview of lists edit

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 edit

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:

  • list (i,x)

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()                # []

Operators edit

Arrays edit

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 edit

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

Characters sets edit

Tables edit

Record types edit

Record type declaration edit

To declare record type use record reserved word, for example:

record person(firstname, lastname, age)

Construction of the record variable edit

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 edit

  • 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 edit

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".

#example of the use of the reserved word return
procedure ex-ret(var1, _Var2)
b := "a_proc succeeded"
if a_proc(var1) then return b else c_proc(_Var2)
end

Generators edit

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

Goal-directed execution edit

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"

External links edit