Golo, Think different

What is Golo? Golo is a lightweight dynamic language for the JVM. Yes, again! But a simple one!

Golo is build with invokedynamic. Golo is easy to use and even easy to modify (it will be the subject of a future article).

It was invented by Julien Ponge (the well known @jponge) the @TypeUnsafe Boss, but also a talented researcher at Dynamid.

Golo is a proof of Dynamid invokedynamic expertise and a powerfull tool to work with dynamic middlewares. To my mind, Golo is is also a great way to prototype your idea quickly using all the possibilities of the Java ecosystem. Indeed, Golo is born to “play” with Java. Golo simplify Java and help you to create nice DSL. You can think to Golo as syntactic sugar for Java.

Today, we’ll take a quick tour of Golo to learn basis.

Install Golo

You have to download Golo here : http://golo-lang.org/download/ and define environment variables:

GOLO_HOME=/where_you_have_unzip_golo_distribution/golo-0-preview12-SNAPSHOT;
export GOLO_HOME
export PATH=$PATH:$GOLO_HOME/bin

And now some code snippets

Golo is so simple that you can learn it only reading source code samples ;)

Functions and closures/lambda

Create a main.golo file :

module demo

function hello = |who| {
  println("Hello " + who)
}

function main = |args| {

  let hi = |who| -> println("Hi " + who) #  this is a closure

  hi("John")

  hello("Bob") 

  ["John", "Jane", "Bob"]: each(|someone|{
    hello(someone)
  })

}

Run it : golo golo --files main.golo

Use and Augment Java

Create a jar file from this source java code :

package acme;

import java.lang.String;
import java.lang.System;

public class Toon {

  public String name;

  public Toon(String name) {
    this.name = name;
  }

  public void hello() {
    System.out.println("Hello, i'm " + this.name);
  }

  public static Toon getInstance(String value) {
    return new Toon(value);
  }
}

# Use Toon class with Golo

module demo

import acme

function main = |args| {

  let buster = Toon("Buster") #  new

  println(buster: name()) #  property (getter)

  buster: name("BUSTER") #  setter

  buster: hello() #  instance method

  let babs = Toon.getInstance("Babs") #  static method

  println(babs: name())

}

Run it : golo golo --classpath jars/*.jar --files main.golo

(my jar file is in the jars directory)

Remarks: please note the : notation for calling instance method and .notation for calling the class method.

# Add abilities to Toon class with Golo

With the augment keyword you can add method to Java types (custom types as Toon but even core Java types as String, LinkedList, …) :

module demo

import acme

augment acme.Toon {
  #  add "french" method
  function salut = |this| {
    println("Salut, je suis " + this: name())
  }
}

function main = |args| {

  let babs = Toon("Babs")

  babs: salut() #  print "Salut, je suis Babs"

}

No Class with Golo, but we have some very powerful elements of languages

# The structure

module demo_structure

struct human = {
  firstName, lastName
}

function main = |args| {

  let bob = human("Bob", "Morane")

  let john = human(): firstName("John"): lastName("Doe")

  println(
    bob: firstName() + " " + bob: lastName()
  )
  println(
    john: firstName() + " " + john: lastName()
  )
}

And you can augment structures too!:

module demo_structure

struct human = {
  firstName, lastName
}

augment human {
  function hello = |this| -> 
    println("Hello " + this: firstName() + " " + this: lastName())
}

function main = |args| {
  let bob = human("bob", "morane")
  bob: hello()
}

# The DynamicObject

DynamicObject is a very flexible structure of Golo language which advantageously replaces the classes, with a touch of functional programming (no troll!) :

function main = |args| {

  let clarkKent = DynamicObject()
    : firstName("Clark")
    : define("toString", |this| -> "firstName : " + this: firstName())

  println(clarkKent: toString())

  clarkKent: lastName("Kent") 
    : define("toString", |this| ->
        "firstName : " + this: firstName() +
        " lastName : " + this: lastName()
    )

  println(clarkKent: toString())
}

# # DynamicObject and mixin

There is no inheritance, but you can mixin DynamicObjects:

module demo_dynamic

function main = |args| {

  let clarkKent = DynamicObject()
    : firstName("Clark"): lastName("Kent")

  let superMan = DynamicObject(): mixin(clarkKent)

  superMan: heroName("SuperMan")
    : power("flying")
    : define("toString", |this| -> "I'm " +
        this: firstName() + " " +
        this: lastName() + " alias " +
        this: heroName() + ", i'm " +
        this: power()
    )

  println(superMan: toString())

}

# # Chaining pattern with DynamicObjects

It’s very usefull to create some DSL:

module demo_dynamic

function main = |args| {

  let somebody = DynamicObject()
    : define("who", |this, name| {
        println("My name is " + name)
        return this
    })
    : define("hero", |this, name| {
        println("I am " + name)
        return this
    })
    : define("power", |this, power| {
        println("I've got a power: " + power)
        return this
    })

  somebody: who("Tony Stark"): hero("IronMan"): power("flying")

  somebody: hero("IronMan"): power("flying"): who("Tony Stark")

}

Golo plays with Java (again) with the dynamic adapters

Remember our Toon class, you can create an adapter of acme.Toon and re implement the hello() method:

module demo

import acme

function main = |args| {

  let toonDefinition = map[
    ["extends", "acme.Toon"], 
    ["implements", map[
      ["hello", |this| {
          println("Hello, i'm " + this: name())
      }]
    ]]
  ]

  let buster = AdapterFabric(): maker(toonDefinition)
    : newInstance("Buster Bunny")

  buster: hello()
}

Remarks: i use extends, but you can use interfaces too (if you’ve got an interface), see documentation: http://golo-lang.org/documentation/next/# _implementing_interfaces.

You can inject code before and after method thanks overrides and super:

module demo

import acme

function main = |args| {

  let toonDefinition = map[
    ["extends", "acme.Toon"],
    ["overrides", map[
      ["hello", |super, this| {
          println("Before ...")
          super(this)
          println("... After")
      }]
    ]]
  ]

  let buster = AdapterFabric(): maker(toonDefinition)
    : newInstance("Buster Bunny")

  buster: hello()
}

Remarks: dynamic adapters are very useful for deal with java frameworks, see example with SparkJava here: http://golo-lang.org/documentation/next/# _a_simple_example.

Draft of a web DSL

Actually, i’m working on a web framework with Golo thanks all these language structures. here’s what it will look like:

appRouter: add([
    get("/hello/{name}") (|http| {
      http: text(http: parameters(): get("name")): close()
    })
  , get("/about") (|http| {
      http: html("<h1>Hello</h1><h2>World</h2><h3>!!!</h3>")
          : close()
    })
  , get("/infos") (|http| {
      http: allowCORS("*", "*", "*")
      http: json(
        JSON. stringify(DynamicObject()
            : firstName("Bob")
            : lastName("Morane"))
      ): close()
    })
  , post("/users") (|http|{

      let data = http: request(): getQuery()

      http: jsonize(map[
        ["firstName", data: get("firstName")]
      ]): status(201): close()
  })
])

And soon we’ll able to write something like this:

@Secured(true)
@Only("admin", ["create", "delete", "update"])
@RESTController("/humans")
function HumansController -> DynamicObject()

That’s all for today. Next time we’ll see how compile an hybrid project with golo and java source code.

blog comments powered by Disqus

Related posts