lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Alexander Gladysh wrote:
[...]
At first it was quite hard to write code in Lua — without compile time
validation, without static types, it felt as if I try to stand on a
blob of wobbly jelly instead of a good solid rock.

I like dynamic languages. I also like static languages. They're good at different things --- some problems that are hard in static languages are very easy in dynamic languages, while some problems that are hard in dynamic languages are very easy in static languages.

So I was fascinated to discover this recently:

http://www.strongtalk.org/

It's a Smalltalk with optional strong typing.

What this means is that if you want it to behave like a dynamic language with duck typing ('if it quacks like a duck, let's just assume it is one'), you can --- and if you want strong typing ('only DNA checked ducks are allowed in the bulding') you can.

You can write code like:

| o |
   o := self getSomeObjectOfUnknownType.
   o callMethodOnObject

...and it will work, regardless of what class o is. OTOH, if you know in advance that o is going to conform to a particular interface, you can say:

| o <MyInterface> |
   o := self getSomeObjectOfUnknownType.
   o callMethodOnObject

...and now the compiler will produce an error if callMethodOnObject isn't applicable to a MyInterface object, or if getSomeObjectOfUnknownType returns an object of an incompatible type.

Here's an introduction to how the type system works:

http://www.bracha.org/nwst.html

The type system is rich and supports things like parameterised types. For example, there's a Smalltalk method collect: which runs a callback for every item in a Collection and produces a new Collection of the values the callback returns. In Strongtalk this is typed like this:

collect: <[T, ^X]> ^<Collection[X]>

That is, the first parameter to the method is a block (callback) that takes as argument an object of type T and returns an object of type X; the result of the method is a Collection of X.

Since a string is a Collection, I can do:

'abcde' collect: [ :c <Character> | c asciiValue ]

...which returns a Collection<Integer>. Or I can do:

'abcde' collect: [ :c <Character> | (c asciiValue + 1) toCharacter ]

...which returns a Collection<Character> (which, if I remember my Smalltalk correctly, is equivalent to a String).

And of course you get to use all of Smalltalk's excellent dynamic features. The type system is orthogonal to the actual implementations of the methods. In Smalltalk it's trivial to create proxy objects, for example, where I can intercept any method send in code and do what I like with them. So I can, for example, create a proxy object that is an implementation of MyInterface that actually does RPC calls to a remote MyInterface, and it's a drop-in replacement without needing any of the factory framework that, say, Java needs. Not to mention all of Smalltalk's traditional incremental development goodness.

But since the type system is *optional*, you don't have to worry about it if you don't want to. The compiler will seamlessly integrate untyped code into typed code. If you like, you can write an untyped library and bolt on a trivial typed API definition and your users will get type checking... or if you don't want to, it'll still work.

And if that's not enough, Strongtalk has a truly excellent JIT, producing some of the fastest code ever seen in a Smalltalk; most of the Strongtalk team went on to make V8, of which I'm sure you've heard!

Alas, Strongtalk is largely unknown because it was stalled in legal hell for a long time, and was only recently open sourced. But it's now all available under a BSD license, both the VM and the class library. Alas, because development has been so slow it's decidedly Old School and mostly only works on ix86 Win32. There is some support for Linux, and I believe you can run the VM headless on it, but if you're not an ix86 user I suspect you're out of luck.

--
┌─── dg@cowlark.com ───── http://www.cowlark.com ─────
│
│ "They laughed at Newton. They laughed at Einstein. Of course, they
│ also laughed at Bozo the Clown." --- Carl Sagan