Note that this page refers to a relatively new language named Io; it's quite different from an earlier one of the same name that was based on continuation passing (see ContinuationExplanation and ContinuationPassingStyle). You can find out more about this older Io at OriginalIoLanguage.
Anyone here have any experience of Io Language? It's claimed to be small, embeddable, reasonably fast, clean, and all good things in a scripting language. It's a PrototypeBasedProgramming Language like SelfLanguage, inspired by NewtonScript and Smalltalk, embeddable like LuaLanguage, and I was wondering what it's like to use.
I have, and so far its everything its claimed to be. It could use a module system, but in this language that's really not more then a nit-pick. -- AnonymousDonorI've written a wiki engine in Io. It's not a particularly great wiki, but its source code does show off some of the things that are so nice about Io. It's also, I hope, going to encourage the Io community to improve the documentation of the language. See IoWiki or http://iowiki.sourceforge.net. -- JasonGrossman
The author, SteveDekorte, aims to have a 1.0 release by the start of 2006.
I (not the person who posted above) have written several hundred lines of Io, and both love and am frustrated by Io. My interest is in writing standalone apps, where I might have used RubyLanguage. The documentation is quite good, but is a bit out of date and incomplete. The author is active on the Io Yahoo Group, and responded to my question almost immediately. - Now there is a #Io channel on irc.freenode.net where you can get live answers too.
If you are already comfortable with Ruby, Io is pretty easy. The weirdest thing is that it doesn't have classes, but you really don't need them because you have object prototyping instead. I definitely wish there were more good, mainstream prototype-based languages.
Io is amazingly simple and clean, but still powerful. I also like that the interpreter, including the core library, is only 112k under Linux. For me, Io has two big weaknesses: 1) the author focuses almost exclusively on Io being an embeddable language, rather than a standalone interpreter, and 2) the core library (IoVM) is nowhere near as elegant as the language itself. -- KevinSmith
YukihiroMatsumoto ('Matz') himself has recommended that those who like Ruby should turn to Io as another interesting language to learn.
Famed Ruby advocate _why the lucky stiff wrote a pair of interesting posts regarding Io:
IoL4 (http://www.iol4.com/) is a small OperatingSystem containing the Io programming language on top of the EllFour microkernel.
link seems to be a spam tarpit now (2011-04-21)
Io's sample page [http://www.iolanguage.com/about/SampleCode/] is a fantastic advert for prototype-based programming. But it left me wondering why prototype-based languages haven't taken off? ... more discussion moved to PrototypeBasedProgramming
It has taken off, considering that JavaScript is ubiquitous in browsers.
I've written a number of Io programs now but still consider myself a novice. I found Io both comfortable and exciting: comfortable because my OOP experience applies; exciting because its simple extension mechanisms let me try new idioms from this comfortable base. IoGame is my first published program, an entry in the Io game programming contest. Documents linked to that page tell a little more about my experience. -- WardCunningham
The unified nature of Io (everything [really] is an object, and all coding is done via slot-accesses [i.e., message-sends]) means that the language is extremely extensible. For instance, as a thought exercise, I went to implement exception-handling in the try-catch style in Io (this already exists, but I thought it worth doing). Code follows:
Object try := method( sender doMessage(thisMessage arguments at(0)) ) Exception := Object clone Exception raise := method(n, m, new := self clone new name := n new message := m sender thisMessage return(new) ) Exception catch := method(exceptionProto, if(exceptionProto == self proto, sender setSlot(thisMessage arguments at(1) code, self) return sender doMessage(thisMessage arguments at(2)) ) self ) //Thus: try( Exception raise("An Exception", "We were expecting this") "This won't print\n" print ) catch(Exception, e, e name print "\n" print e message print ) //Multiple catches work, too, since catch returns the receiver. //-end-Does some nifty tricks with lazy evaluation of arguments and the Io idiom of code-as-argument. Line-by-line explanation can be made available if anyone is interested.
Actually, the above hasn't been tested, but it 'ought to work' -- the important parts are the code-as-argument bits and the ordering-other-methods-to-return thing that are nifty.
Io was recommended to me but I doubt I'll ever get past the syntax. Principally because I don't want to and would resent having to do it.
I don't know much about the subject so can anyone give me an idea how much time and effort it would take to modify the parser to accept keyword notation like Smalltalk and Self?
No; it is impossible. Doing so would completely ruin the homoiconic nature of the language, which is relied upon pretty heavily, when you think about it. What is (a b c d) in Lisp is a(b, c, d) in Io. In fact, in Io, a plain set of parentheses is taken to be merely an invokation of the "" method (yes, that's right -- an empty string. And, yes, you can override the "" method!).
None of these traits of Io rule out keyword arguments. ArrLanguage (which shares every trait named, such as homoiconicity, the way that arguments are really lazily-evaluated FEXPRs, the fact that "()" is just an invocation of the "(" function with no arguments, etc) just uses cons cells with CAR, CDR and TAG, instead of just CAR and CDR. The tag points to a symbol, and is used as the optional name in keyword calls.
And without modifying the runtime you could do keyword args the way other Lisps built out of cons cells do, by having LAMBDA be a macro that injects keyword arg handling over a primitive LAMBDA*.
Regarding the syntax: there's serious talk about rewriting the parser so that Io provides a single, simple syntax with no bells or whistles (which would logically have to look like the current syntax), and then one or more subsidiary syntaxes for people who want to use things like assignment but who don't want to write it in the form of a message :-). It's a worthy task, and not considered enormously hard, but there are SO very many worthy tasks that it hasn't been tackled yet.
Io does include support for an objective-C syntax (square brackets), but it's buggy, and the general consensus is that it's not worth fixing until we have our unified mini-syntax.
I learned many things from IoLanguage. I feel IoLanguage can not only help me expressing my ideas comfortably, but also can help me find out and learn new things. Now my programming style has changed even when programming in java -- where I might have considered making a few classes, now I consider composing some objects instead. --JuneKim
It’s too bad Io has an implicit non-overridable “asBoolean” method in the Object base class. That’s a mistake… the same one Ruby and Perl made. Only Smalltalk gets that right.
it’d be ok if I could at least override “asBoolean” for my classes as far as ifTrue: and ifFalse: are concerned, but no. Io has its own idea, and that’s that. And I can’t even get it to throw a “must be boolean” error instead. Sigh. So close, and yet so far away. -- RandalSchwartz
Hi Randal - I'm very much a novice Io coder, having known about it for maybe 4 hours now - but, does this address some of the concern? An idea, more than anything:
# In this case, I want my if to treat the booleanness based on an object's my_if_bool slot. MyBoolTrue? := Object clone MyBoolTrue? my_if_bool := true MyBoolFalse? := Object clone MyBoolFalse? my_if_bool := false # Tests a given if method. test_ifs := method(if, if(MyBoolTrue?, writeln("MyBoolTrue?: true (OK)"), writeln("MyBoolTrue?: false (!!)")) if(MyBoolFalse?, writeln("MyBoolFalse?: true (!!)"), writeln("MyBoolFalse?: false (OK)")) ) # Current if does what? writeln("Before changes: ") test_ifs(getSlot("if")) # Capture the old real if, and get to work. realIf := getSlot("if") if := method(cond, realIf(cond hasSlot("my_if_bool"), cond := cond my_if_bool) realIf(cond, call evalArgAt(1), call evalArgAt(2) ) ) # Now what? writeln("After changes: ") test_ifs(getSlot("if"))Happily, we now get:
Before changes: MyBoolTrue?: true (OK) MyBoolFalse?: true (!!) After changes: MyBoolTrue?: true (OK) MyBoolFalse?: false (OK)Maybe worth a look? :-) --ArlenCuss?
Addendum: similarly, you can redefine the behaviour of isTrue and isFalse per object if you desire.