SlideShare a Scribd company logo
1 of 97
Download to read offline
Philippe Charrière
O GitHub
GOLO, THE TINY LANGUAGE THAT
GIVES SUPER POWERS
Philippe Charrière
G @k33g
U @k33g_org ⚠"#
Golo committer
“Another language for the JVM”
- Agenda -
The basis of Golo
Some specific features
How Golo ❤ Java
I use it for my job
How to hack Golo with Java or with Golo
What is Golo?
A research project > Julien Ponge @ CitiLab
A dynamic language for the JVM
Built from the first day with invokedynamic
Light (~700 kb) and fast (in a dynamic context)
U @jponge
Why Golo?
Easy to learn
Easy to use
Easy to hack
Small
a language to learn and try
tiger("tigrou 🐯")
: start(4, 2)
: move(2): right(): left()
: stop()
: say("hello")
DSL for children
a language to learn and try
IOT# firmata4j
let myArduino = device(): port("/dev/cu.usbmodem1411")
myArduino: initialize(): onSet(|self| {
let redLed = self: getLedInstance("red", 13)
redLed: switchOn()
self: loop(50, |i| {
redLed: blink(1000_L)
})
}): onFail(|err| {
println("Huston? We've got a problem!")
})
Simple
module operations
function addition = |a, b| {
return a + b
}
function multiplication = |a, b| -> a * b
module operations
function addition = |a, b| {
return a + b
}
function multiplication = |a, b| -> a * b
module operations
function addition = |a, b| {
return a + b
}
function multiplication = |a, b| -> a * b
module operations
function addition = |a, b| {
return a + b
}
function multiplication =
|a, b| -> a * b
#!/usr/bin/env golosh
module demo
import operations
function main = |args| {
println(addition(40,2))
println(multiplication(21,2))
}
#!/usr/bin/env golosh
module demo
import operations
function main = |args| {
println(addition(40,2))
println(multiplication(21,2))
}
module operations
function addition = |a, b| {
return a + b
}
function multiplication =
|a, b| -> a * b
Run Golo scripts
several ways
golo command
compilation (class and jar)
as a shell script
Run it #!/usr/bin/env golosh
module demo
import operations
function main = |args| {
println(addition(40,2))
println(multiplication(21,2))
}
Run it
chmod +x hello.golo
./hello.golo
#!/usr/bin/env golosh
module demo
import operations
function main = |args| {
println(addition(40,2))
println(multiplication(21,2))
}
Run it
./
!"" libs
!"" libA.jar
!"" libB.jar
!"" commons
!"" utils.golo
!"" others.golo
!"" vendors
!"" otherlib.jar
!"" hello.golo
#!/usr/bin/env golosh
module demo
import operations
function main = |args| {
println(addition(40,2))
println(multiplication(21,2))
}
Some features
(my favorite features)
Closures
#!/usr/bin/env golosh
module demo
function main = |args| {
let division = |a,b| {
return a/b
}
try {
println(division(84, 0))
} catch (err) {
println("😡: " + err: message())
}
}
Simple and Efficient
Composition rather than Inheritance
Mixed approach (object / functional)
No Class!
but…
struct human = {
firstName,
lastName
}
module demo1_structure
struct human = {
firstName, lastName
}
function main = |args| {
# no new keyword
let john = human("John", "Doe")
# named parameters
let jane = human(firstName="Jane", lastName="Doe")
# colon notation
let bob = human(): firstName("Bob"): lastName("Morane")
println("Hello, I'm " + bob: firstName() + " " + bob: lastName())
}
module demo1_structure
struct human = {
firstName, lastName
}
function main = |args| {
# no new keyword
let john = human("John", "Doe")
# named parameters
let jane = human(firstName="Jane", lastName="Doe")
# colon notation
let bob = human(): firstName("Bob"): lastName("Morane")
println("Hello, I'm " + bob: firstName() + " " + bob: lastName())
}
module demo1_structure
struct human = {
firstName, lastName
}
function main = |args| {
# no new keyword
let john = human("John", "Doe")
# named parameters
let jane = human(firstName="Jane", lastName="Doe")
# colon notation
let bob = human(): firstName("Bob"): lastName("Morane")
println("Hello, I'm " + bob: firstName() + " " + bob: lastName())
}
module demo1_structure
struct human = {
firstName, lastName
}
function main = |args| {
# no new keyword
let john = human("John", "Doe")
# named parameters
let jane = human(firstName="Jane", lastName="Doe")
# colon notation
let bob = human(): firstName("Bob"): lastName("Morane")
println("Hello, I'm " + bob: firstName() + " " + bob: lastName())
}
⚠
Augmentations
module demo_structure
struct human = {
firstName, lastName
}
augment human {
# this is a ref to human structure
function sayHello = |this| ->
"Hello, I'm " + this: firstName() + " " + this: lastName()
}
function main = |args| {
# colon notation
let jane = human()
: firstName("Jane")
: lastName("Doe")
println(jane: sayHello())
}
module demo_structure
struct human = { firstName, lastName }
augment human {
function sayHello = |this| ->
"Hello, I'm " + this: firstName() + " " + this: lastName()
}
function Human = |firstName, lastName| {
# I'm the human constructor
return human(firstName, lastName)
}
function main = |args| {
# colon notation
let jane = Human("Jane", "Doe")
println(jane: sayHello())
}
kind of constructor
No Class! Part 2
but…
DynamicObjects
module demo_dynamicobjects
function main = |args| {
let jane =
DynamicObject()
: firstName("Jane")
: lastName("Doe")
: define(“sayHello”, |this| {
return "Hello, I'm " + this: firstName() +
" " + this: lastName()
})
println(jane: sayHello())
}
module demo_dynamicobjects
function main = |args| {
let jane =
DynamicObject()
: firstName("Jane")
: lastName("Doe")
: define(“sayHello”, |this| {
return "Hello, I'm " + this: firstName() +
" " + this: lastName()
})
println(jane: sayHello())
}
module demo_dynamicobjects
function Human = |firstName, lastName| {
# I'm the human constructor
return
DynamicObject()
: firstName(firstName)
: lastName(lastName)
: define(“sayHello”, |this| {
return "Hello, I'm " + this: firstName() +
" " + this: lastName()
})
}
function main = |args| {
let jane = Human("Jane", "Doe")
println(jane: sayHello())
}
Golo is functional
functions are 👑
function as
output & input
module demo_func_01
function addition = |a, b| { return a + b }
function main = |args| {
# function as output
let add = |a| {
return |b| {
return addition(a,b)
}
}
let addOne = add(1)
println(addOne(41)) # 42
println(
list[1, 2, 3, 4, 5]: map(addOne)
# [2, 3, 4, 5, 6]
)
}
function as
output & input
module demo_func_01
function addition = |a, b| { return a + b }
function main = |args| {
# function as output
let add = |a| {
return |b| {
return addition(a,b)
}
}
let addOne = add(1)
println(addOne(41)) # 42
println(
list[1, 2, 3, 4, 5]: map(addOne)
# [2, 3, 4, 5, 6]
)
} # function as input
module demo_func_01
function addition = |a, b| { return a + b }
function main = |args| {
let add = |a| -> |b| -> addition(a,b)
let addOne = add(1)
println(
list[1, 2, 3, 4, 5]
: map(addOne) # [2, 3, 4, 5, 6]
: map(addOne) # [3, 4, 5, 6, 7]
)
}
function as
output & input
module demo_func_01
function addition = |a, b| { return a + b }
function main = |args| {
let add = |a| -> |b| -> addition(a,b)
let addOne = add(1)
println(
list[1, 2, 3, 4, 5]
: map(addOne) # [2, 3, 4, 5, 6]
: map(addOne) # [3, 4, 5, 6, 7]
)
}
function as
output & input
no iteration
no iteration
let noChips = |food| -> food isnt "🍟"
# return true if it's not chips
let noOnion = |food| -> food isnt “😭"
noChips("🍞") == true
noChips("🍟") == false
no iteration
let noChips = |food| -> food isnt "🍟"
let noOnion = |food| -> food isnt "😭"
let cutFood = |food| -> "piece of " + food
let Food = list[
"🍞"
, "🍃"
, "🍅"
, "🍖"
, "🍟"
, "😭" # 😡 can't find onion emoji
]
no iteration
let myKebabRecipe = Food
: filter(noChips)
: filter(noOnion)
: map(cutFood)
[🍞, 🍃, 🍅, 🍖, 😭]
[piece of 🍞, piece of 🍃, piece of 🍅, piece of 🍖]
[🍞, 🍃, 🍅, 🍖]
[🍞, 🍃, 🍅, 🍖, 🍟, 😭]
no iteration
# ⚡ preparing kebab with myKebabRecipe
let mixFood = |accFood, nextFood| -> accFood + nextFood + " "
let kebab = myKebabRecipe
: reduce("🌮 with: ", mixFood)
[piece of 🍞, piece of 🍃, piece of 🍅, piece of 🍖]
🌮 with: piece of 🍞 piece of 🍃 piece of 🍅 piece of 🍖
Union Types
Golo is functional
module SomeThing
union SomeThing = {
Yum = { value } # good
Yuck = { value } # bad
}
# you're good or bad, but not good and bad
module SomeThing
union SomeThing = {
Yum = { value } # good
Yuck = { value } # bad
}
# you're good or bad, but not good and bad
let banana = SomeThing.Yum("🍌")
let hotPepper = SomeThing.Yuck("🌶")
println(banana: value())
println(hotPepper: value())
# you can do that:
println(banana: isYum()) # true
println(hotPepper: isYuck()) # true
union SomeThing.Yum{value=🍌}
🍌
🌶
union SomeThing.Yuck{value=🌶}
let banana = SomeThing.Yum("🍌")
let hotPepper = SomeThing.Yuck("🌶")
println(banana: value())
println(hotPepper: value())
# you can do that:
println(banana: isYum()) # true
println(hotPepper: isYuck()) # true
🍌
🌶
let banana = SomeThing.Yum("🍌")
let hotPepper = SomeThing.Yuck("🌶")
println(banana: value())
println(hotPepper: value())
# you can do that:
println(banana: isYum()) # true
println(hotPepper: isYuck()) # true
let onlyBananas = |value| {
if value is "🍌" { return SomeThing.Yum(value)}
return SomeThing.Yuck("🌶")
}
if onlyBananas("🍋"): isYum() {
println("I 💙 bananas")
} else {
println("💔")
}
and… Augmentations
union SomeThing = {
Yum = { value } # good
Yuck = { value } # bad
}
augment SomeThing$Yum {
function so = |this, ifYum, ifYuck| -> ifYum(this: value())
}
augment SomeThing$Yuck {
function so = |this, ifYum, ifYuck| -> ifYuck(this: value())
}
union SomeThing = {
Yum = { value } # good
Yuck = { value } # bad
}
augment SomeThing$Yum {
function so = |this, ifYum, ifYuck| -> ifYum(this: value())
}
augment SomeThing$Yuck {
function so = |this, ifYum, ifYuck| -> ifYuck(this: value())
}
let onlyBananas = |value| {
if value is "🍌" { return SomeThing.Yum(value)}
return SomeThing.Yuck(value)
}
onlyBananas("🍋"): so(
|value| {
println("I 💙 " + value)
},
|value| {
println("I 💔 " + value)
})
Functional Errors
Golo is functional
Result (and Error)
Golo is functional
let toInt = |value| {
try {
return Result(Integer.parseInt(value))
} catch(e) {
return Error(e: getMessage())
}
}
let result = toInt("Fourty-two"): either(
|value| {
println("Succeed!")
return value
},
|err| {
println("Failed!" + err: message())
return 42
})
println(toInt("Hello"): orElse(42))
let toInt = |value| {
try {
return Result(Integer.parseInt(value))
} catch(e) {
return Error(e: getMessage())
}
}
let result = toInt("Fourty-two"): either(
|value| {
println("Succeed!")
return value
},
|err| {
println("Failed!" + err: message())
return 42
})
println(toInt("Hello"): orElse(42))
all is ok
ouch!
let toInt = |value| {
try {
return Result(Integer.parseInt(value))
} catch(e) {
return Error(e: getMessage())
}
}
let result = toInt("Fourty-two"): either(
|value| {
println("Succeed!")
return value
},
|err| {
println("Failed!" + err: message())
return 42
})
println(toInt("Hello"): orElse(42))
Trying
module ResultError
import gololang.Errors
function main = |args| {
# get a Result or an Error
trying({
return Integer.parseInt("Quarante-deux")
})
: either(
|value| {
println("Succeed!")
},
|err| {
println("Failed!" + err: message())
})
}
Golo ❤ Java
part 1
package acme;
import java.lang.String;
import java.lang.System;
public class Toon {
public String name;
private String nickName;
public String getNickName() { return nickName; }
public void setNickName(String value) { nickName = value; }
public Toon(String name) { this.name = name; }
public Toon() { this.name = "John Doe”; }
public void hi() { System.out.println("Hi, I'm " + this.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: hi()
buster: nickName("busty")
println(buster: nickName())
let elmira = Toon.getInstance("elmira")
println(elmira: name())
elmira: name("Elmira")
println(elmira: name())
elmira: hug(buster)
}
module toons
import acme
function main = |args| {
let buster = Toon("Buster") # no new
buster: hi()
buster: nickName("busty")
println(buster: nickName())
let elmira = Toon.getInstance("elmira")
println(elmira: name())
elmira: name("Elmira")
println(elmira: name())
elmira: hug(buster)
}
module toons
import acme
function main = |args| {
let buster = Toon("Buster") # no new
buster: hi()
buster: nickName("busty")
println(buster: nickName())
let elmira = Toon.getInstance("elmira")
println(elmira: name())
elmira: name("Elmira")
println(elmira: name())
elmira: hug(buster)
}
module toons
import acme
function main = |args| {
let buster = Toon("Buster") # no new
buster: hi()
buster: nickName("busty")
println(buster: nickName())
let elmira = Toon.getInstance("elmira")
println(elmira: name())
elmira: name("Elmira")
println(elmira: name())
elmira: hug(buster)
}
module toons
import acme
function main = |args| {
let buster = Toon("Buster") # no new
buster: hi()
buster: nickName("busty")
println(buster: nickName())
let elmira = Toon.getInstance("elmira")
println(elmira: name())
elmira: name("Elmira")
println(elmira: name())
elmira: hug(buster)
}
module toons
import acme
function main = |args| {
let buster = Toon("Buster") # no new
buster: hi()
buster: nickName("busty")
println(buster: nickName())
let elmira = Toon.getInstance("elmira")
println(elmira: name())
elmira: name("Elmira")
println(elmira: name())
elmira: hug(buster)
}
Augmentations again!
module toons2
import acme
augment acme.Toon {
function hi = |this, message| {
this: hi()
println("my message: " + message)
}
}
function main = |args| {
let buster = Toon("Buster") # no new
buster: hi("where is babs")
}
module toons2
import acme
augment acme.Toon {
function hi = |this, message| {
this: hi()
println("my message: " + message)
}
}
function main = |args| {
let buster = Toon("Buster") # no new
buster: hi("where is babs")
}
Golo ❤ Java
part 2
import spark.Spark
function main = |args| {
setPort(8888)
externalStaticFileLocation("public")
get("/hi", |request, response| {
response: type("text/plain")
return "Hi :earth_africa: at JDD 2016"
})
get("/hello", |request, response| {
response: type("application/json")
return JSON.stringify(
DynamicObject(): message("Hello :earth_africa: at JDD 2016")
)
})
}
import spark.Spark
augment spark.Response {
function jsonPayLoad = |this, content| {
this: type("application/json")
return JSON.stringify(content)
}
function textPayLoad = |this, content| {
this: type("text/plain")
return content
}
}
function main = |args| {
setPort(8888)
externalStaticFileLocation("public")
get("/hi", |request, response| ->
response: textPayLoad("Hi :earth_africa: at JDD 2016")
)
get("/hello", |request, response| ->
response: jsonPayLoad(
DynamicObject(): message("Hello :earth_africa: at JDD 2016")
)
)
}
a more functional way
get("/hi", |request, response| -> trying({
return "Hi :earth_africa: at JDD 2016"
})
: either(
|message| -> response: textPayLoad(message),
|error| -> response: textPayLoad(error: message())
))
get("/hello", |request, response| -> trying({
#let r = 42 / 0
return DynamicObject(): message("Hello :earth_africa: at JDD 2016")
})
: either(
|content| -> response: jsonPayLoad(content),
|error| -> response: jsonPayLoad(map[["message", error: message()]])
))
see it in action
I use Golo everyday (almost)
at work
setup a O demo
& faking a CI server
Hacking Golo
Demo
What else?
quickly
Decorators: kind of annotations
Workers: a little bit like JavaScript workers
Promises: asynchronous code
Observables: with a change event
Dynamic evaluation of code
and a lot of other things…
to conclude
http://golo-lang.org/
https://github.com/eclipse/golo-lang
https://github.com/k33g/
golo-jdd-2016/issues
Thank you & Thank you to JDD 😍
-
Questions? (speak slowly)

More Related Content

What's hot

The core libraries you always wanted - Google Guava
The core libraries you always wanted - Google GuavaThe core libraries you always wanted - Google Guava
The core libraries you always wanted - Google Guava
Mite Mitreski
 

What's hot (20)

Kotlin For Android - Functions (part 3 of 7)
Kotlin For Android - Functions (part 3 of 7)Kotlin For Android - Functions (part 3 of 7)
Kotlin For Android - Functions (part 3 of 7)
 
JVMLS 2016. Coroutines in Kotlin
JVMLS 2016. Coroutines in KotlinJVMLS 2016. Coroutines in Kotlin
JVMLS 2016. Coroutines in Kotlin
 
jQuery Data Manipulate API - A source code dissecting journey
jQuery Data Manipulate API - A source code dissecting journeyjQuery Data Manipulate API - A source code dissecting journey
jQuery Data Manipulate API - A source code dissecting journey
 
Google guava
Google guavaGoogle guava
Google guava
 
Google Guava
Google GuavaGoogle Guava
Google Guava
 
The core libraries you always wanted - Google Guava
The core libraries you always wanted - Google GuavaThe core libraries you always wanted - Google Guava
The core libraries you always wanted - Google Guava
 
Google Guava for cleaner code
Google Guava for cleaner codeGoogle Guava for cleaner code
Google Guava for cleaner code
 
Google Guava - Core libraries for Java & Android
Google Guava - Core libraries for Java & AndroidGoogle Guava - Core libraries for Java & Android
Google Guava - Core libraries for Java & Android
 
Meetup di GDG Italia - Leonardo Pirro - Codemotion Rome 2018
Meetup di GDG Italia - Leonardo Pirro -  Codemotion Rome 2018 Meetup di GDG Italia - Leonardo Pirro -  Codemotion Rome 2018
Meetup di GDG Italia - Leonardo Pirro - Codemotion Rome 2018
 
Elixir & Phoenix - fast, concurrent and explicit
Elixir & Phoenix - fast, concurrent and explicitElixir & Phoenix - fast, concurrent and explicit
Elixir & Phoenix - fast, concurrent and explicit
 
Google guava - almost everything you need to know
Google guava - almost everything you need to knowGoogle guava - almost everything you need to know
Google guava - almost everything you need to know
 
Ruby to Elixir - what's great and what you might miss
Ruby to Elixir - what's great and what you might missRuby to Elixir - what's great and what you might miss
Ruby to Elixir - what's great and what you might miss
 
Effective Java and Kotlin
Effective Java and KotlinEffective Java and Kotlin
Effective Java and Kotlin
 
Kotlin intro
Kotlin introKotlin intro
Kotlin intro
 
Best Practices in Plugin Development (WordCamp Seattle)
Best Practices in Plugin Development (WordCamp Seattle)Best Practices in Plugin Development (WordCamp Seattle)
Best Practices in Plugin Development (WordCamp Seattle)
 
Functional Programming In Java
Functional Programming In JavaFunctional Programming In Java
Functional Programming In Java
 
Power of Puppet 4
Power of Puppet 4Power of Puppet 4
Power of Puppet 4
 
Functional programming in java
Functional programming in javaFunctional programming in java
Functional programming in java
 
Real world gobbledygook
Real world gobbledygookReal world gobbledygook
Real world gobbledygook
 
Lean way write asynchronous code with Kotlin’s coroutines - Ronen Sabag, Gett
Lean way write asynchronous code with Kotlin’s coroutines - Ronen Sabag, GettLean way write asynchronous code with Kotlin’s coroutines - Ronen Sabag, Gett
Lean way write asynchronous code with Kotlin’s coroutines - Ronen Sabag, Gett
 

Viewers also liked

Viewers also liked (17)

Material didáctica enfocado al desarrollo de estrategias de comprensión lectora
Material didáctica enfocado al desarrollo de estrategias de comprensión lectoraMaterial didáctica enfocado al desarrollo de estrategias de comprensión lectora
Material didáctica enfocado al desarrollo de estrategias de comprensión lectora
 
Matrices 1
Matrices 1Matrices 1
Matrices 1
 
SCIENCE and EDUCATION a NEW DIMENSION PEDAGOGY and PSYCHOLOGY Issue 14
SCIENCE and EDUCATION a NEW DIMENSION PEDAGOGY and PSYCHOLOGY Issue 14SCIENCE and EDUCATION a NEW DIMENSION PEDAGOGY and PSYCHOLOGY Issue 14
SCIENCE and EDUCATION a NEW DIMENSION PEDAGOGY and PSYCHOLOGY Issue 14
 
Diapo c2I
Diapo c2IDiapo c2I
Diapo c2I
 
JavaOne 2016 - The JCP (Java Community Process)
JavaOne 2016 - The JCP (Java Community Process)JavaOne 2016 - The JCP (Java Community Process)
JavaOne 2016 - The JCP (Java Community Process)
 
Twitter: Failure to Innovate and Profit
Twitter: Failure to Innovate and ProfitTwitter: Failure to Innovate and Profit
Twitter: Failure to Innovate and Profit
 
Donostia
DonostiaDonostia
Donostia
 
Gaetano Bovenzi - Studio Legale Bovenzi
Gaetano Bovenzi - Studio Legale BovenziGaetano Bovenzi - Studio Legale Bovenzi
Gaetano Bovenzi - Studio Legale Bovenzi
 
SCIENCE and EDUCATION a NEW DIMENSION HUMANITIES and SOCIAL SCIENCE Issue 31
SCIENCE and EDUCATION a NEW DIMENSION HUMANITIES and SOCIAL SCIENCE Issue 31SCIENCE and EDUCATION a NEW DIMENSION HUMANITIES and SOCIAL SCIENCE Issue 31
SCIENCE and EDUCATION a NEW DIMENSION HUMANITIES and SOCIAL SCIENCE Issue 31
 
Lighting research
Lighting researchLighting research
Lighting research
 
SCIENCE and EDUCATION a NEW DIMENSION PEDAGOGY and PSYCHOLOGY Issue 43
SCIENCE and EDUCATION a NEW DIMENSION PEDAGOGY and PSYCHOLOGY Issue 43SCIENCE and EDUCATION a NEW DIMENSION PEDAGOGY and PSYCHOLOGY Issue 43
SCIENCE and EDUCATION a NEW DIMENSION PEDAGOGY and PSYCHOLOGY Issue 43
 
hospital admisstions
hospital admisstionshospital admisstions
hospital admisstions
 
Presentación power point uned redes sociales
Presentación power point uned redes sociales Presentación power point uned redes sociales
Presentación power point uned redes sociales
 
MATERI TIK BAB 6
MATERI TIK BAB 6MATERI TIK BAB 6
MATERI TIK BAB 6
 
PRONUNCIAMIENTO
 PRONUNCIAMIENTO  PRONUNCIAMIENTO
PRONUNCIAMIENTO
 
3 Tärkeää digitaalisen myyjän ominaisuutta
3 Tärkeää digitaalisen myyjän ominaisuutta3 Tärkeää digitaalisen myyjän ominaisuutta
3 Tärkeää digitaalisen myyjän ominaisuutta
 
We make your replacement windows in tx
We make your replacement windows in txWe make your replacement windows in tx
We make your replacement windows in tx
 

Similar to JDD 2016 - Philippe Charrière - Golo, The Tiny Language That Gives Super Powers

Your Library Sucks, and why you should use it.
Your Library Sucks, and why you should use it.Your Library Sucks, and why you should use it.
Your Library Sucks, and why you should use it.
Peter Higgins
 

Similar to JDD 2016 - Philippe Charrière - Golo, The Tiny Language That Gives Super Powers (20)

Thinking in Functions: Functional Programming in Python
Thinking in Functions: Functional Programming in PythonThinking in Functions: Functional Programming in Python
Thinking in Functions: Functional Programming in Python
 
Your Library Sucks, and why you should use it.
Your Library Sucks, and why you should use it.Your Library Sucks, and why you should use it.
Your Library Sucks, and why you should use it.
 
Geeks Anonymes - Le langage Go
Geeks Anonymes - Le langage GoGeeks Anonymes - Le langage Go
Geeks Anonymes - Le langage Go
 
Kotlin for android developers whats new
Kotlin for android developers whats newKotlin for android developers whats new
Kotlin for android developers whats new
 
FunctionalJS - George Shevtsov
FunctionalJS - George ShevtsovFunctionalJS - George Shevtsov
FunctionalJS - George Shevtsov
 
1. George Shevtsov - Functional JavaScript
1. George Shevtsov - Functional JavaScript1. George Shevtsov - Functional JavaScript
1. George Shevtsov - Functional JavaScript
 
Kotlin
KotlinKotlin
Kotlin
 
EcmaScript unchained
EcmaScript unchainedEcmaScript unchained
EcmaScript unchained
 
01 Introduction to Kotlin - Programming in Kotlin.pptx
01 Introduction to Kotlin - Programming in Kotlin.pptx01 Introduction to Kotlin - Programming in Kotlin.pptx
01 Introduction to Kotlin - Programming in Kotlin.pptx
 
Introduction to Kotlin.pptx
Introduction to Kotlin.pptxIntroduction to Kotlin.pptx
Introduction to Kotlin.pptx
 
Functional techniques in Ruby
Functional techniques in RubyFunctional techniques in Ruby
Functional techniques in Ruby
 
Functional techniques in Ruby
Functional techniques in RubyFunctional techniques in Ruby
Functional techniques in Ruby
 
A Skeptics guide to functional style javascript
A Skeptics guide to functional style javascriptA Skeptics guide to functional style javascript
A Skeptics guide to functional style javascript
 
Impress Your Friends with EcmaScript 2015
Impress Your Friends with EcmaScript 2015Impress Your Friends with EcmaScript 2015
Impress Your Friends with EcmaScript 2015
 
The Beauty of Java Script
The Beauty of Java ScriptThe Beauty of Java Script
The Beauty of Java Script
 
Dts x dicoding #2 memulai pemrograman kotlin
Dts x dicoding #2 memulai pemrograman kotlinDts x dicoding #2 memulai pemrograman kotlin
Dts x dicoding #2 memulai pemrograman kotlin
 
Scala introduction
Scala introductionScala introduction
Scala introduction
 
25-functions.ppt
25-functions.ppt25-functions.ppt
25-functions.ppt
 
Desarrollo para Android con Groovy
Desarrollo para Android con GroovyDesarrollo para Android con Groovy
Desarrollo para Android con Groovy
 
Practical Celery
Practical CeleryPractical Celery
Practical Celery
 

Recently uploaded

Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 
TrustArc Webinar - Unified Trust Center for Privacy, Security, Compliance, an...
TrustArc Webinar - Unified Trust Center for Privacy, Security, Compliance, an...TrustArc Webinar - Unified Trust Center for Privacy, Security, Compliance, an...
TrustArc Webinar - Unified Trust Center for Privacy, Security, Compliance, an...
TrustArc
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Victor Rentea
 

Recently uploaded (20)

Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
Introduction to use of FHIR Documents in ABDM
Introduction to use of FHIR Documents in ABDMIntroduction to use of FHIR Documents in ABDM
Introduction to use of FHIR Documents in ABDM
 
TrustArc Webinar - Unified Trust Center for Privacy, Security, Compliance, an...
TrustArc Webinar - Unified Trust Center for Privacy, Security, Compliance, an...TrustArc Webinar - Unified Trust Center for Privacy, Security, Compliance, an...
TrustArc Webinar - Unified Trust Center for Privacy, Security, Compliance, an...
 
Modernizing Legacy Systems Using Ballerina
Modernizing Legacy Systems Using BallerinaModernizing Legacy Systems Using Ballerina
Modernizing Legacy Systems Using Ballerina
 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with Milvus
 
Simplifying Mobile A11y Presentation.pptx
Simplifying Mobile A11y Presentation.pptxSimplifying Mobile A11y Presentation.pptx
Simplifying Mobile A11y Presentation.pptx
 
API Governance and Monetization - The evolution of API governance
API Governance and Monetization -  The evolution of API governanceAPI Governance and Monetization -  The evolution of API governance
API Governance and Monetization - The evolution of API governance
 
Six Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal OntologySix Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal Ontology
 
WSO2 Micro Integrator for Enterprise Integration in a Decentralized, Microser...
WSO2 Micro Integrator for Enterprise Integration in a Decentralized, Microser...WSO2 Micro Integrator for Enterprise Integration in a Decentralized, Microser...
WSO2 Micro Integrator for Enterprise Integration in a Decentralized, Microser...
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
 
Platformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityPlatformless Horizons for Digital Adaptability
Platformless Horizons for Digital Adaptability
 
JohnPollard-hybrid-app-RailsConf2024.pptx
JohnPollard-hybrid-app-RailsConf2024.pptxJohnPollard-hybrid-app-RailsConf2024.pptx
JohnPollard-hybrid-app-RailsConf2024.pptx
 
ChatGPT and Beyond - Elevating DevOps Productivity
ChatGPT and Beyond - Elevating DevOps ProductivityChatGPT and Beyond - Elevating DevOps Productivity
ChatGPT and Beyond - Elevating DevOps Productivity
 
Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
 

JDD 2016 - Philippe Charrière - Golo, The Tiny Language That Gives Super Powers

  • 1. Philippe Charrière O GitHub GOLO, THE TINY LANGUAGE THAT GIVES SUPER POWERS
  • 2. Philippe Charrière G @k33g U @k33g_org ⚠"# Golo committer
  • 3. “Another language for the JVM” - Agenda - The basis of Golo Some specific features How Golo ❤ Java I use it for my job How to hack Golo with Java or with Golo
  • 5. A research project > Julien Ponge @ CitiLab A dynamic language for the JVM Built from the first day with invokedynamic Light (~700 kb) and fast (in a dynamic context) U @jponge
  • 6.
  • 7.
  • 9. Easy to learn Easy to use Easy to hack Small
  • 10. a language to learn and try tiger("tigrou 🐯") : start(4, 2) : move(2): right(): left() : stop() : say("hello") DSL for children
  • 11. a language to learn and try IOT# firmata4j let myArduino = device(): port("/dev/cu.usbmodem1411") myArduino: initialize(): onSet(|self| { let redLed = self: getLedInstance("red", 13) redLed: switchOn() self: loop(50, |i| { redLed: blink(1000_L) }) }): onFail(|err| { println("Huston? We've got a problem!") })
  • 13. module operations function addition = |a, b| { return a + b } function multiplication = |a, b| -> a * b
  • 14. module operations function addition = |a, b| { return a + b } function multiplication = |a, b| -> a * b
  • 15. module operations function addition = |a, b| { return a + b } function multiplication = |a, b| -> a * b
  • 16. module operations function addition = |a, b| { return a + b } function multiplication = |a, b| -> a * b #!/usr/bin/env golosh module demo import operations function main = |args| { println(addition(40,2)) println(multiplication(21,2)) }
  • 17. #!/usr/bin/env golosh module demo import operations function main = |args| { println(addition(40,2)) println(multiplication(21,2)) } module operations function addition = |a, b| { return a + b } function multiplication = |a, b| -> a * b
  • 18. Run Golo scripts several ways golo command compilation (class and jar) as a shell script
  • 19. Run it #!/usr/bin/env golosh module demo import operations function main = |args| { println(addition(40,2)) println(multiplication(21,2)) }
  • 20. Run it chmod +x hello.golo ./hello.golo #!/usr/bin/env golosh module demo import operations function main = |args| { println(addition(40,2)) println(multiplication(21,2)) }
  • 21. Run it ./ !"" libs !"" libA.jar !"" libB.jar !"" commons !"" utils.golo !"" others.golo !"" vendors !"" otherlib.jar !"" hello.golo #!/usr/bin/env golosh module demo import operations function main = |args| { println(addition(40,2)) println(multiplication(21,2)) }
  • 24. #!/usr/bin/env golosh module demo function main = |args| { let division = |a,b| { return a/b } try { println(division(84, 0)) } catch (err) { println("😡: " + err: message()) } }
  • 25. Simple and Efficient Composition rather than Inheritance Mixed approach (object / functional)
  • 27. struct human = { firstName, lastName }
  • 28. module demo1_structure struct human = { firstName, lastName } function main = |args| { # no new keyword let john = human("John", "Doe") # named parameters let jane = human(firstName="Jane", lastName="Doe") # colon notation let bob = human(): firstName("Bob"): lastName("Morane") println("Hello, I'm " + bob: firstName() + " " + bob: lastName()) }
  • 29. module demo1_structure struct human = { firstName, lastName } function main = |args| { # no new keyword let john = human("John", "Doe") # named parameters let jane = human(firstName="Jane", lastName="Doe") # colon notation let bob = human(): firstName("Bob"): lastName("Morane") println("Hello, I'm " + bob: firstName() + " " + bob: lastName()) }
  • 30. module demo1_structure struct human = { firstName, lastName } function main = |args| { # no new keyword let john = human("John", "Doe") # named parameters let jane = human(firstName="Jane", lastName="Doe") # colon notation let bob = human(): firstName("Bob"): lastName("Morane") println("Hello, I'm " + bob: firstName() + " " + bob: lastName()) }
  • 31. module demo1_structure struct human = { firstName, lastName } function main = |args| { # no new keyword let john = human("John", "Doe") # named parameters let jane = human(firstName="Jane", lastName="Doe") # colon notation let bob = human(): firstName("Bob"): lastName("Morane") println("Hello, I'm " + bob: firstName() + " " + bob: lastName()) } ⚠
  • 33. module demo_structure struct human = { firstName, lastName } augment human { # this is a ref to human structure function sayHello = |this| -> "Hello, I'm " + this: firstName() + " " + this: lastName() } function main = |args| { # colon notation let jane = human() : firstName("Jane") : lastName("Doe") println(jane: sayHello()) }
  • 34. module demo_structure struct human = { firstName, lastName } augment human { function sayHello = |this| -> "Hello, I'm " + this: firstName() + " " + this: lastName() } function Human = |firstName, lastName| { # I'm the human constructor return human(firstName, lastName) } function main = |args| { # colon notation let jane = Human("Jane", "Doe") println(jane: sayHello()) } kind of constructor
  • 35. No Class! Part 2 but…
  • 37. module demo_dynamicobjects function main = |args| { let jane = DynamicObject() : firstName("Jane") : lastName("Doe") : define(“sayHello”, |this| { return "Hello, I'm " + this: firstName() + " " + this: lastName() }) println(jane: sayHello()) }
  • 38. module demo_dynamicobjects function main = |args| { let jane = DynamicObject() : firstName("Jane") : lastName("Doe") : define(“sayHello”, |this| { return "Hello, I'm " + this: firstName() + " " + this: lastName() }) println(jane: sayHello()) }
  • 39. module demo_dynamicobjects function Human = |firstName, lastName| { # I'm the human constructor return DynamicObject() : firstName(firstName) : lastName(lastName) : define(“sayHello”, |this| { return "Hello, I'm " + this: firstName() + " " + this: lastName() }) } function main = |args| { let jane = Human("Jane", "Doe") println(jane: sayHello()) }
  • 42. function as output & input module demo_func_01 function addition = |a, b| { return a + b } function main = |args| { # function as output let add = |a| { return |b| { return addition(a,b) } } let addOne = add(1) println(addOne(41)) # 42 println( list[1, 2, 3, 4, 5]: map(addOne) # [2, 3, 4, 5, 6] ) }
  • 43. function as output & input module demo_func_01 function addition = |a, b| { return a + b } function main = |args| { # function as output let add = |a| { return |b| { return addition(a,b) } } let addOne = add(1) println(addOne(41)) # 42 println( list[1, 2, 3, 4, 5]: map(addOne) # [2, 3, 4, 5, 6] ) } # function as input
  • 44. module demo_func_01 function addition = |a, b| { return a + b } function main = |args| { let add = |a| -> |b| -> addition(a,b) let addOne = add(1) println( list[1, 2, 3, 4, 5] : map(addOne) # [2, 3, 4, 5, 6] : map(addOne) # [3, 4, 5, 6, 7] ) } function as output & input
  • 45. module demo_func_01 function addition = |a, b| { return a + b } function main = |args| { let add = |a| -> |b| -> addition(a,b) let addOne = add(1) println( list[1, 2, 3, 4, 5] : map(addOne) # [2, 3, 4, 5, 6] : map(addOne) # [3, 4, 5, 6, 7] ) } function as output & input
  • 47. no iteration let noChips = |food| -> food isnt "🍟" # return true if it's not chips let noOnion = |food| -> food isnt “😭" noChips("🍞") == true noChips("🍟") == false
  • 48. no iteration let noChips = |food| -> food isnt "🍟" let noOnion = |food| -> food isnt "😭" let cutFood = |food| -> "piece of " + food let Food = list[ "🍞" , "🍃" , "🍅" , "🍖" , "🍟" , "😭" # 😡 can't find onion emoji ]
  • 49. no iteration let myKebabRecipe = Food : filter(noChips) : filter(noOnion) : map(cutFood) [🍞, 🍃, 🍅, 🍖, 😭] [piece of 🍞, piece of 🍃, piece of 🍅, piece of 🍖] [🍞, 🍃, 🍅, 🍖] [🍞, 🍃, 🍅, 🍖, 🍟, 😭]
  • 50. no iteration # ⚡ preparing kebab with myKebabRecipe let mixFood = |accFood, nextFood| -> accFood + nextFood + " " let kebab = myKebabRecipe : reduce("🌮 with: ", mixFood) [piece of 🍞, piece of 🍃, piece of 🍅, piece of 🍖] 🌮 with: piece of 🍞 piece of 🍃 piece of 🍅 piece of 🍖
  • 51. Union Types Golo is functional
  • 52. module SomeThing union SomeThing = { Yum = { value } # good Yuck = { value } # bad } # you're good or bad, but not good and bad
  • 53. module SomeThing union SomeThing = { Yum = { value } # good Yuck = { value } # bad } # you're good or bad, but not good and bad
  • 54. let banana = SomeThing.Yum("🍌") let hotPepper = SomeThing.Yuck("🌶") println(banana: value()) println(hotPepper: value()) # you can do that: println(banana: isYum()) # true println(hotPepper: isYuck()) # true union SomeThing.Yum{value=🍌} 🍌 🌶 union SomeThing.Yuck{value=🌶}
  • 55. let banana = SomeThing.Yum("🍌") let hotPepper = SomeThing.Yuck("🌶") println(banana: value()) println(hotPepper: value()) # you can do that: println(banana: isYum()) # true println(hotPepper: isYuck()) # true 🍌 🌶
  • 56. let banana = SomeThing.Yum("🍌") let hotPepper = SomeThing.Yuck("🌶") println(banana: value()) println(hotPepper: value()) # you can do that: println(banana: isYum()) # true println(hotPepper: isYuck()) # true
  • 57. let onlyBananas = |value| { if value is "🍌" { return SomeThing.Yum(value)} return SomeThing.Yuck("🌶") } if onlyBananas("🍋"): isYum() { println("I 💙 bananas") } else { println("💔") }
  • 59. union SomeThing = { Yum = { value } # good Yuck = { value } # bad } augment SomeThing$Yum { function so = |this, ifYum, ifYuck| -> ifYum(this: value()) } augment SomeThing$Yuck { function so = |this, ifYum, ifYuck| -> ifYuck(this: value()) }
  • 60. union SomeThing = { Yum = { value } # good Yuck = { value } # bad } augment SomeThing$Yum { function so = |this, ifYum, ifYuck| -> ifYum(this: value()) } augment SomeThing$Yuck { function so = |this, ifYum, ifYuck| -> ifYuck(this: value()) }
  • 61. let onlyBananas = |value| { if value is "🍌" { return SomeThing.Yum(value)} return SomeThing.Yuck(value) } onlyBananas("🍋"): so( |value| { println("I 💙 " + value) }, |value| { println("I 💔 " + value) })
  • 63. Result (and Error) Golo is functional
  • 64. let toInt = |value| { try { return Result(Integer.parseInt(value)) } catch(e) { return Error(e: getMessage()) } } let result = toInt("Fourty-two"): either( |value| { println("Succeed!") return value }, |err| { println("Failed!" + err: message()) return 42 }) println(toInt("Hello"): orElse(42))
  • 65. let toInt = |value| { try { return Result(Integer.parseInt(value)) } catch(e) { return Error(e: getMessage()) } } let result = toInt("Fourty-two"): either( |value| { println("Succeed!") return value }, |err| { println("Failed!" + err: message()) return 42 }) println(toInt("Hello"): orElse(42)) all is ok ouch!
  • 66. let toInt = |value| { try { return Result(Integer.parseInt(value)) } catch(e) { return Error(e: getMessage()) } } let result = toInt("Fourty-two"): either( |value| { println("Succeed!") return value }, |err| { println("Failed!" + err: message()) return 42 }) println(toInt("Hello"): orElse(42))
  • 67. Trying module ResultError import gololang.Errors function main = |args| { # get a Result or an Error trying({ return Integer.parseInt("Quarante-deux") }) : either( |value| { println("Succeed!") }, |err| { println("Failed!" + err: message()) }) }
  • 69. package acme; import java.lang.String; import java.lang.System; public class Toon { public String name; private String nickName; public String getNickName() { return nickName; } public void setNickName(String value) { nickName = value; } public Toon(String name) { this.name = name; } public Toon() { this.name = "John Doe”; } public void hi() { System.out.println("Hi, I'm " + this.name); } public static Toon getInstance(String name) { return new Toon(name); } public void hug(Toon toon) { System.out.println("I 💙 " + toon.name); } }
  • 70. module toons import acme function main = |args| { let buster = Toon("Buster") # no new buster: hi() buster: nickName("busty") println(buster: nickName()) let elmira = Toon.getInstance("elmira") println(elmira: name()) elmira: name("Elmira") println(elmira: name()) elmira: hug(buster) }
  • 71. module toons import acme function main = |args| { let buster = Toon("Buster") # no new buster: hi() buster: nickName("busty") println(buster: nickName()) let elmira = Toon.getInstance("elmira") println(elmira: name()) elmira: name("Elmira") println(elmira: name()) elmira: hug(buster) }
  • 72. module toons import acme function main = |args| { let buster = Toon("Buster") # no new buster: hi() buster: nickName("busty") println(buster: nickName()) let elmira = Toon.getInstance("elmira") println(elmira: name()) elmira: name("Elmira") println(elmira: name()) elmira: hug(buster) }
  • 73. module toons import acme function main = |args| { let buster = Toon("Buster") # no new buster: hi() buster: nickName("busty") println(buster: nickName()) let elmira = Toon.getInstance("elmira") println(elmira: name()) elmira: name("Elmira") println(elmira: name()) elmira: hug(buster) }
  • 74. module toons import acme function main = |args| { let buster = Toon("Buster") # no new buster: hi() buster: nickName("busty") println(buster: nickName()) let elmira = Toon.getInstance("elmira") println(elmira: name()) elmira: name("Elmira") println(elmira: name()) elmira: hug(buster) }
  • 75. module toons import acme function main = |args| { let buster = Toon("Buster") # no new buster: hi() buster: nickName("busty") println(buster: nickName()) let elmira = Toon.getInstance("elmira") println(elmira: name()) elmira: name("Elmira") println(elmira: name()) elmira: hug(buster) }
  • 77. module toons2 import acme augment acme.Toon { function hi = |this, message| { this: hi() println("my message: " + message) } } function main = |args| { let buster = Toon("Buster") # no new buster: hi("where is babs") }
  • 78. module toons2 import acme augment acme.Toon { function hi = |this, message| { this: hi() println("my message: " + message) } } function main = |args| { let buster = Toon("Buster") # no new buster: hi("where is babs") }
  • 80.
  • 81. import spark.Spark function main = |args| { setPort(8888) externalStaticFileLocation("public") get("/hi", |request, response| { response: type("text/plain") return "Hi :earth_africa: at JDD 2016" }) get("/hello", |request, response| { response: type("application/json") return JSON.stringify( DynamicObject(): message("Hello :earth_africa: at JDD 2016") ) }) }
  • 82. import spark.Spark augment spark.Response { function jsonPayLoad = |this, content| { this: type("application/json") return JSON.stringify(content) } function textPayLoad = |this, content| { this: type("text/plain") return content } }
  • 83. function main = |args| { setPort(8888) externalStaticFileLocation("public") get("/hi", |request, response| -> response: textPayLoad("Hi :earth_africa: at JDD 2016") ) get("/hello", |request, response| -> response: jsonPayLoad( DynamicObject(): message("Hello :earth_africa: at JDD 2016") ) ) }
  • 85. get("/hi", |request, response| -> trying({ return "Hi :earth_africa: at JDD 2016" }) : either( |message| -> response: textPayLoad(message), |error| -> response: textPayLoad(error: message()) )) get("/hello", |request, response| -> trying({ #let r = 42 / 0 return DynamicObject(): message("Hello :earth_africa: at JDD 2016") }) : either( |content| -> response: jsonPayLoad(content), |error| -> response: jsonPayLoad(map[["message", error: message()]]) ))
  • 86. see it in action
  • 87. I use Golo everyday (almost) at work
  • 88.
  • 89. setup a O demo & faking a CI server
  • 91. Demo
  • 93. Decorators: kind of annotations Workers: a little bit like JavaScript workers Promises: asynchronous code Observables: with a change event Dynamic evaluation of code and a lot of other things…
  • 97. Thank you & Thank you to JDD 😍 - Questions? (speak slowly)