The origins, philosophy, and influences behind Io.
Io is a dynamic prototype-based programming language. The ideas in Io are mostly inspired by Smalltalk[1] (all values are objects), Self[2] (prototype-based), NewtonScript[3] (differential inheritance), Act1[4] (actors and futures for concurrency), Lisp[5] (code is a runtime inspectable / modifiable tree) and Lua[6] (small, embeddable).
The focus of programming language research for the last thirty years has been to combine the expressive power of high level languages like Smalltalk and the performance of low level language like C with little attention paid to advancing expressive power itself. The result has been a series of languages which are neither as fast as C or as expressive as Smalltalk. Io's purpose is to refocus attention on expressiveness by exploring higher level dynamic programming features with greater levels of runtime flexibility and simplified programming syntax and semantics.
In Io, all values are objects (of which, anything can change at runtime, including slots, methods and inheritance), all code is made up of expressions (which are runtime inspectable and modifiable) and all expressions are made up of dynamic message sends (including assignment and control structures). Execution contexts themselves are objects and activatable objects such as methods/blocks and functions are unified into blocks with assignable scope. Concurrency is made more easily manageable through actors and implemented using coroutines for scalability.
Io is distributed as a single WebAssembly module (io_static.wasm) that runs under any WASM host — wasmtime, Node.js, or a browser. Source and build instructions live at github.com/IoLanguage/io.
To start the REPL, run the WASM binary under wasmtime:
wasmtime --dir=. build/bin/io_staticThis opens the Io interpreter prompt.
You can evaluate code by entering it directly. Example:
Io> "Hello world!" println
==> Hello world!Expressions are evaluated in the context of the Lobby:
Io> print
[printout of lobby contents]If you have a .iorc file in your home folder, it will be evaled before the interactive prompt starts.
You can get a list of the slots of an object like this:
Io> someObject slotNamesTo show them in sorted order:
Io> someObject slotNames sortFor a nicely formatted description of an object, the slotSummary method is handy:
Io> slotSummary
==> Object_0x20c4e0:
Lobby = Object_0x20c4e0
Protos = Object_0x20bff0
exit = method(...)
forward = method(...)Exploring further:
Io> Protos
==> Object_0x20bff0:
Core = Object_0x20c4b0Inspecting a method will print a decompiled version of it:
Io> Lobby getSlot("forward")
==> # io/Z_Importer.io:65
method(
Importer import(call)
)A script can be run from the interactive mode using the doFile method:
doFile("scriptName.io")The evaluation context of doFile is the receiver, which in this case would be the lobby. To evaluate the script in the context of some other object, simply send the doFile message to it:
someObject doFile("scriptName.io")The doString method can be used to evaluate a string:
Io> doString("1+1")
==> 2And to evaluate a string in the context of a particular object:
someObject doString("1 + 1")Example of printing out command line arguments:
System args foreach(k, v, write("'", v, "'\n"))The System "launchPath" slot is set to the location of the initial source file that is executed; when the interactive prompt is started (without specifying a source file to execute), the launchPath is the current working directory:
System launchPath