Unicon Programming — Unicon Programming v0.6.148

Unicon, Unified extended Icon, by Clinton Jeffery, Shamim Mohamed,
Jafar Al Gharaibeh, Ray Pereda, Robert Parlett, and team.
Icon, an iconoclastic programming language. The design of Icon was led by
Dr. Ralph Griswold at the University of Arizona, starting in 1977, as a
structured successor to SNOBOL and refinement of SL5. Icon includes a
rich set of datatypes and operators, generators, goal directed evaluation with
implicit backtracking, text scanning, integrated graphics, and other
complementary very high level features. The design facilitates powerfully
concise, yet surprisingly readable program source code. All with an admirable
performance profile.
Unicon extends the feature set of Icon by adding classes, a POSIX
layer, networking, and a host of other modern development productivity
enhancements. Development of Unicon is led by Clinton Jeffery.
Well met
#
# Introductory Unicon
#
procedure main()
write("Hello, world")
end
Example run:
prompt$ unicon -s introductory.icn -x
Hello, world
And that is the Hello, world program for Unicon, proof that the basic
system is properly installed and functioning.
Unicon deserves a little more than that, so this next introduction lets us
see what features are included in the installation.
#
# Introductory Unicon
#
procedure main()
write("Hello, world")
write("\nFeatures in this ", &version)
every write(&features)
end
examples/introductory-features.icn
This time, all the glorious command line details are also included, but don’t
worry, this will all be second nature before you know it.
prompt$ unicon introductory-features.icn -x
Parsing introductory-features.icn: .
/home/btiffin/unicon-git/bin/icont -c -O introductory-features.icn /tmp/uni12016255
Translating:
introductory-features.icn:
main
No errors
/home/btiffin/unicon-git/bin/icont introductory-features.u -x
Linking:
Executing:
Hello, world
Features in this Unicon Version 13.1. August 19, 2019
UNIX
POSIX
DBM
ASCII
co-expressions
native coswitch
concurrent threads
dynamic loading
environment variables
event monitoring
external functions
keyboard functions
large integers
multiple programs
pattern type
pipes
pseudo terminals
system function
messaging
graphics
3D graphics
X Windows
libz file compression
JPEG images
PNG images
SQL via ODBC
Audio
secure sockets layer encryption
CCompiler gcc 5.5.0
Physical memory: 7808401408 bytes
Revision 6034-743ffd1
Arch x86_64
CPU cores 4
Binaries at /home/btiffin/unicon-git/bin/
So, yeah, wow, there is a lot of neat stuff in there.
Seeing as there are graphics, here is a graphical hello.
#
# hello-graphics.icn, graphical hello demonstration
#
procedure main()
w := open("hello-graphics", "g")
writes(w, "Hello, graphic world")
Event(w)
close(w)
end

examples/hello-graphic-borders.icn
That example is the basics for graphical output in Unicon.
As simple as console output, to a graphical window.
The next listing is a little more sophisticated, more appropriate for the
automatic image captures shown throughout this docset. Note the different
font choice.
#
# hello-graphics.icn, graphical hello demonstration
#
procedure main()
if find("graphics", !&features) then stop("no graphics, sorry")
w := open("hello-graphics", "g", "font=12x24", "rows=1",
"columns=22", "canvas=hidden") |
stop("no graphics window")
writes(w, " Hello, graphic world ")
WSync(w)
WriteImage(w, "../images/hello-graphics.png")
close(w)
end
Giving:
prompt$ unicon -s hello-graphics.icn -x

Overview of Unicon
Note
Unicon encompasses Icon. Many things attributed to Unicon here,
may have originated in Icon. Attempts will be made to clearly state
when Icon is the origin. Everything from Icon is in Unicon, and then
extended out by the Unicon team. This Unicon centric view is not
meant as a slight to the Icon project, but merely a convenience when
writing about Unicon.
A quick tour of Unicon syntax and semantics.
Unicon is a very high level, network and graphic savvy, multiple paradigm
programming language. Elements of imperative, procedural, concurrent, object
oriented, reflective, and iterative programming are present and can be freely
mixed. Support library sources add more paradigms in a limited fashion, such
as interactive, list, logic and XML based programming.
Unicon counts as a curly-bracket language.
The reference implementation is written in C (and a specialized C variant
called rtt).
A Java based variant is available, Junicon,
http://junicon.sourceforge.net/site/index.html, but this version is not yet
complete in terms of runtime function support. Junicon translates core Unicon
to Groovy (for an interactive interpreter mode) or Java (for regular compiled
mode) on way to the JVM.
The rest of this page describes the reference implementation, although most of
the material would be the same for Junicon.
The Icon programming language lies at the heart of Unicon. Icon has been in
development in various forms since 1977, with predecessors including SNOBOL
and SL5, which date back even further to the 1960s. Unicon builds on the Icon
feature set.
Icon is marked as complete, and is in maintenance mode. Unicon continues to
evolve, and is in active development.
Unicon includes a vast array of features. One can look at that as tool
bloat; but a better, more productive, point of view is to look at Unicon as
a full tool box. A single, unified entity containing a well integrated
collection of mechanisms, working together to become greater than the sum of
the parts. (Without bulging at the seams).
Virtual Machine
Unicon source can be compiled for a cross platform virtual machine ucode
readable source and icode bytecode.
Or Unicon source can be natively compiled to binary executable form using a
-C command line option. Native compiles do not yet support all Unicon
features.
Expressions
Unicon is an expression language; everything is an expression, including
control flow reserved words. Unicon expressions produce a value or fail.
Expressions strive to succeed and will attempt alternatives, within the bounds
of an expression context, before producing a value or eventually failing.
This is termed goal-directed evaluation. Goal-directed evaluation works
hand in hand with generators, mentioned below and works best when
backtracking is kept in mind.
A nice one word synopsis of Unicon is determination.
Values and Types
There are 6 basic immutable types in Unicon:
- null (with a special keyword name, &null)
- integer
- real
- string
- cset (short for character set)
- pattern
Unicon is an 8 bit clean ASCII system, zero valued bytes are allowed in
strings and character sets. Unicon uses one relative indexing in most cases,
the first element is 1, not 0.
Values have a type, variables do not. Variables can be freely assigned any
value. All values are first class values in Unicon, and can be assigned to
variables, passed as arguments, and returned as results.
Strings are immutable, and subscript assignment or concatenate operations will
produce a new string, not change an existing string value in place.
Unicon has no pointers, but internally manages references to values.
There are high level, mutable, structured data types:
Unicon includes class and method definitions that internally use record
structures for compile time and runtime management.
Unicon also has a set of support data types:
- co-expression (including synchronous tasks and concurrent threads)
- window
- file
Variables not bound to a value default to null, represented by the keyword
&null.
Although Unicon allows variable use without declaration, explicit control over
local, global and static scope is always preferred and can avoid
unintended name resolution behaviours. This can be a problem when changes to a
program introduce a new global and previously undeclared, assumed
local, variables are no longer local to a particular procedure.
Undeclared variable warnings can be produced with the compiler -u switch.
Numeric calculations will raise a runtime error when non numeric values (or
values that cannot be unambiguously converted to numeric) are included in a
computation.
Runtime errors normally cause an abnormal program termination with back trace,
but can be transformed and treated as failure conditions through the use of
a special keyword, &error.
Automatic type coercion is attempted between integer, real, string, and
character set values as required by the surrounding expression context.
null and the empty string are not promoted to zero in calculations, but
cause an aforementioned runtime error.
Division with all integer values produces an integer result. Division by zero
causes a runtime error. Zero to the power of zero is deemed an undefined
number and causes a runtime error.
Integer literals can include a base radix prefix, and real
number literals can include an exponent notation suffix. Base
10 integer literals can also include a scaling suffix. Integer literal
scaling includes (case insensitive):
Integer literals can be of arbitrary magnitude.
Internally, large integers are a special type and values exceeding native
processor signed value bit widths (commonly 15, 31, or 63 bits) are
automatically managed by Unicon with special software routines. (These large
integer routines are much slower than native hardware integer computation
circuitry and are, by necessity, non-atomic when concurrency is involved).
Although transition from native to large integer handling is automatic, and
does not usually require any attention when programming, there may be times
when explicit handling is called for. There is a sample in the Program
Library for testing when a number has been promoted to large integer
form.
String literals use double quotes, i.e. "a string".
Character set literals, called Cset in Unicon, use apostrophe (single
quotes), i.e. 'aaaxyz'. Please note, cset data is a set. That
previous example will only contain a single occurrence of the a character
at runtime.
String literals can be extended across lines by ending the source line with an
underscore. Leading spaces on the following line are ignored.
Newlines and other non printable characters can be included in string literals
using backslash escape notation.
|
|
Regular expression literals use open and close angle brackets (chevrons), i.e.
<[a-c]>, matches a or b or c during a match expression.
List literals are enclosed in square brackets, each element separated by
commas. Elements can be any type, including lists or other high level
aggregate types. Empty lists are expressed as []. Dangling commas at the
end of a list literal create an extra null item in the list, as do empty
intermediate entries.
List comprehensions use [: expr :] bracket colon/colon bracket syntax. The
resulting list will be all the values generated by expr.
Scope
Unicon has local, static (local), and global scope. There is also support
for package variable name spaces.
Undeclared variables inside procedures default to local scope. This can be an
issue during long term maintenance. If a global variable is later declared
with the same name, an “undeclared” procedure variable is now declared and the
procedure may inadvertently change a global value with undesirable outcome.
Long term Unicon development wisdom means fully declaring all local variables
even though it is a default semantic.
unicon -u will cause a compile time error when detecting use of an
undeclared local variable. You will need to run this pass before adding
any new global variables for maximum effect in catching inadvertent name
conflicts.
Static variables are local to a procedure but retain values between
invocations of the procedure. The initial clause is handy for preparing
static values when more than simple assignment is required (loading tables
from disk, for instance). The initial expression is only evaluated once
per procedure during the lifetime of a program.
Procedure names are global. Procedure parameter identifiers are always
explicitly local to the procedure, overriding any global identifier lookup.
For those rare times when a procedure needs to access a global variable with
the same name as a parameter, the variable built in reflective
function can be used.
Record constructor descriptors are global. Although the inner field names are
somewhat local to the record (there can be duplicate member names across
different records). All instances of a record type have the same field names.
Class definitions are global. Methods follow the same inner-local sharing as
records. All instances of a class have access to all the variable and method
names of the class, but different classes may use duplicate names inside.
The package declaration specifies that all global symbols within the source
unit belong to a named package. All global declarations (variables, procedures
records and classes) are invisible outside the package, unless explicitly
imported. This feature, along with class definitions, uses an external compile
time database to help manage namespace and import linkage of resources within
a package.
Package management in Unicon is designed as a “programming in the large”
feature. There are some externally influenced management issues to be aware of
to ease programming at this scale. See the package entry and Objects
for details.
Functions
Unicon builds with over 300 predefined functions.
User defined functions are called procedures in Unicon. These
are all expressions that produce values or fail.
Unicon does not have a so called void type; there is success and a value
(possibly null) or failure.
Note
Throughout this documentation, the terms function and procedure are
used somewhat interchangeably given the context of Unicon.
In comparison to some other programming languages, such as Pascal where
by definition procedures do not return values. Or in a mathematical
sense where functions do not cause side effects. Neither of those cases
hold in current or historic Unicon terminology or jargon. Nothing will
stop you from writing code to meet those stricter definitions if so
desired, but they are not commonly used Unicon terms of art.
Procedure names can be overridden within scoping rules.
As first class values, procedure and function references can be passed as
arguments, returned from procedures, and bound to variables.
Procedures are invoked with commonly seen function(args,...) parenthesis
syntax or function!list application.
Programmer defined control structure invocation is also possible with
function{expr1; expr2...} brace syntax. See User defined control structures.
Procedures can also be invoked by string name once enabled (see
invocable).
More technically, the syntax is actually expr (), where the invocation
operator () follows an expression, any expression.
When the initial invocation expression in an integer, it becomes a grouped
expression and the value determines the parameter to use as the result of the
entire comma separated expression group, counted from 1 going left to right.
For example: 2(first(), second()) is a grouped expression returning the
second result.
Procedures compiled for the Unicon virtual machine can be linked into other
Unicon programs with the link reserved word. The link phase is fairly
smart, and will only include procedures actually used (or set as
invocable), so there is no worry of overall program bloat when linking
to files that contain multiple procedures.
Without an explicit return or suspend, procedures fail by default.
That means that procedures that “fall through” to the end reserved word,
fail and produce no value. This has implications that developers should
keep in mind. An empty return can be used to avoid unexpected nested or
chained expression failure.
String scanning
The Unicon language includes a syntax for string scanning, with bookkeeping of
subject string and current position managed by the scanning environment.
s is a subject string, and the expr scanning expression can be
arbitrarily complex. Results can be nested in other scanning expressions.
String scanning can be far more powerful than regular expressions. The
subject matter does not need to be regular or finite or free of context.
String scanning expressions can have ever changing contextual state managed
within the expression itself, and are free to move the position of interest
without constraint. Theoretically. You will exceed the limits of RAM and
disk space available in the world before you exceed the power inherent in
Unicon string scanning expressions. And if you think you are getting close,
Unicon also supports regular expressions and SNOBOL style patterns,
so, the Universe is the limit (and then some).
Generators
Functions and operators can return values, or suspend values.
return places a boundary on goal directed evaluation, suspend allows
the Unicon goal-directed evaluation engine to resume a procedure and attempt
alternatives. return can be followed by any expression or if omitted,
defaults to a null value. suspend can include an optional do
phrase that is evaluated when the expression is resumed before following the
rest of the normal flow of control. In grand Unicon fashion, the expression
that follows suspend do can also be a generator.
Co-expressions
Unicon co-expressions are encapsulated expression contexts which allow for
parallel evaluation and coroutines, among other power features, like
concurrency and multitasking.
Graphics
Unicon builds with 2D, and 3D graphics facilities. Unicon also ships with an
object oriented, class based, graphical user interface builder. The
graphics engine is event driven with features allowing for implicit and
explicit event management.
Audio
Unicon supports sound, including a layer for VOIP if prerequisites are
available during build.
Object oriented
Unicon includes class based object oriented features. This layer is an
integration of the earlier IDOL preprocessor into the Unicon core language.
Unicon classes are quite simple and yet complex; circular inheritance is
supported (although not overly recommended unless programming routines
dealing with things like the wave/particle duality in quantum physics
theories).
Flexibility
Unicon leans to the more than one way of doing things school of thinking,
but there is also a tendency toward idiomatic Unicon, which comes with
experience and shared learning by example.
# do some thing to each line of an open file
while line := read(f) do {
thing(line)
}
# same, without bracing
while line := read(f) do thing(line)
# another form with nested expressions
while thing(read(f))
# another form, using the generate elements operator
every line := !f do thing(line)
# object oriented forms (if f is a class instance encapsulating file)
every f.thing()
# or an alternative
while f.thing()
# others, yes there are other expression forms...
# and perhaps the idiomatic form (opinions may vary)
every thing(!f)
You are free to choose. Unicon practitioners will accept all of the above
forms as valid source constructs, but that last one sure is concise, sweet
looking code.
Unicon expression and operator syntax is so well designed and flexible
that even after 40 years of study, advanced programmers are still
impressing each other with new techniques. Ok, maybe that is just this
author’s impression from initial readings of some of the conversations
between the Unicon gurus regarding the secrets yet to discover in Unicon
syntax and idioms.
Building Unicon from source
Now on to getting all this Unicon goodness installed on your computer.

Where url-svn is svn://svn.code.sf.net/p/unicon/code/trunk unicon-svn.
./configure options are explained in more detail in the README file. For a
a list of build options, use ./configure --help.
GNU/Linux
In the instructions below, working-dir, install-dir, and
unicon-projects are dealer’s choice directory names (pick a name
appropriate for the local system).
Unicon follows the de facto standard ./configure; make; sudo make install
paradigm. There are quite a few options to allow for customized builds. See
./configure --help for details of all the build options. Enable and
disable features and components during the ./configure phase.
prompt$ cd $HOME/working-dir/
prompt$ svn checkout svn://svn.code.sf.net/p/unicon/code/trunk unicon
prompt$ cd unicon
- Prep: (somewhere in ~/.bashrc add)
# add unicon
add-unicon () {
if [[ ! $PATH =~ unicon ]]; then
PATH="$HOME/working-dir/unicon/bin:$PATH"
export PATH
fi
}
You will now have an add-unicon shell function available. Set it to load
during startup or type the command when you want to have unicon tools
available.
Or simply use make install to install Unicon to the configured locations.
prompt$ source ~/.bashrc
prompt$ add-unicon
The above step will not be necessary if make install was used.
prompt$ cd $HOME/unicon-projects/
prompt$ cat hello.icn
procedure main()
write("Hello, world")
end
prompt$ unicon -s hello.icn -x
Hello, world
Party, like it’s 2099.
The Unicon source build creates a directory structure and command sequence so
the only thing you really need to do is set the PATH to the unicon/bin
directory. This layout knows where the link libraries are, include
subdirectories, etcetera. If you like a little more control over the
placement, then read through $HOME/working-dir/unicon/Makefile for details
on setting up an install with:
prompt$ sudo make install
If using the default prefix (/usr/local usually), the above command
(usually) requires sudo or run the command as the root super user so the
installer has permissions for the system directories.
There are older Make rules to control this as shown below, but using the de
facto standard DESTDIR and PREFIX settings are now recommended.
prompt$ make Install dest=install-dir
You can change the add-unicon function to set the path to this shiny new
install-dir/bin, (or, just export that bin path). The add-unicon
function is handy when initially trying out a Unicon build, but you will
probably find that setting the Unicon path becomes part and parcel of your
shell login. I never type add-unicon anymore, the Unicon path setting is
built into the shell startup now.
As of Unicon 13.1, Jafar has created package build rules, which can be used to
build your own binary packages. Jafar has also created a PPA (Personal
Package Archive), which can be used to automatically stay up to date with
binary builds of Unicon on Ubuntu. No sourcing around required.
- sudo add-apt-repository ppa:jafaral/unicon
- sudo apt update
- sudo apt install unicon
- Time to enjoy programming in Unicon
Things should now be ready to go; so on with the show…
But first, a brief word from our sponsors … the people that created
Unicon, not advertising, this is free documentation.
Feel free to skip over some of this very exciting background and history
information and get right into Datatypes, or hit Development Tools and leap
right into developing, compiling, and running Unicon programs.


