Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Golo, the Tiny Language that gives super powers

Golo, the Tiny Language that gives super powers

at CodeEurope 2017 - https://www.codeeurope.pl/en

Golo is a JVM dynamic language, light and fast I'm not a Java Ninja, however I can do a lot of things easily with Golo. I will present: - The basics - Some features (as DynamicObjects, Functional Types) - How Golo loves Java and how you can develop tools even for the IOT - How you can hack Golo

Philippe CHARRIERE

May 23, 2017
Tweet

More Decks by Philippe CHARRIERE

Other Decks in Programming

Transcript

  1. Philippe Charrière > Technical “evangelist” & CSO @Clever_Cloud > Core

    committer for the eclipse/golo-lang project U@k33g_org / O @k33g
  2. A dynamic language for the JVM Built from the first

    day with invokedynamic Light (~700 kb) and fast (in a dynamic context) A research project by Julien Ponge http://golo-lang.org @jponge
  3. Thanks to Golo… I learned to read the Java doc

    I progressed in Java (I wasn’t a Java Ninja) I learned how to participate in an opensource project I do things I didn’t do before
  4. we are going to talk about: Golo’s simplicity some Golo’s

    specificities Functional Programming Golo ❤ Java Augmenting Golo
  5. Run some Golo Code: Compile and Run golo compile --output

    classes helloworld.golo golo run --module hello.world
  6. Run some Golo Code: Maven or Gradle projects golo new

    hello --type maven --profile app mvn package mvn exec:java
  7. Run some Golo Code: Maven or Gradle projects golo new

    hello --type maven --profile lib mvn package
  8. Modules & Functions # my.lib.golo module my.lib function hello =

    |name| { return "Hello " + name } # short version function hi = |name| -> "Hi " + name # main.golo module myApp import my.lib function main = |args| { let name = "Baby Groot" println(hello(name)) println(hi(name)) }
  9. Modules & Functions # my.lib.golo module my.lib function hello =

    |name| { return "Hello " + name } # short version function hi = |name| -> "Hi " + name # main.golo module myApp import my.lib function main = |args| { let name = "Baby Groot" println(hello(name)) println(hi(name)) }
  10. Modules & Functions # my.lib.golo module my.lib function hello =

    |name| { return "Hello " + name } # short version function hi = |name| -> "Hi " + name # main.golo module myApp import my.lib function main = |args| { let name = "Baby Groot" println(hello(name)) println(hi(name)) }
  11. Modules & Functions # my.lib.golo module my.lib function hello =

    |name| { return "Hello " + name } # short version function hi = |name| -> "Hi " + name # main.golo module myApp import my.lib function main = |args| { let name = "Baby Groot" println(hello(name)) println(hi(name)) }
  12. Lambdas module lambdas function main = |args| { let add

    = |a, b| { return a + b } # compact version let addOne = |value| -> value + 1 println( add(40, 2) ) # 42 println( addOne(41) ) # 42 }
  13. Lambdas module lambdas function main = |args| { let add

    = |a, b| { return a + b } # compact version let addOne = |value| -> value + 1 println( add(40, 2) ) # 42 println( addOne(41) ) # 42 }
  14. Lambdas module lambdas function main = |args| { let add

    = |a, b| { return a + b } # compact version let addOne = |value| -> value + 1 println( add(40, 2) ) # 42 println( addOne(41) ) # 42 }
  15. Lambdas module lambdas function main = |args| { let something

    = |a, b| { return |value| -> (a + b) / value } println( something(40,44)(2) ) # 42 }
  16. Lambdas module lambdas function main = |args| { let something

    = |a, b| -> |value| -> (a + b) / value println( something(40,44)(2) ) # 42 }
  17. Lambdas module lambdas function main = |args| { let something

    = |a, b| { return |value| -> (a + b) / value } println( something(40,44)(2) ) # 42 }
  18. Lambdas module lambdas function main = |args| { let something

    = |a, b| { return |value| -> (a + b) / value } let divideSum = something(40,44) println( divideSum(2) ) # 42 }
  19. Control structures module control function main = |args| { let

    fourtyTwo = 42 if fourtyTwo is 42 { println("") } else { println("") } }
  20. Control structures module control function main = |args| { let

    isEqualTo42 = |value| { case { when value is 42 { return " good" } when value > 42 { return " too big" } otherwise { return " too little" } } } println(isEqualTo42(42)) # good println(isEqualTo42(24)) # too little println(isEqualTo42(84)) # too big }
  21. Loop structures module loops function main = |args| { var

    counter = 0 while (counter < 4) { counter = counter + 1 } println(counter) # 4 }
  22. Loop structures module loops function main = |args| { foreach

    item in [1, 2, 3, 4, 5] { if item < 3 { println(item) } } foreach item in [1, 2, 3, 4, 5] when item < 3 { println(item) } }
  23. Loop structures with a guard module loops function main =

    |args| { foreach item in [1, 2, 3, 4, 5] { if item < 3 { println(item) } } foreach item in [1, 2, 3, 4, 5] when item < 3 { println(item) } }
  24. Java types module javatypes function main = |args| { let

    vegetables = java.util.LinkedList() # no new keyword vegetables: add("") # colon notation vegetables: add("") vegetables: add("") println(vegetables) # [, , ] let mixedSalad = vegetables : stream() : map( |ingredient| -> java.lang.String.join(ingredient, ingredient, ingredient) ) : reduce("", |acc, next| -> acc + next) println(mixedSalad) # } # dot notation
  25. Java types module javatypes function main = |args| { let

    vegetables = java.util.LinkedList() # no new keyword vegetables: add("") # colon notation vegetables: add("") vegetables: add("") println(vegetables) # [, , ] let mixedSalad = vegetables : stream() : map( |ingredient| -> java.lang.String.join(ingredient, ingredient, ingredient) ) : reduce("", |acc, next| -> acc + next) println(mixedSalad) # } # dot notation
  26. Java types module javatypes function main = |args| { let

    vegetables = java.util.LinkedList() # no new keyword vegetables: add("") # colon notation vegetables: add("") vegetables: add("") println(vegetables) # [, , ] let mixedSalad = vegetables : stream() : map( |ingredient| -> java.lang.String.join(ingredient, ingredient, ingredient) ) : reduce("", |acc, next| -> acc + next) println(mixedSalad) # } # dot notation
  27. Simpler way: Collection literals module javatypes function main = |args|

    { let vegetables = list["", "", ""] let mixedSalad = vegetables : map(|ingredient| -> "": join(ingredient,ingredient,ingredient)) : reduce("", |acc, next| -> acc + next) println(mixedSalad) # } java.util.LinkedList()
  28. Simpler way: Collection literals module javatypes function main = |args|

    { let vegetables = list["", "", ""] let mixedSalad = vegetables : map(|ingredient| -> ingredient: join(ingredient,ingredient)) : reduce("", |acc, next| -> acc + next) println(mixedSalad) # }
  29. Simpler way: Collection literals Collection Java type Syntax Tuple gololang.Tuple

    tuple[1, 2, 3], or simply [1, 2, 3] Array java.lang.Object[] array[1, 2, 3] List java.util.LinkedList list[1, 2, 3] Vector java.util.ArrayList vector[1, 2, 3] Set java.util.LinkedHashSet set[1, 2, 3] Map java.util.LinkedHashMap map[[1, "a"], [2, "b"]] Range gololang.Range [1..10], ['a'..'f']
  30. DynamicObject module clark function main = |args| { let clark

    = DynamicObject() : firstName("Clark"): lastName("Kent") : define("hello", |this| { println("Hello, I'm " + this: firstName()) return this }) : define("say", |this, message| { println(message) return this }) clark: hello(): say("hi!") # Hello, I'm Clark\n hi! clark: firstName("CLARK") clark: hello() # Hello, I'm CLARK clark: define("yo", |this| -> println("yo!")) }
  31. DynamicObject module clark function main = |args| { let clark

    = DynamicObject() : firstName("Clark"): lastName("Kent") : define("hello", |this| { println("Hello, I'm " + this: firstName()) return this }) : define("say", |this, message| { println(message) return this }) clark: hello(): say("hi!") # Hello, I'm Clark\n hi! clark: firstName("CLARK") clark: hello() # Hello, I'm CLARK clark: define("yo", |this| -> println("yo!")) }
  32. DynamicObject module clark function main = |args| { let clark

    = DynamicObject() : firstName("Clark"): lastName("Kent") : define("hello", |this| { println("Hello, I'm " + this: firstName()) return this }) : define("say", |this, message| { println(message) return this }) clark: hello(): say("hi!") # Hello, I'm Clark\n hi! clark: firstName("CLARK") clark: hello() # Hello, I'm CLARK clark: define("yo", |this| -> println("yo!")) }
  33. Mixin of DynamicObjects module krypton function main = |args| {

    # set the kind of the DynamicObject let clark = DynamicObject("Kryptonian"): name("Clark") let kara = DynamicObject("Kryptonian"): name("Kara") let powers = DynamicObject(): define("fly", |this| -> println("")) clark: mixin(powers) kara: mixin(powers) clark: fly() # kara: fly() # }
  34. Structures module doeFamiliy struct human = { firstName, lastName }

    function main = |args| { # simple constructor let jane = human("Jane", "Doe") # constructor, then setters let john = human(): firstName("John"): lastName("Doe") println("hello we are " + jane: firstName() + " " + jane: lastName() + " and " + john: firstName() + " " + john: lastName() ) println(jane oftype doeFamiliy.types.human.class) # true }
  35. Structures module doeFamiliy struct human = { firstName, lastName }

    function main = |args| { # simple constructor let jane = human("Jane", "Doe") # constructor, then setters let john = human(): firstName("John"): lastName("Doe") println("hello we are " + jane: firstName() + " " + jane: lastName() + " and " + john: firstName() + " " + john: lastName() ) println(jane oftype doeFamiliy.types.human.class) # true }
  36. Structures & Augmentations module doeFamiliy struct human = { firstName,

    lastName } augment human { function hello = |this| { println(this: firstName() + ": Hello!") } function hello = |this, message| { println(this: firstName() + ": Hello! " + message) } } function main = |args| { let jane = human("Jane", "Doe") jane: hello() # Jane: Hello! jane: hello("How are you doing?") # Jane: Hello! How are you doing? }
  37. Structures & Augmentations module doeFamiliy struct human = { firstName,

    lastName } augment human { function hello = |this| { println(this: firstName() + ": Hello!") } function hello = |this, message| { println(this: firstName() + ": Hello! " + message) } } function main = |args| { let jane = human("Jane", "Doe") jane: hello() # Jane: Hello! jane: hello("How are you doing?") # Jane: Hello! How are you doing? }
  38. Structures & named Augmentations module doeFamiliy struct human = {

    firstName, lastName } struct dog = { name } augmentation eat = { function eat = |this, something| -> println("I'm eating " + something) } augment human with eat augment dog with eat function main = |args| { let jane = human("Jane", "Doe") let cookie = dog("Cookie") jane: eat("") # I'm eating cookie: eat("") # I'm eating }
  39. Golo translation from Java module http # synchronous method function

    getContent = |uri| { let obj = java.net.URL(uri) # URL obj let connection = obj: openConnection() # HttpURLConnection connection: setRequestMethod("GET") let responseCode = connection: getResponseCode() let responseMessage = connection: getResponseMessage() let responseText = java.util.Scanner( connection: getInputStream(), "UTF-8" ): useDelimiter("\\A"): next() # String responseText return responseText }
  40. Synchronous version module demo_sync import http function main = |args|

    { let googleContent = getContent("http://www.google.com") println(googleContent) let goloContent = getContent("http://golo-lang.org/") println(goloContent) }
  41. Synchronous -> Asynchronous with promises module demo_async import http import

    gololang.Async function main = |args| { # define a promise let getAsyncContent = |uri| -> promise(): initializeWithinThread(|resolve, reject| { try { let content = getContent(uri) resolve(content) } catch(error) { reject(error) } }) # call the promise getAsyncContent("http://www.google.com") : onSet(|result| { # if success println(result) }) : onFail(|error| { # if failed println(error: message()) }) } lambdas as parameters
  42. Synchronous -> Asynchronous with promises module demo_async import http import

    gololang.Async function main = |args| { # define a promise let getAsyncContent = |uri| -> promise(): initializeWithinThread(|resolve, reject| { try { let content = getContent(uri) resolve(content) } catch(error) { reject(error) } }) # call the promise getAsyncContent("http://www.google.com") : onSet(|result| { # if success println(result) }) : onFail(|error| { # if failed println(error: message()) }) } resolve reject
  43. NPE module nomore_npe struct buddy = { id, avatar }

    function main = |args| { let buddies = list[buddy(1, ""), buddy(2, ""), buddy(3, "")] # println(buddies: find(|buddy| -> buddy: id(): equals(3)): avatar()) # java.lang.NullPointerException println(buddies: find(|buddy| -> buddy: id(): equals(4)): avatar()) }
  44. Option() / Some / None function main = |args| {

    let buddies = list[buddy(1, ""), buddy(2, ""), buddy(3, "")] let getBuddy = |id| -> Option( buddies: find(|buddy| -> buddy: id(): equals(id)) ) let maybePanda = getBuddy(2) let maybeNobody = getBuddy(4) println( maybePanda ) # Optional[struct buddy{id=2, avatar=}] println( maybeNobody ) # Optional.empty println( maybePanda: isSome() ) # true println( maybeNobody: isNone() ) # true println( maybePanda: orElse(buddy(0, "")) ) # struct buddy{id=2, avatar=} println( maybeNobody: orElse(buddy(0, "")) ) # struct buddy{id=0, avatar=} }
  45. Option() / Some / None function main = |args| {

    let buddies = list[buddy(1, ""), buddy(2, ""), buddy(3, "")] let getBuddy = |id| -> Option( buddies: find(|buddy| -> buddy: id(): equals(id)) ) let maybePanda = getBuddy(2) let maybeNobody = getBuddy(4) println( maybePanda ) # Optional[struct buddy{id=2, avatar=}] println( maybeNobody ) # Optional.empty println( maybePanda: isSome() ) # true println( maybeNobody: isNone() ) # true println( maybePanda: orElse(buddy(0, "")) ) # struct buddy{id=2, avatar=} println( maybeNobody: orElse(buddy(0, "")) ) # struct buddy{id=0, avatar=} }
  46. Option() / Some / None function main = |args| {

    let buddies = list[buddy(1, ""), buddy(2, ""), buddy(3, "")] let getBuddy = |id| -> Option( buddies: find(|buddy| -> buddy: id(): equals(id)) ) let maybePanda = getBuddy(2) let maybeNobody = getBuddy(4) println( maybePanda ) # Optional[struct buddy{id=2, avatar=}] println( maybeNobody ) # Optional.empty println( maybePanda: isSome() ) # true println( maybeNobody: isNone() ) # true println( maybePanda: orElse(buddy(0, "")) ) # struct buddy{id=2, avatar=} println( maybeNobody: orElse(buddy(0, "")) ) # struct buddy{id=0, avatar=} }
  47. Option() / either() function main = |args| { let buddies

    = list[buddy(1, ""), buddy(2, ""), buddy(3, "")] let getBuddy = |id| -> Option( buddies: find(|buddy| -> buddy: id(): equals(id)) ) getBuddy(2) : either( |buddy| { println("Hello "+ buddy: avatar()) }, # Hello { println(" ouch❗") } ) }
  48. Result / Error module nomore_error import gololang.Errors function main =

    |args| { let divide = |a, b| { try { return Result(a/b) } catch(e) { return Error(e: message()) } } println( divide(84, 2) ) # Result.value[42] println( divide(84, 0) ) # Result.error[ java.lang.RuntimeException: / by zero] }
  49. Result / Error / trying() / either() module nomore_error import

    gololang.Errors function main = |args| { let divide = |a, b| -> trying({ return a/b }) divide(84, 0): either( |result| -> println(": " + result), |error| -> println(": " + error: message()) # : / by zero ) }
  50. Result / Error / trying() / either() module nomore_error import

    gololang.Errors function main = |args| { let divide = |a, b| -> trying({ return a/b }) divide(84, 0): either( |result| -> println(": " + result), |error| -> println(": " + error: message()) # : / by zero ) }
  51. Golo ❤ Java package acme; import java.lang.String; import java.lang.System; public

    class Toon { private String name; public String getName() { return name; } public void setName(String value) { name = value; } public Toon(String name) { this.name = name; } public static Toon getInstance(String name) { return new Toon(name); } public void hug(Toon toon) { System.out.println("I ❤ " + toon.name); } } module toons import acme function main = |args| { let buster = Toon("Buster") # no new buster: name("Buster Bunny") println(buster: name()) let elmira = Toon.getInstance("elmira") elmira: hug(buster) }
  52. Golo ❤ Java package acme; import java.lang.String; import java.lang.System; public

    class Toon { private String name; public String getName() { return name; } public void setName(String value) { name = value; } public Toon(String name) { this.name = name; } public static Toon getInstance(String name) { return new Toon(name); } public void hug(Toon toon) { System.out.println("I ❤ " + toon.name); } } module toons import acme function main = |args| { let buster = Toon("Buster") # no new buster: name("Buster Bunny") println(buster: name()) let elmira = Toon.getInstance("elmira") elmira: hug(buster) }
  53. Golo ❤ Java package acme; import java.lang.String; import java.lang.System; public

    class Toon { private String name; public String getName() { return name; } public void setName(String value) { name = value; } public Toon(String name) { this.name = name; } public static Toon getInstance(String name) { return new Toon(name); } public void hug(Toon toon) { System.out.println("I ❤ " + toon.name); } } module toons import acme function main = |args| { let buster = Toon("Buster") # no new buster: name("Buster Bunny") println(buster: name()) let elmira = Toon.getInstance("elmira") elmira: hug(buster) }
  54. Golo ✨⚡ Java module toons import acme augment acme.Toon {

    function hey = |this, message| { println(this: name() + ": " + message) } } function main = |args| { let buster = Toon("Buster") buster: hey("I'm a ") }
  55. RxJava with Java // defining the source Observable<Long> observable =

    Observable.interval(1, TimeUnit.SECONDS); // defining the observer Observer<Long> observer = new Observer<Long>() { @Override public void onSubscribe(Disposable disposable) { System.out.println(" subscribed"); } @Override public void onNext(Long value) { System.out.println(" " + value); } @Override public void onError(Throwable throwable) { System.out.println(" error"); } @Override public void onComplete() { System.out.println(" completed"); } }; // connecting the observer to source observable.subscribe(observer); java.lang.Thread.sleep(5000);
  56. RxJava with Golo # defining the source let observable =

    Observable.interval(1_L, java.util.concurrent.TimeUnit.SECONDS()) # defining the observer let ObserverAdapter = Adapter(): interfaces(["io.reactivex.Observer"]) : implements("onSubscribe", |this, disposable| { println(" subscribed") }) : implements("onNext", |this, value| { println(" " + value) }) : implements("onError", |this, error| { println(" error") }) : implements("onComplete", |this| { println(" completed") }) let observer = ObserverAdapter: newInstance() # connecting the observer to source observable: subscribe(observer) sleep(5000_L) subscribed 0 1 2 3 4 http://golo-lang.org/documentation/next/index.html#_adapters_helper
  57. Java web application with Vert-x int httpPort = 8080; Vertx

    vertx = Vertx.vertx(); HttpServer server = vertx.createHttpServer(); Router router = Router.router(vertx); router.route().handler(BodyHandler.create()); router.get("/about").handler(routingContext -> { routingContext.response() .putHeader("content-type", "application/json;charset=UTF-8") .end((new JsonObject().put("about", " hello from Golo")).toString()); }); router.post("/hello").handler(routingContext -> { String name = routingContext.getBodyAsJson().getString("name"); routingContext.response() .putHeader("content-type", "application/json;charset=UTF-8") .end((new JsonObject().put("message", " Hello " + name)).toString()); }); server.requestHandler(router::accept).listen(httpPort);
  58. Simplify Vert-x let httpPort = 8080 let server = createHttpServer()

    let router = getRouter() router: get("/about", |context| { context: response(): djson(): about(" hello from Golo"): send() }) router: post("/hello", |context| { let data = context: dbody() let name = data: name() context: response(): djson(): message(" Hello " + name): send() }) startHttpServer(server, router, httpPort, "/*")
  59. some of the augmentations augment io.vertx.ext.web.Router { function get =

    |this, uri, handler| { return this: get(uri): handler(handler) } function post = |this, uri, handler| { return this: post(uri): handler(handler) } } augment io.vertx.core.http.HttpServerResponse { function djson = |this| { this: putHeader("content-type", "application/json;charset=UTF-8") let d = DynamicObject() d: define("send", |self| { this: end(JSON.stringify(self), "UTF-8") }) return d } } augment io.vertx.ext.web.RoutingContext { function dbody = |this| -> JSON.toDynamicObjectFromJSONString(this: getBodyAsString()) }
  60. Simplify Vert-x - Functional way let httpPort = Integer.parseInt(System.getenv(): get("PORT")

    orIfNull "8080") let server = createHttpServer() let router = getRouter() router: get("/about", |context| { context: response(): djson(): about(" hello from Golo"): send() }) router: post("/hello", |context| { trying({ let data = context: dbody() return data: name() }) : either( |name| -> context: response(): djson(): message(" Hello " + name): send(), |error| -> context: response(): djson(): error(" " + error: message()): send() ) }) startHttpServer(server, router, httpPort, "/*")
  61. http://pi4j.com/ struct led = { pin, board } augment led

    { function toggle = |this| -> this: pin(): toggle() function off = |this| -> this: pulse(300_L, true) function name = |this| -> this: pin(): name() function blink = |this, howManyTimes, delay| -> (howManyTimes * 2): times(|index| { Thread.sleep(delay) this: toggle() }) function worker = |this, task| -> this: board(): workerEnvironment(): spawn(|message| { task(this, message) }) } function Led = |board, gpio, name, state| { let pin = digitalOutputPin(board, gpio, name, state): provision() return led(pin, board) }
  62. http://pi4j.com/ struct led = { pin, board } augment led

    { function toggle = |this| -> this: pin(): toggle() function off = |this| -> this: pulse(300_L, true) function name = |this| -> this: pin(): name() function blink = |this, howManyTimes, delay| -> (howManyTimes * 2): times(|index| { Thread.sleep(delay) this: toggle() }) function worker = |this, task| -> this: board(): workerEnvironment(): spawn(|message| { task(this, message) }) } function Led = |board, gpio, name, state| { let pin = digitalOutputPin(board, gpio, name, state): provision() return led(pin, board) }
  63. http://pi4j.com/ let greenLED = Led(breadBoard, GPIO_05(), "MyGreenLED", HIGH()) let greenWorker

    = greenLED: worker(|led, times| { println(led: name() + " is blinking ") led: blink(times,500_L) # howmanytimes, delay led: off() }) router: get("/blink/:led", |context| { let selectedLed = context: request(): param("led") match { when selectedLed: equals("red") then redWorker: send(5) when selectedLed: equals("green") then greenWorker: send(5) when selectedLed: equals("blue") then greenWorker: send(5) otherwise raise(" Huston!") } # … })
  64. https://github.com/kurbatov/firmata4j # firmata4j let myArduino = device(): port("/dev/cu.usbmodem1411") let redLed

    = myArduino: getLedInstance("red", 13) redLed: switchOn() redLed: blink(1000_L) redLed: blink(1000_L) redLed: blink(1000_L) redLed: blink(1000_L)
  65. a language to learn and try IOT the benefit of

    the entire Java Ecosystem easy experiments https://github.com/golo-x/golo-x-mqtt
  66. I am a superhero I’m not a real Java Developer

    I ❤ JavaScript and Node But I made (accepted) PR on the Golo project