Affichage des articles dont le libellé est meta. Afficher tous les articles
Affichage des articles dont le libellé est meta. Afficher tous les articles

lundi 22 mars 2010

Tumblelog de jeu

Je viens de me lancer dans un nouveau blog (oui, je sais, vu l'activité de ce celui-ci...) à propos de jeu(x), toutes catégories confondus : jeux de plateaux, jeux de rôle, jeux vidéos (de préférence libres ou indés si possible...) et autres.

C'est l'occasion de faire mes petites fiches de jeu, de me remettre un peu à publier sur un sujet qui me plait, et accessoirement de tester Tumblr qui me parait être une plate-forme bien pratique...

jeudi 15 mai 2008

Ruby : Création dynamique de méthodes

Ola Bini vient de publier un article très bien fait sur les différentes façons disponibles en Ruby pour la création dynamique de méthodes.


Pour cela, il envisage trois voies : le def classique, la méthode define_method ou l'une de ces deux dans un eval. Plusieurs paramètres importants dans le choix de la méthode utilisée :

De façon assez amusante, il recommande pour des questions de vitesse, surtout, d'utiliser en priorité le def classique. Juste pour l'exemple, voici le code d'une définition par def, dans un eval :

class Foo
end

bar = Foo.new
method_name = :something

eval "def bar.#{method_name}; puts 'Hi !'; end"

bar.method(method_name).call
#=> Hi !



dimanche 27 avril 2008

MetaTricks : Un petit DSL

Depuis quelques temps, j'avais envie de tester s'il était facile ou non d'implémenter un petit DSL (ou Domain Specific Language) en Ruby. Il se trouve que plutôt, oui. Le code collé chez Pastie :


Le langage que je vous propose est loin d'être Turing-complet : ce n'est pas le but. Dans sa forme actuelle, il gère les transferts entre les "comptes" de plusieurs personnes grâce à une syntaxe en anglais. Trois verbes disponibles : donner, recevoir et avoir. Les phrases sont formées de la façon suivante :

"Sujet" "Verbe" "Somme" $ [complément]

Avec pour complément facultatif :

"Cibleur" "Second compte"

Il est possible de commenter une ligne en la commençant par "--" (comme en Ada !). Un "cibleur" ('to' ou 'from') désigne un autre compte. Attention, pour des raisons de blocage mental de ma part à l'approche d'une Regexp, la somme d'argent doit être un entier, et non un flottant. Pas de centimes pour les vrais. Ah, oui, et pas de point à la fin des phrases. Il parait que ça sert à rien(.)

Un exemple ?

-- Marie is cool:
Marie gives 5 $ to Peter
Marie has 10 $
Marie receives 15 $ from Peter
Peter gives 10 $ to Simon because he previously borrowed him...
-- Marion is Marie's dark-twin...
Sobe receives 1 $ from Marion
-- But Sobe's a gangsta who gat connectionz so:
Sobe receives 100000 $ like this !


est valable, et donnera :

--------------------
-= Report =-
--------------------
Number of accounts: 5
Marie owns 25.0 $.
Peter lost 20.0 $.
Simon earned 10.0 $.
Sobe earned 100001.0 $.
Marion lost 1.0 $.

C'est loin d'être parfait, mais le corps de l'interprète fait à peine 200 lignes. Je suis juste un peu déçu de ne pas avoir davantage employé les outils de la métaprogrammation : je passe sans doute trop par de l'analyse de chaîne de caractère, opération en soit risquée.

Tout commentaire ou critique vivement apprécié(e).

mercredi 23 avril 2008

Ruby : Sécuriser la redéfinition de méthode

Etant un peu angoissé de nature, il y a un truc qui me tracasse en Ruby depuis quelques temps : l'absence de warning à la redéfinition de méthodes existantes. Un exemple ?




class Object
def self.new
puts "Oh dude !"
end
end

a = Array.new 46
#=> **Judgement Day**


Ceci devrait bien vous convaincre de l'utilité d'avertir le programmeur durant le développement. Rappelons aussi que Object.methods dénombre 77 méthodes pour cette racine de tout objet en Ruby...

Du coup, voilà un petit trick qui permet de sécuriser ce point, grâce à la méthode de classe method_added :


class Object
def self.method_added sym
if self.methods.include? sym.to_s then
print "WARNING: method #{sym}" + \\
"of class #{self} redefined\n"

end
end
end

class Integer
def clone
puts "I'm your dark twin !"
end
end
#=> WARNING: method clone of class Integer redefined

lundi 7 avril 2008

MetaTricks : Ciseaux pour enfants

Les 28 et 29 Mars derniers a eu lieu la MountainWest RubyConf 2008, une série de présentations sur la programmation en Ruby. Il y a beaucoup de conférences de Rubyistes et de Railistes à travers le monde (certains en sont d'ailleurs agacés...), mais celle-ci me semble avoir été particulièrement riche, avec des sujets très intéressants : DSL, cœur du langage, écosystème général, et... métaprogrammation.

Je n'ai pas la chance d'avoir été sur place mais, miracle du web oblige, les vidéos des différentes présentations sont disponibles (en bonne voire très bonne qualité, avec les slides en direct) à cette page. Merci Confreaks !

La présentation de Giles Bowkett est particulièrement réussie :


Giles Bowkett, dont j'ai régulièrement parlé ici (générateur de MIDI en Ruby, métaprogrammation...), y parle bien sûr de métaprog' et de génération "automatique" de code, le premier étant un outil pour le second.
Il est assez difficile de résumer ce type de présentation en quelques mots, et je vais donc lancer ça en vrac :

  • Archimède et mathématiques par les cercles en Grèce.
  • Les Rubyistes pratiquent des "langages exotiques" : Scala, Erlang, Haskell, Lisp, Io, Scheme, Smalltalk... mais ne parle pas Grec !
  • De Pi "The Circle" à Lambda "The Ultimate" en LISP.
  • 3 piliers improbables : Rubinius, Nodebox et "code == data".
  • Ruby2ruby
  • "Monkeypatch Monkeypatching is Metamonkeypatching"
  • Avantages économiques de la génération de code.
  • Pub pour "Code Generation in Action"...
  • De Java à Rails en passant par LISP (et Perl ! (et Smalltalk !)).
  • "Skilled programmers can write better programmers than they can hire."
Avec de l'humour absurde au milieu, du code en live et de la bonne humeur... Très agréable à regarder. Les deux seuls reproches que je pourrais faire sont d'une part qu'il passe un peu trop vite (à mon goût) de l'"historique" à la pratique, et d'autre part que les domaines d'applications proposés en exemple ne me paraissent pas assez ambitieux, surtout venant de lui ; G. Bowkett n'étant pas le dernier des n00bs : parmi ses petites réalisations persos on trouve autre chose que des applis en Rails : API pour le robot Lego, générateur de MIDI, programmation graphique, diverses gems... visitez son site ! (ou retrouvez les autres présentations ici.)

lundi 18 février 2008

MetaTricks : référence à une méthode

En Ruby, tout ou presque est objet. Les méthodes sont des objets comme les autres, sauf qu'il n'est pas forcément évident au premier abord d'y avoir accès. Pour cela, on utilise des références, manipulées comme dans le code suivant.

Code :
(Testé sous Windows XP ; Ruby 1.8.6)



class Canard
def initialize name
@nom = name
end

def coin
"Coin coin, I'm #{@nom} !"
end

def Canard.coin2
"Can Can !"
end
end

toto = Canard.new "Dude"

# L'accès à une méthode se fait via +method+
#prenant en argument la référence de la méthode
#(son nom sous forme de string ou de symbol).
hello = toto.method(:coin)
puts hello.call

#(bonus -> arity donne le nombre d'arguments d'une méthode)
puts "To create a new *Canard* needs " \
+ (toto.method(:initialize).arity).to_s \
+ " argument(s)."

# Une liste de références à des méthodes de +Canard+
meths = [:to_s, :to_something_else, :coin, "to_yaml"]

# L'accès se fait ensuite ici encore via +method+
#et l'appel via +call+
meths.each do |meth|
begin
puts "-----------------"
puts "Method #{meth}"
puts (toto.method(meth).call).to_s
rescue
puts "Problem with this method."
next
end
end


Note :

Les manipulations possibles sur les méthodes sont peu nombreuses, mais assez puissantes. Ici on a vu call et arity : unbind permet elle de "dissocier" la méthode référencée de son receveur (ce qui donne un objet de la classe UnboundMethod...)

Documentation :

lundi 28 janvier 2008

MetaTricks : Présentation DSL en Ruby

Une présentation très intéressante de la métaprogrammation, et de sa mise en pratique pour la conception de langages dédiés (DSL en anglais), lors du Belgian Ruby User Group meeting du 3 Octobre 2007.

  • Vidéo et sources du DSL présenté : chez XAOP
  • Slides de la présentation en PDF (recommendés pour suivre la vidéo) : sur RubyForge
XAOP est une société informatique Belge utilisant entre autre Ruby.

Dans un premier temps, la présentation revient sur la définition de la métaprogrammation et d'un DSL (en insistant sur le fait que cette notion dépend fortement de l'angle par lequel on regarde un langage donné). Est ensuite discutée la facilité de métaprogrammation en Ruby (comparé au Java notamment).
La seconde partie concerne plus particulièrement les techniques employées pour la conception de langage dédié (exemple d'une banque) : gestion de self, constantes et méthodes manquantes et personnalisation des opérateurs notamment (et petites allusions à Rails).

jeudi 17 janvier 2008

MetaTricks : define_method

Un bon programmeur est un programmeur feignant... Et en Ruby, il existe une façon relativement simple d'éviter de coder : la méthode define_method. De quoi devenir vraiment feignant (donc vraiment bon !) grâce à la métaprogrammation !


L'exemple suivant est un cas simple. Après avoir défini une méthode mult (multiplication) pour la classe des entiers, je souhaite définir les méthodes mult_by_0, ..., mult_by_10 automatiquement. C'est ce qui est fait dans la première boucle grâce à define_method. Cette méthode prend en entrée le nom de la méthode à définir et lui affecte pour implémentation la closure (ici "mult int").
La vérification que les méthodes d'instances correspondantes ont bien été définies (et pas mult_by_11) est assuré par l'impression de la dernière boucle.

Le code :



class Integer
def mult by
self * by
end

(0..10).each{|int|
define_method("mult_by_#{int}") do
mult int
end
}
end

(0..11).each{|int|
boo = (1.respond_to? "mult_by_#{int}".to_sym)? \
"" : "don't "
puts "Integers #{boo}respond to mult_by_#{int}"
}


Où est la sorcellerie ?

dimanche 13 janvier 2008

MetaTricks : accesseurs

Suite à mon petit article de hier, je me lance dans une série d'articles courts, intitulée MetaTricks, présentant des petites astuces ou fonctionnalités liées à l'introspection et la métaprogrammation, avec petits scripts à l'appui.
Aujourd'hui, les accesseurs.

Les instructions attr_reader/writer/accessor :nom_variable_instance, même si elles forment une entorse au principe de l'encapsulation, sont très pratiques (et utilisées), et font appel à la métaprogrammation. Pourquoi ? Parce qu'elles implémentent automatiquement les méthodes d'accès en lecture et/ou en écriture pour une variable d'instance donnée (ces méthodes sont alors nommées : nom_variable et nom_variable=).

La preuve :


class Barbare
def initialize a = 1
@alpha = a
end
end

a = Barbare.new.methods.sort

class Barbare
attr_accessor :alpha
end

b = Barbare.new.methods.sort

puts "Methodes ajoutees par attr_accessor = "
puts b-a
#=> [alpha, alpha=]


Où est la sorcellerie ?

samedi 12 janvier 2008

Métaprogrammation et Sorcellerie

Le nom est effrayant. "Métaprogrammation". Brrrr !

Dans son très bon article, Giles Bowket essaie de mettre en avant, par diverses citations de Rubyistes reconnus, dont _Why et Russ Olsen (interview - auteur de "Design Patterns in Ruby"), le fait que la métaprogrammation n'est pas un concept obscur et arcanique.

Il y a quelques temps, je vous donnais un lien vers un bon petit tutoriel à ce sujet.

De fait, en Ruby, la métaprogrammation est encouragée, souvent transparente et très utile.

Encouragée, car finalement assez simple syntaxiquement (voir exemples ci-dessous), et surtout déjà implémentée !

Transparente. Si si. Un exemple entre mille : les attr_accessor. Un attr_accessor en début de classe implémente automatiquement les méthodes d'accès en lecture et en écriture d'une variable d'instance donnée. Le saviez-vous ? Pour ma part, j'utilisais les attr bien avant que ce soit le cas !

Très utile. Que celui qui n'a jamais tapé "toto.methods.sort" dans irb me jette la première cacahouète nucléaire. Avant d'avoir la moindre idée de ce qu'était la métaprogrammation ou l'introspection, j'utilisais des méthodes associées à ces concepts (redéfinition de méthodes, inspection des méthodes d'un objet, inclusion d'un module ou non dans une classe, respond_to?, etc...).

Un premier exemple :

Pour montrer l'utilité, et défendre la métaprogrammation contre ses accusations de sorcellerie, ce code implémente 2 fonctionnalités sympas :
  • method_added (méthode de classe) réagit ici à la (re)définition de méthodes pour la classe String. Ici par exemple, on souhaite que ma_meth ne soit pas redéfinie ultérieurement, et on soulève donc une exception dans ce cas. Il existe également method_removed se construisant sur le même schéma dans le cas de suppression de méthode (via undef).
  • method_missing est appelée en cas d'appel à une méthode d'instance inexistante. Si ça c'est pas utile... A noter qu'il s'agit cette fois d'une méthode d'instance.



class String
def ma_meth
# Pour x raisons, cette methode ne doit
# pas etre modifiee
puts "C'est pas faux..."
true
end

def self.method_added(sym)
if sym == :ma_meth
raise "Pas de modif autorisee pour ma_meth !"
else
puts "Methode #{sym} (re)definie"
end
end


def method_missing(m, *params)
puts "Utilise des methodes existantes ! TOJO !!!"
end
end

a = String.new "toto"

puts "Methode inexistante"

a.lalalalaleeeeere

puts "Redefinition"
class String
def ma_meth
puts "autre..."
false
end
end
#erreur soulevee

a.ma_meth


Alors, où est la sorcellerie ?

Dans les références présentées en début d'article, il est dit que la métaprogrammation ne doit pas être désignée par une "pratique avancée". Giles Bowkett propose de dire simplement que c'est une "nouvelle technique" plutôt qu'avancée. Modestement, je serais tentée qu'il s'agit simplement d'une fonctionnalité avancée du langage : cela ne signifie nullement qu'elle serait réservée aux programmeurs "avancés", mais plutôt que le langage est "avancé".

On en reparlera...

mardi 18 décembre 2007

Un nouveau tutoriel Ruby : introspection

Petit coup de pub pour un tuto de Ruby paru hier sur le site du zéro.

Il se penche sur un point très puissant du Ruby : l'introspection, c'est à dire la capacité du code à s'analyser lui même. Si ça peut paraître abstrait vu d'ici, je vous conseille vraiment d'aller y jeter un coup d'oeil, car pas mal de choses sont en fait utilisables "au quotidien" (j'y ai mieux compris des choses que j'utilisais depuis assez longtemps...).

Le tuto :


par Pingouin Chauffé, un jeune Rubyiste de talent.