Have a look at Io.

What do you want to see in Armagetron soon? Any new feature ideas? Let's ponder these ground breaking ideas...
User avatar
Z-Man
God & Project Admin
Posts: 11710
Joined: Sun Jan 23, 2005 6:01 pm
Location: Cologne
Contact:

Have a look at Io.

Post by Z-Man »

One of the hot candidates for scripting in AA is Io. Nobody but Nemostultae and me so far seems to have had a look at it, so I'd ask you to do it now. The Io website is http://www.iolanguage.com , you can find the manual, a small tutorial and sample code there, as well as a not very complete reference. One of the drawbacks of Io is that there have been no releases yet, it's all just one continuous darcs archive. A guaranteed to work (well, for the bits I have touched) snapshot is attached to this post. I stripped the Flux addon that would have more than doubled the download size. Just untar it (it's really bzipped) and run "make; make install" in the created directory, it will install into /usr/local.

The plan would be to fully embed it into our source so it is not added to our runtime or compile time dependencies. It's small enough to justify that. We'd strip more addons, of course; the core source is about 250 kb bzipped. Lua would be smaller than that, but it seems to be harder to wrap C++ objects in Lua.

A goal of adding scripting to AA would be that everyone, including as of yet non-programmers, should be able to change simple things in the behavior of game objects. We currently have no TnA around to test Io's beginner appeal, so would one of the listening players without or with little programming experience volunteer for testing? We'll try to hold your hand while you do, and see what docs we can write to help those that follow you.

A simple minded introduction to Io follows. It assumes you are using the interactive mode of Io so that results are printed right away; in a script file, you'll have to occasionally enclose the given code in a writeln(...).

1. Variables, assignments and expressions

Io knows about numbers and can do calculations:

Code: Select all

Io> 1+1
==> 2
The syntax is just like on a regular calculator, including parentheses:

Code: Select all

Io> (2+2)*3
==> 12
Io> 4 sqrt
==> 2
Some math functions take parameters, those have to come in parentheses. 2 to the power of 5 is

Code: Select all

Io> 2 pow(5)
==> 32
(The seemingly natural operator ^ is, as in many languages, reserved for bitwise exclusive or.)
You can assign results of calculations to variables for later use. If you want to define a new variable, you use the := operator; for overwriting an already set variable, you can use the = operator.

Code: Select all

Io> pi := 0 acos * 2
==> 3.141593
Io> pi * 2
==> 6.283185
Io> x := 0
==> 0
Io> x = 1
==> 1
Io> y = 2
  Exception: Slot y not found. Must define slot using := operator before updating.
==> nil
The last line demonstrates what happens if you use the = operator on a not-yet existing variable; it fails. You should use = whenever you want to overwrite a variable, the error protects you from typos. The error message talks about a thing called "slot"; that's Io's term for what we've been calling variables here.

2. Functions

Repeatedly used pieces of code can be put into functions so they don't have to be typed every time. A function is defined like this:

Code: Select all

Io> f := method(t, t - t * t)
==> method(t, t -(t *(t)))
The declaration has to be read as "f is a function that maps t to t - t * t". Note: "t * t" is usually faster than the equivalent "t pow(2)". In the output, you see the implicit parentheses Io adds to the function body. You can use the function you just defined just like you learned in math:

Code: Select all

Io> f(0)
==> 0
Io> f(1)
==> 0
Io> f(2)
==> -2
What this does is: the argument of f was called t internally. If you write f(2), A local variable, invisible outside of the function, called t is created and assigned the value 2. Then, the function body is evaluated, the result is returned (you can use it like any other number, i.e. write "f(2) + 6" and get 4) after the local variable t is eliminated. You'll find no trace of t outside of the function. Any variable called t existing outside of the function is a different variable from the t inside the function.
Functions can have any number of arguments, including zero. The general syntax is "method(arg1, arg2, ..., argn, body) where arg1 to argn are the arguments and body the expression(s) you want to evaluate on these arguments.
Keen minds will have noticed that a function with zero arguments doesn't sound all that useful. All it can do is return a constant value, right? No arguments, no meaningful calculation. Well, not quite: in the function body, you have access to variables defined earlier (or later):

Code: Select all

Io> x := 2
==> 2
Io> y := 3
==> 3
Io> f := method(x*y)
==> method(x *(y))
Io> f()
==> 6
Io> x = 3
==> 3
Io> f()
==> 9
Functions with zero arguments can also be invoked without the parentheses. "f" instead of "f()" would have worked just as well.
You can write arbitrary commands inside a function body. You can define variables, use them, define new functions, whatever you want. If it is legal outside of a function, it is legal inside. The one thing you need to know is that all variable definitions in the function body are local; that means that, just like the parameter t in our first function, they will vanish once the function exits. They won't be restored on the next usage of the function either; they're gone.

----

This is getting too simple minded for a post in the development subforum :) I'll continue and expand this on the wiki later. Nemo: I'll tell the reader where I lied further down in the text, don't worry :)

The four small drawbacks I see with Io:
- No release, we'll have to freeze the darcs repository ourselves and pull bugfixing patches
- The official documentation is pretty thin
- It's bigger than Lua both in code size and binary size
- It's purely OO, meaning it may be hard to pick up. But note that my introduction attempt above doesn't use the word "Object" once and pretends that Io is a procedural language. I think that for the simple customization tasks in AA, the ones that can be done with functions alone, we can keep up that illusion.
- I really would prefer sin(2) over 2 sin. Of course, "Object sin := method( x, x sin )" fixes that :)

Edit: updated attachment to fix the bug reported by wrtl.
Attachments
Io-20061114.tar.bz.not.zip
Io snapshot
(1.72 MiB) Downloaded 244 times
Last edited by Z-Man on Fri Dec 08, 2006 7:01 pm, edited 1 time in total.
User avatar
ed
Match Winner
Posts: 613
Joined: Mon Feb 13, 2006 12:34 pm
Location: UK

Re: Have a look at Io.

Post by ed »

z-man wrote:so would one of the listening players without or with little programming experience volunteer for testing?
Well, I can write simple scripts using bash, perl or php. That's about the limit of my programming abilities.
And I've set up a few crazy servers in my time. If you'd like me to help test it I'd be happy to give it a go.
User avatar
Tank Program
Forum & Project Admin, PhD
Posts: 6712
Joined: Thu Dec 18, 2003 7:03 pm

Post by Tank Program »

Looks simple enough.
Image
User avatar
wrtlprnft
Reverse Outside Corner Grinder
Posts: 1679
Joined: Wed Jan 04, 2006 4:42 am
Location: 0x08048000
Contact:

Post by wrtlprnft »

I'll be giving it a try this evening. I didn't try before because I had no idea if it worked and how much it did and all. The language itself sounds interesting :)
There's no place like ::1
User avatar
wrtlprnft
Reverse Outside Corner Grinder
Posts: 1679
Joined: Wed Jan 04, 2006 4:42 am
Location: 0x08048000
Contact:

Post by wrtlprnft »

Addition (sorry for the double post):
The Makefile wants to install to /home/moos/usr, so you need to change that if your username's not moos (and/or you don't want to install into that dir) :P

Edit: Is the stuff in private/z-man/clio supposed to be usuable already? It doesn't compile for me.
There's no place like ::1
User avatar
Z-Man
God & Project Admin
Posts: 11710
Joined: Sun Jan 23, 2005 6:01 pm
Location: Cologne
Contact:

Post by Z-Man »

Whoops, corrected that in the tarball. I also added the installation of headers into PREFIX/include/io. That's what the stuff in z-man/private (yes, it should work then) expects, and the original "make install" just keeps the headers for itself.
User avatar
ed
Match Winner
Posts: 613
Joined: Mon Feb 13, 2006 12:34 pm
Location: UK

Post by ed »

ok, I ran the make; make install, when I ran io I got:

Code: Select all

root@ubuntu64:/usr/local# io
io: error while loading shared libraries: libiovmall.so: cannot open shared object file: No such file or directory
I googled this and it seemed to be a common problem on *nix systems. Some helpful chap suggested:

Code: Select all

I assume you're on Linux since it's the only platform braindead  
enough to not cache standard lib dirs on bootup. Edit your /etc/
ld.so.conf and add /usr/local/lib to it, then run "ldconfig". "io"  
should work then. 
I did this. I now get:

Code: Select all

root@ubuntu64:/home/ed# io
Segmentation fault
Saying that, someone said io_static worked fine. So I tried that and it does.
All your examples work as intended. I will have a proper play with it when I get time.
User avatar
wrtlprnft
Reverse Outside Corner Grinder
Posts: 1679
Joined: Wed Jan 04, 2006 4:42 am
Location: 0x08048000
Contact:

Post by wrtlprnft »

Wow, the more I look at the examples the more beautiful I think it is… Who needs four kinds of brackets if you can just implement if as a method?
It seems to be able to all kinds of “system” stuff, including file and net access and opengl. Of course, those should only be enabled on the serverside or for scripts the user installed manually or that are distributed with the game.

I'd have preferred the classical dot syntax, but well, I can live with the dots missing. Now I also understand the point of “42 sqrt” instead of “42 sqrt”—you're calling the sqrt method of 42. Would have been more obvious if it had been “42.sqrt()”, though (and you can actually put the brackets).
There's no place like ::1
Luke-Jr
Dr Z Level
Posts: 2246
Joined: Sun Mar 20, 2005 4:03 pm
Location: IM: luke@dashjr.org

Post by Luke-Jr »

Note it's still scripting, though, so still requires a programmer, though being a higher level language it doesn't need an as experienced programmer. The method syntax seems a bit awkward and non-intuitional to me...

Just comments, as far as scripting support goes, I think we should provide compatibility with as many languages as possible, provided they all remain optional.

Though IMO, I'd prefer a dependency over embedding code, especially when we're likely to want future features of the language as well...
User avatar
Z-Man
God & Project Admin
Posts: 11710
Joined: Sun Jan 23, 2005 6:01 pm
Location: Cologne
Contact:

Post by Z-Man »

I prefer supporting a single scripting language and doing it right. There are so many possile quirks with each language that it's highly notrivial to add support for each. Memory management alone is a tough topic. And then there is the N^2 problem of accessing a game object from several scripting languages simultaneously. Put it another way: one scripting language may be as many as possible :) Also, with many optional languages, we'd never get downloadable code. Ever. Nobody would know what the client supports as a language.

The same problem comes if we don't embed that single language in our own source: new language features from later versions may be fine, but what good are they if you can't use them in your script because you don't know whether the other side supports them? Again, it's the only way to get downloadable code.

Of course, downloadable code isn't a must, and this thread isn't actually supposed to be about embedding Io vs any other language. It's just the "have a look at Io, it's our best ticket to consistent scripting for everyone" thread.
meriton
Round Winner
Posts: 256
Joined: Sun Nov 20, 2005 3:33 am

Post by meriton »

I have skimmed the documentation on the site, but I don't have time to actually try out Io, so the following is merely a first assessment.

Io is very flexible, for instance due to argument passing by expression. This permits a by far more reflective kind of programming that possible in older languages such as Java. Of course, I am not sure we'll actually need this kind of flexiblity in this application.

Another thing contributing to the flexibility is the "type system" (I put it in quotes because I was unable to find the definition of type safety it ensures, and I doubt whether I'd call it a type system, too), that realizes dynamic inheritance (i.e. it is possible to add a method to a super"class" after it has been instantiated).

In terms of syntax, Io is novel in some respects, but the syntax appears logical and clear. However, it is largely distinct from any programming language I know, so learning does require quite some effort.

To conclude my high-level assessment, I can't help but quote:
All [lanuages] are dynamically typed except Java which is statically (uses type declarations) typed (this makes Java less flexible in terms of being able to quickly add features to existing code).
That is entirely true, but this very restriction also permits the Java compiler to verify type safety, and immensely simplifies providing context assist in an IDE. By consequence, the compiler will run by far less integrity checks on Io code. For instance, even trying to access a non-present member of an object (for instance due to a typo) will not be caught be the compiler (or at script load time), but only when this expression is about to be evaluated. Now if this expression is in a rarely used branch ... you get the picture. Therefore, I wouldn't want to write complex scripts in Io, but for our use, Io appears a good choice.
User avatar
Z-Man
God & Project Admin
Posts: 11710
Joined: Sun Jan 23, 2005 6:01 pm
Location: Cologne
Contact:

Post by Z-Man »

Yeah, that's the old static vs. dynamic typing debate. Usually, proponents of dynamic typing bring forward two main arguments why you shouldn't worry too much about type errors:
- Type errors are only a very small portion of the errors that can happen in a program
- Type errors can just as well prevented by thorough unit tests with good code coverage which you should do anyway
Weak typing, or "duck typing", has two advantages over strong typing:
- it's easier, especially for beginners. It's one less annoying obstacle in your way. You don't care what objects you put into that array, so why should your computer let you only put in objects of a single type and specify that type in advance?
- it allows to write generic code. That function SHOULD work on all numeric types out of the box. Why do you have to write it several times (or use templates in C++) for ints, floats, doubles and complex numbers? It shouldn't matter to your computer, as long as a * b + c has a meaning.

Our additional argument is that our core language, C++, uses strong type checking, so there is little point in picking a scripting language that does that, too. I think there is consesus on that point :)
Luke-Jr
Dr Z Level
Posts: 2246
Joined: Sun Mar 20, 2005 4:03 pm
Location: IM: luke@dashjr.org

Post by Luke-Jr »

z-man wrote:I prefer supporting a single scripting language and doing it right. There are so many possile quirks with each language that it's highly notrivial to add support for each. Memory management alone is a tough topic.
A common interface should make it trivial.
z-man wrote:Also, with many optional languages, we'd never get downloadable code. Ever. Nobody would know what the client supports as a language.
Since scripting will be optional, it's not a big deal if the client doesn't understand the language. If your client can't handle it (scripting disabled, or that language unsupported), you're limited to simple vValue-based predictions (which should be plenty good enough for playing, provided the script on the server is properly writ).
z-man wrote:The same problem comes if we don't embed that single language in our own source: new language features from later versions may be fine, but what good are they if you can't use them in your script because you don't know whether the other side supports them? Again, it's the only way to get downloadable code.
Scripts would need a way to depend on a specific version.
meriton
Round Winner
Posts: 256
Joined: Sun Nov 20, 2005 3:33 am

Post by meriton »

As I wrote above, that "old dynamic vs. static typing debate" is largely irrelevant for our use of the language, but since you've argued your point, I take the liberty to argue mine as well: ;)

There is no doubt that declaring static types all over the place entails work both when reading and writing code. Personally, I think it excessive to declare types for local variables, for instance. However, declaring types for global variables can be used to document interfaces in a machine-checkable manner, which is useful, because wrong use of interfaces need not result in immediate failure of the system.

The chief advantage of static typing is that it permits much better tool support. Static typing permits Context Assist, source code analysis features such as call graphs, and various refactorings. For instance, assume there are methods Thread::Initialize and List::Initialize, and you'd like to refactor the latter to List::InitializeEmpty. Then, the IDE will need static type information to tell which method invocations need to be renamed.

For these reasons, I contest the claim of certain scripting enthusiasts that static typing is useless. This may be the case for their typical projects, but certainly not for all projects out there. Static typing can be a neccessary burden or a pointless one, it depends on the kind of project you use it for.

PS: Strong typing doesn't prevent genericity; if a common super type is present, you can express the algorithm for that super type.
User avatar
dlh
Formerly That OS X Guy
Posts: 2035
Joined: Fri Jan 02, 2004 12:05 am
Contact:

Post by dlh »

meriton wrote:The chief advantage of static typing is that it permits much better tool support.
Dynamic languages can have great tool support too — look at Smalltalk, which has arguably better tool support than C++ or Java.
Post Reply