A la découverte de Golo

En dĂ©but d’annĂ©e, j’ai eu la chance de contribuer Ă  un projet open-source en tant que testeur (utilisateur qui s’amuse). Ce projet c’est Golo http://golo-lang.org/, un langage qui “tourne” dans la JVM Java. Encore un! me direz vous ? Et pourquoi pas ? Son crĂ©ateur @jponge explique trĂšs bien le comment du pourquoi (ainsi que les spĂ©cificitĂ©s) par ici https://speakerdeck.com/jponge/golo-at-devoxx-france-2013, mais aussi par lĂ  https://speakerdeck.com/jponge/golo-au-lyonjug-mars-2013, ou bien en avant premiĂšre en Auvergne https://speakerdeck.com/jponge/golo-au-lavajug.

Au passage, merci Ă  @hgomez qui m’a parlĂ© de ce projet, ce qui m’a permis d’aller em
 @jponge pour ĂȘtre testeur.

Cette expĂ©rience a Ă©tĂ©, est (sera) enrichissante techniquement (faut utiliser Golo pour comprendre), humainement : j’ai eu le plaisir de voir que je ne suis pas le seul geek “senior” avec des idĂ©es Ă  la c
 en rĂ©gion, @titimoby si tu me lis ;) NDA : il est beaucoup plus jeune que moi.

J’ai doucement caressĂ© le rĂȘve de faire une prez Ă  Mix-IT sur le sujet avec @titimoby, ça n’a pas marchĂ© :( mais quand on voit le niveau des speakers 2013, c’est comprĂ©hensible :) et vivement les 25 et 26 avril. Du coup j’écrit ici une partie de ce que je voulais prĂ©senter.

Mais ça suffit pour les blablas, passons tout de suite à la pratique et voyons comment faire “gologolo en douceur”. Je ne vous parlerais pas des “basiques” (if, while, for ...) pour ça il y a une documentation trùs bien faite http://golo-lang.org/documentation/next/. Je vais juste vous montrer comment j’utilise Golo, aprùs chacun son style ;).

Ceci n’est qu’un 1er aperçu des possibilitĂ©s de Golo.

Installons

1ùre fois 
 Toute 1ùre fois

Telle une jeune vierge effarouchĂ©e Ă  son premier rendez vous, vous ĂȘtes tout fĂ©brile, comment allez-vous vous en sortir ? Pas de problĂšme, c’est facile. Avec votre Ă©diteur de texte prĂ©fĂ©rĂ© (votre serviteur a fait un mini support pour Sublime Text 2 : https://github.com/k33g/sublime-golo), crĂ©ez votre premier fichier golo : hello.golo avec ceci (incontournable) :

module hello

function main = |args| {
	println("Salut Ă  tous!")
}

et dans un terminal tapez ceci : gologolo hello.golo et lĂ  sans surprise vous obtiendrez Salut Ă  tous!. Soyez fous et modifiez votre code de la maniĂšre suivante :

module hello

function main = |args| {
	println("Salut " + aget(args, 0))
}

puis (encore dans le terminal) : gologolo hello.golo --args Bob et là vous obtiendrez 
 Salut Bob.

Explications

aget(args, 0) prend le 1er Ă©lĂ©ment (index 0) du tableau d’arguments. Pour une description de la gestion des Arrays en Golo c’est par lĂ  http://golo-lang.org/documentation/next/# _arrays

2Ăšme fois : import

VoilĂ , vous avez fait “gologolo”, vous pouvez passer au niveau supĂ©rieur (on reste dĂ©butant mais on prend un peu d’assurance).

Créez un fichier tools.golo :

module tools

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

function add = |a, b| {
	return a + b
}

function sub =|a, b| -> a-b

puis un fichier main.golo :

module main

import tools

function main = |args| {
	hello("Douglas Adams")
	println(add(40, 2))
	println(sub(44, 2))
}

Nous avons donc fait un import de nos fonctions du module tools. Soit dis en passant nous pourrions appeler nos fonctions de cette maniĂšre tools.hello("Douglas Adams"), tools.add(40, 2), tools.sub(44, 2).

Pour lancer, utilisez la commande suivante : gologolo tools.golo main.golo et vous obtiendrez :

Salut Douglas Adams
42
42

Au fait, vous avez vu ? Vous avez une formulation “compacte” de function sub =|a, b| -> a-b utilisĂ©e pour les closures, pour creuser le sujet http://golo-lang.org/documentation/next/# _closures

Un peu plus de sport ? De l’objet, de l’objet !

Alors, probablement la chose que je prĂ©fĂšre dans Golo (mais c’est trĂšs personnel) : le DynamicObject().

De nous jours, si dans un langage on ne peut plus faire d’objet, ce n’est pas drĂŽle. Eh bien en Golo, pour cela nous avons les DynamicObjects. Un DynamicObject est un objet auquel on peut rajouter dynamiquement des propriĂ©tĂ©s (getters/setters) et des mĂ©thodes.

KĂ©zaco ?

Parlons peu, parlons bien, un exemple est plus parlant qu’un long discours (et blablablabla 
) :

module human

function main = |args| {

	var bob = -> DynamicObject():
		firstName("Bob"):lastName("Morane"):
		define("sayHello", |this|-> println("Hello i'm "+ this:firstName()+" "+ this:lastName()))

	println(bob():firstName())
	println(bob():lastName())

	bob():sayHello()

}

qui a l’exĂ©cution nous affichera :

Bob
Morane
Hello i'm Bob Morane

# On récapitule

  • Pour ajouter une propriĂ©tĂ© : property_name() ou property_name(default_value)
  • Pour ajouter une 2Ăšme propriĂ©tĂ©, la notation est “chaĂźnĂ©e” (Ă  la jQuery) : property_one_name():property_two_name()
  • Pour ajouter une mĂ©thode : define("method_name", |this, parameter| { # foo ... }) (toujours le this en 1er paramĂštre de mĂ©thode, le # c’est pour les commentaires)
  • Pour utiliser l’objet ainsi dĂ©fini, bob() les () sont importantes, cela correspond Ă  une instanciation
  • Pour utiliser un “membre” de bob, on utilise :, par exemple bob():firstName() retourne la valeur de firstName et bob():firstName("Bobby") change la valeur de firstName
  • il est possible d’ajouter des propriĂ©tĂ©s Ă  la volĂ©e Ă  l’instance bob() de bob

Le DynamicObject utilisé comme une classe ?

Pour se faire, ce n’est pas difficile, on externalise le DynamicObject de main par le biais d’une fonction.

module human

function Human = -> DynamicObject():
	firstName("John"):
	lastName("Default"):
	define("sayHello", |this| {
			println("Hello i'm "+ 
				this:firstName()+" "+ 
				this:lastName()
			)
	})

function main = |args| {

	var bob = Human(): firstName("Bob"): lastName("Morane")

	println(bob:firstName())
	println(bob:lastName())

	bob:sayHello()

}
  • vous remarquerez que bob n’a plus de () puisque l’on a fait une affectation de l’instance de Human()
  • vous remarquerez aussi que l’on set les propriĂ©tĂ©s “inline et Ă  la chaĂźne” : Human(): firstName("Bob"): lastName("Morane")
  • vous remarquez que cette fois-ci j’ai mis un espace aprĂšs les :, c’est juste pour faire joli, ce n’est pas obligatoire

et vous obtiendrez donc :

Bob
Morane
Hello i'm Bob Morane

Hop hop hop, je n’ai pas de constructeur ?

Eh bien non, mais cela se contourne trĂšs bien, il suffit de vous crĂ©er une mĂ©thode intialize (en fait vous l’appelez comme vous voulez) qui retourne l’objet lui mĂȘme :

module human

function Human = -> DynamicObject():
	firstName("John"):
	lastName("Default"):
	define("initialize", |this, firstName, lastName| { # mon constructeur

		this: firstName(firstName)
		this: lastName(lastName)
		return this
	}):
	define("sayHello", |this| {
			println("Hello i'm "+ 
				this:firstName()+" "+ 
				this:lastName()
			)
	})

function main = |args| {

	var bob = Human(): initialize("Bob", "Morane")

	println(bob:firstName())
	println(bob:lastName())

	bob:sayHello()

}

OK, mais l’hĂ©ritage, tu fais comment ?

L’hĂ©ritage cĂ©mal, la composition c’est bien. Ok, c’est pas faux. Mais comme @jponge il est trĂšs sympa (et que moi, je peux ĂȘtre lourdement pĂ©nible) il nous a ajoutĂ© un petit truc bien pratique : le mixin() qui ne dĂ©paysera en rien les amoureux du javascript et de la programmation fonctionnelle. Le mixin() copie les membres d’un DynamicObject sur un autre.

module human

function Human = -> DynamicObject():
	firstName("John"):
	lastName("Default"):
	define("initialize", |this, firstName, lastName| {
		this: firstName(firstName)
		this: lastName(lastName)
		return this
	}):
	define("sayHello", |this| {
			println("Hello i'm "+ 
				this:firstName()+" "+ 
				this:lastName()
			)
	})

function SuperHero = -> DynamicObject():
	mixin(Human()): # sorte d'héritage fonctionnel

	define("savePeople", |this| {
		println(this: name() + " is saving people")
	})

function main = |args| {

	var clark = SuperHero(): initialize("Clark", "Kent"): name("SuperMan")

	println(clark: firstName())
	println(clark: lastName())

	clark: sayHello()
	clark: savePeople()

}

Nous obtiendrons :

Clark
Kent
Hello i'm Clark Kent
SuperMan is saving people

Remarque : la position du mixin() dans la définition du DynamicObject est importante si vous surchargez des membres (attention de ne pas les écraser).

Fun & pratique :)

Si vous souhaitez en savoir plus sur les DynamicObjects, RTFM : http://golo-lang.org/documentation/next/# _dynamic_objects.

C’est tout pour aujourd’hui, dans les prochains Ă©pisodes, nous verrons (peut-ĂȘtre pas dans cette ordre):

  • Golo parle Ă  Java, mais Java aussi (on parlera un peu des closures quand mĂȘme)
  • Golo et les Workers, ou comment se la jouer avec les threads
  • 
 je vous parlerez aussi de ma stack web en pur Golo (un mini Play!>Framework en Golo)

Utilisez le, c’est l’adopter!

Si vous faites des petites fonctions sympa, des mini frameworks (ou mĂȘme mega) vous pouvez aller les enregistrer ici pour montrer votre support : http://k33g.github.com/nano.golo/. Si vous aves des question, c’est chez Stackoverflow aussi : http://stackoverflow.com/questions/tagged/golo-lang.

Bientît le week-end, profitez-en pour faire gologolo 
 (je sais 
)

blog comments powered by Disqus

Related posts