Io Has A Very Clean Mirror
The best languages are deceptively simple. Io has an incredibly brief grammar, so it’s easy to think you’ve learned everything with one short perusal. And the manual is quite short, too, isn’t it? Nothing to it, right?
Io is just an incredibly hushed secret. (Perhaps because it is impossible to Google stuff about it.) Did you know that Io’s introspection and meta tricks put Ruby to serious shame? Where Ruby once schooled Java, Io has now pogoed.
Here, let’s start with a simple block:
Io> plus := block(a, b, a + b)
==> method(a, b,
a + b
)
Io> plus call(2, 3)
==> 5
Okay, so the block works. The plus
block added two numbers.
Now let’s do some introspection on this little fellow.
Io> plus argumentNames
==> list("a", "b")
Io> plus code
==> block(a, b, a +(b))
Io> plus message name
==> a
Io> plus message next
==> +(b)
Io> plus message next name
==> +
Hot holy cold mold. Not only can you get the names of the block params. And not only can you get a string of the block’s complete source code. You can sneak into the code and traverse the messages inside. And most amazing of all: it’s awfully easy and natural. True to Io’s quest. Ruby’s mirror can’t see any of that.
But, whoa whoa, hey now, don’t touch that dial.
Io> plus message next setName("-")
==> -(b)
Io> plus
==> method(a, b,
a - b
)
Io> plus call(2, 3)
==> -1
Gunpowder and treason! Now THAT is a monkeypatch to the viscera. Subtraction is in effect.
See, I first had Io pegged as a Python. Simple rules, very strict, few sigils, very little sugar, both adhering strongly to their own manifestos. No way, though. Python keeps trying to shed its functional skin, only to reveal its acid wash jeans underneath. Ironed and starched and pegged.
Io pays obeisance to minimalism, but somehow cracks the door open on a wild and uncouth gymnasium of meta magic. And it goes so much deeper than these examples. I don’t know if Io is trying to be rebellious, but its malleability goes far beyond Ruby. And, I’d say it goes beyond Smalltalk and Self and Lisp, since it makes this kind of ripping and tearing completely effortless.
Now begin the comments …
alex
The way concurrency works in io is fun for making little prototypes (pun intended!)
Danno
IO is pretty amazing. You’d probably also like Factor.
AkitaOnRails
Wow, you’re right (and as a plus, it uses Git as its repository, great). And you’re right. It is not easy to find good info about Io from Google. I would love to see a minimalist Poignant Guide to Io from you! :-)
Brian Mitchell
Indeed. Io has been a stage to some of the craziest meta-programming I’ve seen anywhere. It has come a long way since its earlier debuts years ago… so I’d encourage people to check out the source and join conversation with the community. There are some exciting developments so now would be a good time to dive in.
Mod Serf
I, for one, bow to my new Io overlords.
zimbatm
I’m scared. The universe is loosing is bounds and start to fibble away in a meta fashion style. What you just showed are simple operations with an enormously complicated potential.
ReFLect
You might like to check out the ReFLect language. Equivalent code is
let plus = {| \a.\b.a+b |};
let change2minus {| \`s.\`t.`p `q `r |} = {| \`s. \`t. `q–`r |};
eval {| `(change2minus plus) 2 3 |};
: {|–1 |}
\x.E is a lambda expression. Quotes such as `s stand in for pattern matching within a term. So {| \`s.\`t.\`p `q `r |} matches any function with two arguments that consists of a function application with two arguments–s and t are the outer arguments, and p is the inner function being applied (in this case, +).
In essense, reflect makes tearing apart code even easier, because you can pattern match code expressions.
Max Battcher
I think a Lisp hacker would give you a “young whippersnapper” lesson and explain properly how all of that is possible in Lisp, particularly if you were one of the few to use a Lisp Machine in that amazing era of dinosaurs. Io simply takes that sauce and places it entirely within a minimalist OO goodness ala Self and that’s probably the biggest reason it seems different from the Lisp way of doing this sort of thing in that the message tree looks like a nice collection of objects to those of us long schooled in the ways of OO. Io’s a good language and something that I like returning to once in a while as a damn pretty sandbox. I don’t think it is rebelliousness, only a deep respect for the history of languages (Steve seems to have a great knowledge of this) and a wish to do something like classic Lisp or Self in the form factor of Lua more than anything.
PS, don’t be hating on my jeans… they are quite pragmatic for working in.
tesing 123
this is a test!
sb
Damn it, I just had my first apocalyptic vision in 3 years. People really really can’t be trusted with this kind of power, okay? As you gaze into the mirror, the mirror also gazes into you. Turn back while you still can!
sb
(I almost forgot, insert bad joke here about how replacing the math operators is already affecting the comment system. Don’t say I didn’t warn you, is all I’m saying.)
tester
testing is stupid!
Test with Yahoo!
arthur
However, let’s not forget a few weak points currently on Io (and I will only mention things which can be improved)
–Makefile based compilation only (gnu autoconfigure at least provides a “fine tuning”).
–Windows binaries lag behind. It is more than a half year now, where one ultimately wonders how much attention Io gets on non-mac plattforms.
–Documentation. The documentation is partially ok–but partially it is simply not existing, where one is to be expected to look at the source.
I am sure the two first points can easily be solved, but the third one is one that had Ruby troubled for a long time until the Pickaxe book emerged.
But where is a Pickaxe-for-Io?
_why
Akita: Perhaps we could give Io an informal moniker (such as: Schneider) which could be more easily distinguished by the robots.
ReFLect: Oh, good show. Any other codes from the crowd are welcome.
language_nazi
To “peruse” means to “read through with thoroughness or care.”
jer
Arthur: I have been working for quite a while on an “Io Tome”. It exists mostly in my head at the moment, due to other projects coming up. One of these days I’ll have enough time to sit down and work out a draft which other people can refine. Documentation does sorely lack behind in Io right now.
As far as Windows support goes, that is remarkably good considering none of the core contributors use windows as a platform, and we only ever see fading interest in Io running ontop of windows. Perhaps if there was more interest from the user base, it would improve, and that would be nice to see!
The build system is a source of huge contention. We all tend to agree that autotools isn’t exactly the best thing out there, where we deviate (at least myself and Steve Dekorte) is that it’s a better system than what we have right now, less fragile. He’s not against using it, someone just needs to come forth with a patchset demonstrating its usefulness, and he’ll consider it (at least, this was his position a year ago when I last discussed it with him—then I started a new job and have had no time since).
In any event, Io is an extremely young language, with some quirks and gotchas. Overall, it has great potential however.
serhei
Holy crap your comments section just imploded.
Pupeno
It’d be nice if you added more step-by-step explanations of the code snippets, for those of us who never touched Io. It looks very interesting.
AndrewO
Tip for Googling: search for “Io language”. Slightly fewer results about I/O and a lot fewer about the Jovian moon and Greek mythology.
jer
Pupeno: I’ll explain the code steps one by one.
This line of code assigns a lexically scoped method (or block) that takes two formal parameters, a and b, and adds those two parameters returning the result, to the method “plus”. That is to say, it assigns that block to plus, calling plus will return the results if given two arguments.
Unlike in some other languages, blocks do not automatically activate like methods or functions do. In Io, you must explicitly “call” a block. This line of code activates the block in the “plus” slot (think "variable") with two arguments, 2 and 3, returning the expected result “5”.
Here we ask the block for the names of the formal parameters. It returns a list of items in string representation.
This line of code asks the interpreter for the code representing the entire method. Appending a “;” message to the string returned here can cause your method to be serializable.
This line of code asks the interpreter for the message object of the body of the method (in Io by convention, the body of a control structure is always the last argument passed in, usually implicitly, since methods and blocks in Io can accept any number of arguments, it’ll just ignore the ones not used in the body) then it asks for the string representation of the first item in that message tree, in this case, the string “a”.
Like the above, but instead of asking for the name of the message, we ask for the object representing the next message in the body of the block (the “+” method with the argument "b").
Like above, but we ask for the message object, then skip to the next message in that tree, and ask for its name, in this case “+”.
The other examples are pretty easy to decipher, “set” methods just set the value of the objects I listed above.
So if you think of messages in Io as a simple tree (which is essentially, what they are when you include arguments), then “next” is like skipping down the left side of the tree, and arguments are like skipping down the right side of the tree. Each node in this tree has several pieces of state and behaviour that you can ask about.
jer
Grr, sorry about the crappy formatting folks. I’d edit it if I could.
_why
There you are. Very generous, jer. Interesting about the semicolon message. I’ve been running into that alot but hadn’t stopped to look at it.
Arrogant
As soon as I get my MacBook I plan to jump wholeheartedly back into the Io game. I love me some Io.
jer
Thanks for fixing up the formatting _why, should use Preview next time first. :)
I should make one more note about serialization. Not everything is serializable at the present time in Io. For instance, CFunction objects (that is, for instance, “clone” on the Object method (and as a result, all objects respond to it unless you get into some bit of magic, which I won’t describe here)) do not know about their source code. They could, but it’d involve modifying the source before it’s compiled, which is not only silly, it’s superfluous. Many methods in Io respond to the “serialized” method which returns a string representation of the receiver of that message, which is extremely handy in many cases. For instance:
bug
Ya, Io is fun stuff. Now it just needs to get its feet wet in the coder pool (& vice versa). Ruby is only the cool kid now because he has a smooth library and a killer app. Coding Io might become the next “elegant programming” fashion statement.
thisAintMath_itsHistory
Smalltalk = Simula.messaging + AlanKay.inspiration
Ruby = the_good_bits_of(Perl + Python) + some_of(Smalltalk)
Io = the_rest_of(Smalltalk) + Ruby
Rich
Working with Io on Windows every day. I have a bunch of Windows patches that I need to submit when I get a chance. If anyone has any windows questions, feel free to ask.
richcollins@gmail.com
crabby from a cold
This is supposed to be elegant? I hate to say it, but even “public static void” looks more parseable.
bug
crabby: Why’s example is pretty contrived, but the idea is that the better you can reflect onto the language itself (although not completely, as per Gödel), the DRYer your code can get. Elegance doesn’t have to do with appearances, necessarily. From Wikipedia, “elegance is the attribute of being impressively effective, yet slighty simplistic.” Lisp is considered by some to be elegant, although on a functional level, as opposed to OO, but few would call its syntax pretty.
Of course, you could always make your own keywords:
jer
Not exactly “re-opening” as they’re never closed, but anyway, you can do something like this (keeping in mind, newSlot is similar to attr_accessor in Ruby):
Erm
Anyone managed to build Io on OSX using macports (Io-2007-03-21.tar.gz)?
jer
2007-03-21 is historic. I would highly recommend you grab the new tarball pushed out last night from www.iolanguage.com or download the git repository and build from that.
mechazoidal
If you’re not averse to rolling up your sleeves, you can take the existing Io Portfile and add the latest tarball location+md5 hashes to it to get the latest nightly build. I would, however, check your compile environment first as I’ve never gotten build errors like that on up-to-date machines.
Erm
Thanks jer…that did the trick. Now to explore…
tripdragon
so… are you leaving ruby ? just curious what this really is on top of things
bug
tripdragon: What? Ruby’s not dead, and Io isn’t super cool yet. It doesn’t even have hashes! We can still play with it, though.
_why
bug: Internet communities are like moving flotillas. And, once you’ve chained up, they like to know when you come and go. Many dads don’t like the screen door left ajar.
Many Dads
Speaking of doors and what they like. Will you be at SXSW, perhaps riding a mandolin pony, question.
The power of Assembler
In the 60’s and 70’s, power coders would use assembler to get the most out of those old microcontrollers masquerading as mainframes. A primary technique was self-modifying code to avoid re-executing conditionals.
By and by, it turned out that, in large systems, self-modifying code was effectively impossible to debug. It’s a method for hiding bugs. Slowly, it was banned.
Yeah, things aren’t exactly the same, but there are similarities. If my money were resting on the outcome, I’d limit self-modification in some ways, perhaps to boot-time self modding. That way it is at least possible to view a listing of the code that is executing.
If you think about testing, code coverage, provability, auditing, code reviews, and debugging, you’ll see what I mean.
There’s clearly an area for this. Self-modding might be a good base for grad students to quickly generate new languages from Io, in order to experiment with a new or different programming paradigm. And new DSL’s.
But people tend to guess that by trimming the code at run-time you can improve performance. Yeah, to an extent, but self-modding interpreters have never beat straight C for performance. Any interpreted language with ‘eval’ can pull a more-or-less equivalent trick. And we’ve learned to limit that.
Even simple mods like updating DLL’s has been shown to be problematic—the user is running a codebase that is different from the code that was tested. Search for ‘dll hell’ for further info.
Katie
tumble
Reflection is not just about self-modding, thank goodness. For more on what’s so great about reflection, look up how it’s used by Smalltalk (and probably also LISP, Ruby etc.).
jer
A language need not limit self modifying code. Convention should limit it to very few areas. This feature demonstrated in this post is used sparingly (mostly in control structures) in Io, but yes, it is used.
A language should not impose itself on the programmer. The whole idea is that the programmer imposes himself on the language. Keeping your language as flexible as you need it to be allows you to not only make mistakes and learn from them in a practical manner, by for instance, hard to find bugs; but also learn new techniques that other languages may or may not expose to you.
I find it a win-win opportunity, though I know some folks who have played with Io have run away screaming at this very feature (mostly those who did, ran straight to Haskell =]).
Comments are closed for this entry.