- Event Loop Built-in event loop serviced by a thread pool with a fixed number of threads. Threads never block.
- Dynamic Eddon is duck-typed and late-bound. All blocks & control structures are first class objects. if/while/select are methods passed to objects. This means you can change the conditions or branches of your logic at run-time rather than constantly testing state variables.
- LogicNodes A LogicNode is an object (usually built by the compiler) that holds a test condition and the branches for the condition (so you don't have to pass them as arguments at run-time, but can still modify them). It tests or compares and follows simple branches with nulls and exceptions caught via named branches. It can perform select/case operations. It can test if objects are contained within each other.
- Exceptions Exception handlers can be set by simply setting the 'error:' argument of any method call. The run-time will catch it. This includes undoing held locks if set with the 'lock:' argument or unlocked in an exit clause
- Parallel Easily send messages to objects in parallel, thread loops automatically, or process queues (using Unix pipe operations) that pass data between tasks. There is no boiler plate and no need to specifically create new threads. Any method that works on an array or could return an array can supports concurrent operation and an 'each:' argument saying what to do with the results.
- No Variables What?! The definition is changed such that a variable is no longer a fixed memory location with a fixed type, but rather a key looked up in some other object. The type belongs to the object found. Imagine an sql query that returns a database row as an object with the column names as instances, then use 'with:' to pass the entire row such that the called method sees each column as the local variables. Compare with the complexity of "array adaptors"!
- Notify Data change notification is built in
- Pre-Execution The compiler executes part of your code immediately after compilation to build the network of objects that becomes your program. You can do just about anything including the building of complex objects so that you don't have to do it at at run-time. Subclassing is actually done via a 'subclass' method call, not with special syntax. Compare to systems that use special syntax and/or a separate XML system and/or require lengthly initialization boilerplate run at every program start. Labels ("verb"-last method calls to a literal) are sent at compile-time allowing you to easily support new types in a portable way or do data conversions, etc.
- Method Chains An odd feature, but when you chain multiple methods, you give a single argument list. All arguments are passed to the entire chain, sharing the same execution context. Earlier methods may pass new arguments down the chain simply by setting "local" variables, or the method can verify and/or modify variables being passed down the chain.
- Active Objects You find data in an object by its name, as a method call. There is no difference between accessing an attribute (contained variable) and a method (contained code). You can replace the attribute with code by overriding it in a subclass without changing code that accesses it. This doesn't break encapsulation, in fact, it enforces it. You set attributes with a 'set' method which allows you to set multiple attributes all at once. Containers have an additional data storage area that can be accessed by index rather than by key (although, you can use a key as well since almost all containers are sparse). The index area does not execute methods if you place code in it.
- Auto-translate Strings are placed into a table indexed by a hashkey formed from the string. If it finds a translated version, it will use it. Basically, all the benfits of an external string table, but you don't have to maintain it. Just use regular old double quoted strings in your code.
- Feature Rich Continuations, Prototyping, Protocols, Closures, Bit-Vectors, realSets (uses a bitmap of included objects), Ranges, references, soft references, MetaClasses, a dynamic/portable C compiler built-in, and all sorts of other features are supported with basically no syntax beyond which brace is which. Consistency has been key!
default world value:"World" writeln format "Hello, $name" name:world
The first line sets a default value for a local variable (only set if it has no value yet). The second line is a method chain. You start at the arguments and place the 'world' variable into a context under the variable 'name'. The variable to the left of the arguments (or any literal) is the direct object of the call. The method name is the first identifier to the left, 'format'. The method is found in the direct object via its 'hashkey' (actually Judy structures are used not hashtables). The next step is to find the next method to the left, 'writeln' and jump to that method using the current context, which will have the 'return value' of the previous call as the direct object and all variables already initialized.
play sound file "myfile.mp3"
Nope, not BASIC. As above, we start with the literal at the far right as there are no arguments. Passing the 'file' message to a string returns an instance representing the file. You may be used to using 'new' to create objects, but in this case, the file exists and we aren't creating a 'new' one! The 'sound' method attempts to find a sound stream within the file (files open on demand). Then passing "play" to the stream attempts to play it. It returns the event object currently playing (asynchronously) the stream so that the caller can send it messages to pause or stop.
distance = sqrt (x.^2 + y.^2)
No, not a function call. There are no functions. And the horrible Java hack of a library of math routines in an 'object' is not allowed. The above uses the power operator on two variables, adds them, then calls 'sqrt' on the result.
min (34, x, y)
A 3 valued min function? Well no. There are no functions. The 'min' method finds the minimum value in an object. The comma operator in parenthesis creates an array.