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