Recently by Bryan Weber
Protogrid is a dynamically typed, prototype based programming language that runs on the JVM.
It can be found on github at http://www.github.com/brweber2/protogrid
For users:
Protogrid strives to be simple to write and read. Each form is intended to mean one thing so there should not be any confusion once you become familiar with the syntax. In many ways this one to one mapping of syntax and semantics has been a simplifying and limiting factor in the design of the language. This is especially true for developers who come to protogrid with pre-conceived notions from past experience.
- There is a single keyword 'var'.
- nil, undefined, true and false are built in prototypes.
- In protogrid there is a single numeric type.
- Variable names cannot contain numbers.
- Parenthesis always indicate function application, even there is no function to apply. For example, parenthesis used for changing or specifying order of operation precedence are strictly evaluated and the resulting value is left as the current context, but no function invocation actually takes place.
- Brackets indicate a function declaration.
- Braces indicate a scoped block.
- Single = denotes assignment.
Unfortunately, there isn't much here that will excite you. Protogrid introduces virtually no new programming paradigms, it merely strives to make the developer experience more enjoyable. The current form of Java interop is not something I've seen in any other language that runs on the JVM, but it is not something new or revolutionary. It is arguably a nicer reflection API. And yes, you will cringe if you look under the hood. The implementation is insanely naive and non-performant in every aspect imaginable.
Java Interop
To start interacting with the underlying Java platform, the first step is typically to wrap a Java class.
var JavaString = WrapClass( java.lang.String )
The JavaString prototype now is a wrapped Java class. It can be used in one of two ways.
- If invoked the arguments are used to determine which constructor should be called at runtime and if successful a wrapped instance is returned.
- Accessing a slot on the wrapped class will look for a field. If one is found a wrapped field is returned. If no field is found, a wrapped methods prototype is returned that wraps all the static methods on the class with the matching name. If this wrapped methods prototype is invoked it uses the arguments passed to it to determine at runtime which specific method should be invoked and a wrapped instance is returned with the result of the invocation.
var message = JavaString.format( "Hello %s", "World!" )
There are a few points of interest here. There is more than one static format method on java.lang.String. Additionally, the String "World!" is converted to an Object[] to support the variadic version of the format method used here. A wrapped instance is a prototype that can be used with the protogrid, but that can be coerced back to its native Java type when necessary.
println( message.toUpperCase() )
What's missing from the interop story?
Quite a bit. There is currently no way to implement an interface, to extend a class or to create a new interface or class.
Show me more!
Creating a new prototype Simply clone an existing prototype
var MyProto = clone( Object )
Setting and accessing slots on the prototype is trivial
MyProto.foo = "barbaz"
println( MyProto.foo )
Inspecting the prototype
println( MyProto.slots() )
Viewing the AST
At any point, the built in ast function can be called to print out a readable form of the Abstract Syntax Tree if there is every any doubt about what the interpreter is seeing.
ast( 2 + 3 * 4 ^ 5 % 6 )
This will result in the following AST
( 2 + ( ( 3 * ( 4 ^ 5 ) ) % 6 ) )
Loading code from a file
When loading code from a file, any side effects will occur at load time and a scope object with all the top level definitions from the file will be returned. This can be assigned to a variable and values and functions can be accessed without worrying about collisions within the current scope. Suppose we have a file located at src/hello_world.grid relative to the current directory with the following content.
var sayHelloTo = [name] { println( strf( "Hello %s" List(name) ) ) }
To load this file, simply call the built in load function.
var ns = load( "src/hello_world.grid" )
ns.sayHelloTo( "Flynn" )
If you do not want to namespace any particular functions it is possible to map them into the curent scope by simply assigning them to a variable.
var sayHelloTo = ns.sayHelloTo
Operators
Math + - * / % ^
Logic && ||
Comparison == != < <= > >=
Control Flow
There are built in functions for conditionals, looping, exceptions and exception handling. Conditionals
if ( true println( "true" ) println( "false" ) )
if ( <cond><true expr> <false expr> )
Looping
loop( <structure> <function> )
The function passed to loop must have two parameters, the value for each iteration and in the index number of the iteration (zero based).
while( <condition> <block> )
Exceptions
var err = error( "Uh oh" )
raise( err )
try ( <block> <finally-block> )
But what about catching the exceptions? A try block does not return the result of the block, it returns an object that contains a boolean indicating whether or not an exception was thrown and either the exception or the resultant value. It is therefore possible to access slots on the resultant prototype to perform whatever error handling is necessary.
var t = try( socket.write() socket.close() )
if ( t.hasError raise( t.error ) t.result )
Composite Data Structures
There are lists. There is a built in function to construct them and they can contain an object of any type. Lists are zero indexed for access operations.
var names = List( "Kevin", "Sam", "Quorra" )
println( names.get( 1 ) )
Because I have to...
Hello World
println( "Hello world!" )
Factorial
var fac = [n] {
if ( n == 0 || n == 1
1
n * recur( n - 1 ) )
}
In protogrid, recursion is achieved by calling the recur function instead of the current function by name.
Getting started
The best way to get started is to download the executable protogrid jar and start experimenting with the REPL. Syntax highlighting for IntelliJ IDEA and TextMate will be added to github in the very near future.
Down the road
- Syntax highlighting
- Compiled version
- Debugger
- Static typing
- Lazy evaluation
- Macros
- Named arguments
- Default values for parameters
- Richer Java interop
- De-structuring
- Targeting other platforms
By far the most entertaining and most thought provoking presentation of the JVM language summit was given by Erik Meijer (and by a large margin). Unfortunately, it was not recorded and will not be on InfoQ like many of the other presentations as far as I know. His talk was called Fundamentalist Functional Programming which is basically his way of advocating pure functional languages (read: Haskell although he did mention Clean as well). He argued that any impure functional language is NOT a functional language. Either you are pure or you happen to have some features of functional programming languages. And he did this in a wildly entertaining manner. I've personally been looking at Haskell recently so this talk was very timely and informative. How often do you see a presentation where someone suggests that Computer Science has gone in completely the wrong direction the past 50 years and needs to get back on track and has some ammo to back it up? I think many people in the audience found it entertaining, but not really practical. To that I would ask, why not? How many times a day do you say to yourself "there must be a better way?" Maybe this would be a quantum leap? I'm still exploring Haskell and I think that it might not be the solution, but it might inspire a better way. I've found many people on the Haskell IRC channel (which is extremely active) to be very helpful, but the documentation about Haskell will scare away most programmers. The concepts aren't hard, but if you read the wikibook you will likely come away with the impression that only PhDs in Mathematics can learn Haskell. Real World Hasekll seems better, but still lacks that killer intro that will grab the attention of the masses (and maybe they don't want the masses...). Erik's presentation was passionate and you could tell that he really believes that pure functional programming is the future.
Cliff Click's demo of Azul Systems tool was very, very impressive (and only about a dozen people saw it). His presentation was also good. This type of low level HotSpot support is necessary for language designers who are serious about performance and $40k seemed reasonable for a machine if you get Cliff's expertise along with it!
In addition to some C# by Mads, Allison Randal spoke about the Parrot VM. I was happy to see that Sun had the openness to invite Microsoft and Parrot to take part. I think that it really added to the quality of the summit. Google had some folks present, but didn't really talk about how they use the JVM. Next year, I would love to see some more activity from Google.
Parrot is a register based VM which makes some things (ie continuations) easier to implement, but I think that it might be quite some time before the performance can match the HotSpot JVM for most things. Parrot has been around for 7 years so they just have not had as much time (and money?) to devote to making it as mature as the JVM.
Thinking about going to the JVM language summit next year? I highly recommend the event, but it is a small group of highly experienced language designers. So the following words should not scare you: invariant, covariance, type erasure, continuations, tail call optimization, etc. You probably also should have some experience implementing your own language and/or working extensively at the byte code level. It will also help to be familiar with the symbols used to describe type systems. I don't mean to scare anyone away, but I recommend that you make an honest assessment if the event is right for you. Otherwise you might have a good time but not be able to take part in the conversations. If this is your thing, Microsoft also has a Lang.NET conference you might want to check out.
My only suggestion to Sun: use a room with a screen that is elevated a little more so the entire room can see the full screen.
Summary
- LINQ - Functional programming features in C#.
- Kawa - Scheme without full continuations.
- Fundamentalist Functional Programming - Turn your world upside down presentation. Described in detail above.
- NetRexx - An old IBM scripting language that has been open sourced.
- Scalify - Library to take Java code as input and produce Scala as output. Looking for others to join to add Java -> "other JVM language" implementations as well.
- Closures and the JVM - Mostly discussed language interoperability on the JVM and the problems languages face when trying to use libraries written in other languages (with Java being somewhat of an exception). If you haven't heard by now, Neal is also working for Microsoft.
- Bytecodes for fast JVMs - Showed low level metrics for Clojure, JRuby and Jython. Cliff was able to identify areas where teams thought that something was being inlined, but in fact was not.
- Jatha Common Lisp - What Ola Bini worked on before JRuby.
- Parrot VM - Register based VM.
Many thanks to Sun for hosting a spectacular event. In particular, thank you John Rose for taking the time on several occasions to chat. I know you were very busy.

