About this ‘A Language a Day’ Advent Calendar
This article became a part of my book ‘A Language a Day’, which you can get in both electronic and paper format. Languages covered in the book: C++, Clojure, Crystal, D, Dart, Elixir, Factor, Go, Hack, Hy, Io, Julia, Kotlin, Lua, Mercury, Nim, OCaml, Raku, Rust, Scala, and TypeScript.
Welcome to Day 23 of this year’s A Language a Day Advent Calendar. Today’s topic is introduction to the Io programming language.
Facts about the language
- Prototype-based, object oriented
- Dynamically typed
- A homoiconic language
- Appeared in 2002
- Website: iolanguage.com
Installing and running Io
To install Io, download one of the packages for your operating system.
To run a program, run io
:
$ io helloworld.io
Hello, World!
Here is the minimum Hello, World! program in Io:
"Hello, World!\n" print
Alternatively, you can use println
to add the newline instead of \n
:
"Hello, World!" println
What happens in the Hello, World! program is you send the print
message to the string. In essence, this is a keystone knowledge of the design of Io.
Variables
To create a variable, use the :=
assignment.
name := "John" ("Hello, " .. name .. "!") println
Notice the ..
for string concatenation here.
There are also ::=
and =
forms, please refer to the Io guide for more details about them. ::=
also creates a setter, while =
raises exception when the slot does not exist.
Functions
To create a function, use method
. Let us first create a function that takes no arguments.
greet := method("Hello, World!" println) greet
In the second line, you call the earlier created function.
Now, let us add an argument by just listing it before the function body:
greet := method(name, ("Hello, " .. name .. "!") println) greet("Alla")
A Factorial example
Here is a possible solution of computing a factorial:
factorial := method(n, if(n < 2, 1, n * factorial(n - 1))) factorial(1) println # 1 factorial(5) println # 120 factorial(7) println # 5040
But there is a simple way, as the function that we need is already built in:
1 factorial println // 1 5 factorial println // 120 7 factorial println // 5040
Objects
Io implements the prototype-based object-oriented mechanism. To create a new object or a type, clone the Object
object:
Person := Object clone
An identifier that begins with a capital letter is considered a type. Otherwise, it is an object.
Object fields, or, slots, are accessed by sending messages to the object. For example, let us state that a Person
works in the X
company:
Person company := "X"
Now, we can create (or clone) people working in this company, and set their own slots:
john := Person clone john name := "John" john age := 23 alla := Person clone alla name := "Alla" alla age := 22
Whenever you need to access data, do it in the same manner:
((alla name) .. " is " .. (alla age)) println ("She works in " .. (alla company)) println
This program prints:
Alla is 22 She works in X
Be careful not to accidentally send messages that has no effect. This can happen when you omit a punctuation or type extra characters.
("Works in" (alla company)) println 42
The output of this line of code is a single string "Works in"
.
Inheritance
Expressing inheritance is very easy, just clone a type and set the needed slots:
Person := Object clone XPerson := Person clone XPerson company := "X" YPerson := Person clone YPerson company := "Y"
Now, we have a type for people working in X and another type for those who work in Y.
john := YPerson clone alla := XPerson clone
A Polymorphic example
Let us define the two types that are based on the Animal
type. Just for diversity, let us add an unknown animal to the collection. That animal will be served but the info
slot of the Animal
type object.
Animal := Object clone Animal info := "I am an unknown animal" Cat := Animal clone Cat info := "I am a cat" Dog := Animal clone Dog info := "I am a dog" zoo := list(Cat clone, Cat clone, Dog clone, Dog clone, Animal clone) zoo foreach(i, x, x info println)
In the foreach loop, the x
variable loops over the zoo
list items and it receives the info
message, which returns a different string depending on a real type of the object.
As an exercise, modify the program to make info
methods, for example:
Dog info := method("I am a dog" println)
Concurrency
Io offers support for coroutines and the scheduler, actors (which are objects having their own coroutine), and futures.
Let us use actors to implement the Sleep sort algorithm.
Sleep Sort
The main idea behind the following solution is to send an asynchronous message to an object. So, we define the Sorter
type that has the sort
method. To send the message (sort
in our case) asynchronously, prefix it with @@
.
data := list(10, 4, 2, 6, 2, 7, 1, 3) Sorter := Object clone Sorter sort := method(n, wait(n/10); n println ) sort_me := method(n, s := Sorter clone; s @@sort(n) ) data foreach(n, sort_me(n)) wait(2)
Get more
Io is a very syntactically compact language. Its basics can be learned literary within minutes. To dive deeper, examine its documentation pages:
The source codes of this issue of the series are located on GitHub.
Next: Day 24. Factor