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

Specific version for @DevTalksRo

Philippe CHARRIERE

June 08, 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: hello world,

    … some Golo’s specificities: DynamicObjects, Structures,… Functional Programming: Optional, Result,… Golo ❤ Java: Vert-x, … Augmenting Golo: add features to Golo
  5. Run some Golo Code You can compile and run Or

    create Jar files applications (or Libraries) but…
  6. 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)) }
  7. 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)) }
  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. 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 }
  11. 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 }
  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. Control structures module control function main = |args| { let

    fourtyTwo = 42 if fourtyTwo is 42 { println("") } else { println("") } }
  14. 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 }
  15. Loop structures module loops function main = |args| { var

    counter = 0 while (counter < 4) { counter = counter + 1 } println(counter) # 4 }
  16. 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) } }
  17. 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) } }
  18. 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
  19. 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
  20. 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
  21. 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()
  22. 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) # }
  23. 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!")) }
  24. 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!")) }
  25. 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!")) }
  26. 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 }
  27. 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 }
  28. 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? }
  29. 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? }
  30. 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 }
  31. 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()) }
  32. 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=} }
  33. 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=} }
  34. 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=} }
  35. 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❗") } ) }
  36. 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] }
  37. 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 ) }
  38. 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 ) }
  39. 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) }
  40. 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) }
  41. 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) }
  42. 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 ") }
  43. 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);
  44. 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, "/*")
  45. 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()) }
  46. 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, "/*")
  47. I am a superhero I’m not a real Java Developer

    I ❤ JavaScript and Node But I made (accepted) PR on the Golo project
  48. IOT & MQTT experiments the benefit of the entire Java

    Ecosystem easy experiments https://github.com/golo-x/golo-x-mqtt