Ruby 2.0 est sorti

Posté par  . Édité par _jordan_, YLD, Marc Quinton, baud123, Nicolas Blanco, barmic, Nÿco et Katyucha. Modéré par baud123. Licence CC By‑SA.
Étiquettes :
33
5
mar.
2013
Ruby

Pour fêter ses 20 ans, Ruby arrive en version 2.0 !

Malgré ce changement de version majeur, il y a moins de différences entre Ruby 2.0 et 1.9 qu'entre Ruby 1.9 et 1.8.
La compatibilité avec les logiciels 1.9 est quasiment assurée. Cerise sur le gâteau : cette nouvelle version est considérée comme stable et on y trouve un certain nombre de nouveautés et d'optimisations.

Pour rappel : Ruby est un langage de programmation orienté objets, à typage dynamique et qui s'est inspiré de Lisp, Perl, Smalltalk, Eiffel, etc. Sa principale caractéristique est de mettre en avant les besoins humains avant ceux informatiques, et notamment le fun et la productivité.

NdM : merci à reno pour son journal et _jordan_ pour ses compléments pour approfondir, ainsi qu'à YLD, Marc Quinton, Nicolas Blanco, Barret Michel, Nÿco, Katyucha pour leur participation.

Sommaire

Changements du langage

Paramètres par mot-clé

Le langage gère maintenant directement le passage de paramètres par mots clefs : c'était déjà possible avant, mais en utilisant un moyen détourné (via un Hash en paramètre).

Ci dessous un exemple de définition de méthode avec une valeur par défaut pour un argument "nommé".

# Ruby 1.9 et précédents
def render(source, opts = {})
  opts = {fmt: 'html'}.merge(opts)
  r = Renderer.for(opts[:fmt])
  r.render(source)
end

# Ruby 2
def render(source, fmt: 'html')
  r = Renderer.for(fmt)
  r.render(source)
end

A noter que le passage de paramètres par mots clefs utilise la syntaxe de Ruby 1.9 pour définir les Hash.

# Ruby 1.8
my_hash = { :key1 => 1, :key2 => 3 }

# Ruby 1.9
my_hash = { key1: 1, key2: 3 }

UTF8

Ruby 1.9 ayant introduit la prise en charge complète de l'UTF-8 au niveau des chaînes, Ruby 2.0 traite désormais les fichiers de code source dans cet encodage (ce qui peut poser des problèmes de compatibilité).

Débogage

DTrace et SystemTap sont maintenant pris en charge pour instrumenter l'exécution des scripts.

Variables non utilisées

Les variables commençant par _ peuvent désormais être inutilisées dans vos sources sans causer de warning. C'est l'option -w qui permet d'activer cette fonction.

# Ruby 1.9
def foo
  _, world = 'hello, world'.split(', ')
  world
end
# => pas d'avertissement

# Ruby 2.0
def hi
  _hello, world = 'hello, world'.split(', ')
  world
end
# => pas d'avertissement non plus.

Création de hash

to_Hash permet de convertir une classe en hash. Cette méthode a été implémentée pour nil, Struct et OpenStruct

# Ruby 2.0:
Car = Struct.new(:make, :model, :year) do
  def build
    #...
  end
end
car = Car.new('Toyota', 'Prius', 2014)
car.to_h # => {:make=>"Toyota", :model=>"Prius", :year=>2014}
nil.to_h # => {}

Attention, cela n'a pas été implémenté pour les classes Enumerable/Array

{hello: 'world'}.map{|k, v| [k.to_s, v.upcase]}
                .to_h # => NoMethodError:
# undefined method `to_h' for [["hello", "WORLD"]]:Array

Chemin du dossier courant

__dir__ retourne le chemin absolu du dossier du fichier en cours d'exécution.

Création de tableaux de symboles

%i et %I ont été ajoutés pour la création de tableaux de symboles avec une syntaxe minimale.

# Ruby 1.9:
KEYS = [:foo, :bar, :baz]
# Ruby 2.0:
KEYS = %i[foo bar baz]

de la même manière que %w et %W servaient à la création simplifiée de listes de chaîne de caractères :

KEYS = %w[foo bar baz]
KEYS = ["foo", "bar", "baz"]

Inclusion par précédence

Lorsqu'un module est inclus dans un autre, il se retrouve automatiquement ajouté après la définition de celui qui l'inclut. Cela oblige à pas mal de gymnastique lorsque l'on veut "wrapper" des méthodes du conteneur.

class Template
  def initialize(erb)
    @erb = erb
  end
  def render values
    ERB.new(@erb).result(binding)
  end
end

module RenderProfiler
  def self.included base
    base.send :alias_method, :render_without_profiling, :render
    base.send :alias_method, :render, :render_with_profiling
  end
  def render_with_profiling values
    start = Time.now
    render_without_profiling(values).tap {
      $stderr.puts "Rendered in #{Time.now - start}s."
    }
  end
end

class Template
  include RenderProfiler
end

Template.ancestors
  #=> [Template, RenderProfiler, Object, Kernel, BasicObject]

Désormais il est possible d'inclure un module avant la défintion de son conteneur:

module RenderProfiler
  def render values
    start = Time.now
    super(values).tap {
      $stderr.puts "Rendered in #{Time.now - start}s."
    }
  end
end
class Template
  prepend RenderProfiler
end
Template.ancestors
  #=> [RenderProfiler, Template, Object, Kernel, BasicObject]

Exemples ci-dessus issus du blog de Ben Hoskings

Onigmo : nouveau moteur d'expression régulière

Onigmo remplace Oniguruma comme moteur d'expressions régulières (c'est un fork). Il permet d'utiliser certaines fonctionnalités présentes dans perl depuis la version 5.10.
Notamment l'expression conditionnelle (?(condition)yes-pattern|no-pattern) qui vaut yes-pattern si la condition est vérifiée, no-pattern sinon.

Refinements

Les versions précédentes de Ruby permettent déjà de redéfinir des méthodes ou d'étendre des classes existantes. Le défaut principal de cette fonction très puissante est que les modifications de classes existantes se retrouvent dans tout un projet ainsi que les librairies utilisées. Les refinements, introduits dans Ruby 2.0 en fonctionnalité expérimentale, permettent d'effectuer ces modifications de manière "cloisonnée".

Magnus Holm en a donné un bon exemple dans un article à ce sujet (en anglais)

module TimeExtensions
  refine Fixnum do
    def minutes; self * 60; end
  end
end

class MyApp
  using TimeExtensions

  def initialize
    p 2.minutes
  end
end

MyApp.new    # => 120
p 2.minutes  # => NoMethodError

Dans cet exemple, plutôt que d'ajouter la méthode minutes dans la classe Fixnum, il l'a ajouté en tant que «raffinement» dans le module TimeExtensions. L'intérêt est que la méthode minutes n'existe que dans le bloc contenant using TimeExtensions

 Lazy Enumerator et Enumerable

Enumerators et Enumerables sont maintenant disponibles en version lazy (optimisation visant à retarder une opération jusqu'au moment où son résultat est nécessaire, ou bien au moment où des ressources sont inoccupées ) :

Enumerable#lazy et Enumerator::Lazy permettent de gérer des suites potentiellement infinies (lazy streams)

A cela s'ajoutent Enumerator#size et Range#size pour déterminer la taille par évaluation retardée (lazy evaluation)

API de gestion asynchrone des exceptions

Une nouvelle API de gestion asynchrone des exceptions fait son apparition dans cette version 2.0.

Optimisations des performances

Ramasse-miette

Le ramasse-miettes a été optimisé par la technique du "bitmap marking". Il devrait radicalement réduire la mémoire occupée par les programmes ruby tournant sur serveur web. Narihiro Nakamura (en anglais) y travaillait depuis 2008.

L'idée principale est de profiter de la non-duplication de structures égales lors des forks (voir Copy-On-Write). En ruby, les valeurs sont divisées en deux parties : les données (RArray, RHash, RFile …) et un ensemble de flags. On appelle ces valeurs des RValue (Ruby Value).

Les ensembles de flags sont souvent identiques d'une RValue à une autre. Le système ne devrait donc pas avoir à les dupliquer. Seulement, l'un des flags FL_MARK, est régulièrement modifié par le garbage collector pour indiquer les RValue recyclables. Comme celui-ci change très souvent de valeur, l'ensemble de flags varie, obligeant le système à dupliquer tout l'ensemble.

Narihiro Nakamura a donc sorti FL_MARK de la structure en regroupant tous les FL_MARK dans une collection de bit mappés à la RValue (d'où le "bitmap marking"). Ainsi Ruby peut régulièrement modifier FL_MARK sans toucher à l'ensemble de flags de la RValue.

Dès lors, le système n'a pas besoin de dupliquer les ensembles de flags lorsqu'ils sont parfaitement égaux pour deux RValue différentes. Vous l'aurez peut-être compris, ceci est valable lors des appels de fork qui, dans les systèmes UNIX, ne dupliquent pas la mémoire tant qu'elle est identique aux deux processus.

Pour plus d'informations à ce sujet, je vous invite à lire cet article très intéressant (en anglais).

Autres

D'autres optimisations ont été faites pour améliorer la vitesse de démarrage notamment sur Kernel#require, les calculs sur des nombres à virgule flottante et sur la machine virtuelle. Cela profite déjà grandement au framework web Ruby on Rails.

Documentation

D'après le site ruby-lang.org : « Un effort important à également été produit pour améliorer la documentation, ce qui a été une demande régulière de la part de la communauté. Le volume de documentation rdoc pour les modules et les méthodes a ainsi notablement augmenté : 75% de la 2.0.0 est couvert, tandis que la 1.9.3 plafonnait vers les 60%. Par ailleurs, vous pouvez retrouver une description de la syntaxe ruby en appelant : »

$ ri ruby:syntax

L'ouvrage de référence sur Ruby (le "pickaxe") sort, lui, dans une nouvelle édition qui couvre désormais Ruby 2.0.

Autres mises à jour notables

La version 2.0.0 de RubyGems et la version 1.3 de Bundler accompagnent la sortie de Ruby 2.0, elles ajoutent la gestion de cette dernière, tout en restant compatible avec les 1.9.x.

De même, l'équipe de Ruby on Rails sort une version 3.2.13-rc1 compatible Ruby 2.0 ainsi qu'une version 4 en bêta pour qui Ruby 2 sera l'environnement de prédilection.

Aller plus loin

  • # Quelques coquilles

    Posté par  . Évalué à 4.

    Lorsqu'un module est inclus dans un autre, il se retrouve automatiquement ajouté après la définition de celui qui l'~~inclue~~ inclut
    Une nouvelle API de gestion asynchrone des exceptions fait sont son apparition
    Vous l'aurez peut**-**être compris

    • [^] # Re: Quelques coquilles

      Posté par  (site web personnel) . Évalué à 1.

      Corrigé.
      Tu es le bienvenu en Rédaction pour traquer ce genre de coquilles (ou attendre le 5e fil de commentaire, plutôt que de le passer en first post).

      • [^] # Re: Quelques coquilles

        Posté par  . Évalué à 2.

        ça c'est un peu ma signature, la faute sur le dernier mot que j'écris.
        En programmation c'est pareil, je compile jamais du premier coup à cause du ; que j'ai oublié sur la dernière ligne écrite.

  • # Bof

    Posté par  . Évalué à 2.

    Les deux aspects les plus intéressants de Ruby sont le traitement de yield et l'histoire de _why. Cette nouvelle version ne touchant aucun des deux, il me semble que l'annonce de Topaz intéressera plus les gens qui ne sont pas concernés par les petites améliorations incrémentales du langages.

  • # VM

    Posté par  . Évalué à 1. Dernière modification le 05 mars 2013 à 15:25.

    Je ne suis plus l'actu de Ruby notamment de la VM. Elle utilise toujours les green threads ? La 2 ou la 1.9 utilise t-elle une nouvelle implémentation plus efficace ?

    • [^] # Re: VM

      Posté par  . Évalué à 2.

      Sur la page que tu cites, il y a bien « Ruby before version 1.9 » ;) Ruby 1.9 et 2.0 utilisent les pthreads.

      • [^] # Re: VM

        Posté par  . Évalué à 1.

        En effet désolé pour le bruit. Par contre cette page indique qu'il y a un toujours un global lock ce qui n'aide pas en perf je présume.

        • [^] # Re: VM

          Posté par  . Évalué à 6.

          Oui et non. Le global lock est tout de même libéré lors des IO. Donc s'il n'est toujours pas envisageable de faire du calcul intensif sur plusieurs coeurs (sauf à utiliser une autre implémentation), les thread permettent tout de même de paralléliser les IO ce qui est loin d'être négligeable.

          • [^] # Re: VM

            Posté par  . Évalué à 2.

            ok merci pour l'info !

            • [^] # Re: VM

              Posté par  . Évalué à 2.

              J'ai aussi une question bête du coup. Est-ce qu'il est possible d'utiliser les « green threads » ET les pthreads ? Je m'explique : très souvent les pthreads sont utiles pour garantir qu'ils vont tourner sur des cœurs différents, et donc profiter de caches, etc. séparés. Mais les threads collaboratifs sont très utiles pour séparer logiquement les traitements quand l'ordre n'a pas d'importance (si on veut juste des séparations logiques, des fonctions/méthodes suffisent). Donc voilà, on utilise les pthreads pour séparer des traitements en parallèle (au moins pour les entrées/sorties), et on sépare les traitements indépendants en threads coopératifs pour les traitements qui vont arriver séquentiellement mais dont l'ordre d'exécution n'a pas d'importance.

              Je ne sais pas ce que le verrou au niveau de l'interpréteur limite cependant. Si seules les E/S sont « débloquées » alors je ne vois pas l'intérêt d'utiliser les pthreads : autant utiliser GnuPth. Au moins c'est optimisé pour exactement ce cas (threads en espace utilisateur avec un mécanisme pour ne pas bloquer en cas d'E/S).

              • [^] # Re: VM

                Posté par  . Évalué à 2.

                Est-ce qu'il est possible d'utiliser les « green threads » ET les pthreads ?

                Pas vraiment. En fait la bibliothèque standard de ruby expose simplement une class Thread sans préciser d'implémentation. Le fait que ce soit implémenté avec des green thread, ou des pthreads et un GIL dépend de quelle implementation tu utilise. YARV (implémentation "de référence" de Ruby >= 1.9) à fait ce choix. JRuby par exemple implémente ça avec des trhead Java sans GIL ce qui n'est pas sans poser des problèmes avec les librairies non "thread-safe"

                Pour ce qui est du reste de ta question je dois avouer que je ne suis pas suffisamment calé en threads pour te répondre avec certitude. Mais ce dont tu parles me rappelle les Fiber: http://www.ruby-doc.org/core-2.0/Fiber.html

                • [^] # Re: VM

                  Posté par  . Évalué à 2.

                  Oui, les fibers sont en gros ce que je veux, mais je veux aussi un vrai environnement multithread (ce qui n'est pas gagné, je sais, car les interpréteurs ont tendance a rendre les choses très compliquées pour les accès concurrents).

                  Du coup on a bien des threads coopératifs, on a bien des (p|green)threads, mais on se retrouve a faire uniquement du multiplexage en temps (pour les I/O), et pas de "vrai" parallélisme (il faut quand même un processus par cœur, puis plusieurs threads par processus, ce qui gâche de la mémoire).

                  Bon, c'est aussi le cas pour Perl et Python je crois, du coup je suppose qu'il faut se contenter de ça. :)

  • # String... symbol

    Posté par  (site web personnel) . Évalué à 4.

    Utilisateur de Python, je me demandais pourquoi il y avait en Ruby des string et des symboles (préfixe :), c'est lié au fait que les chaînes Ruby sont mutables. Un article là dessus The Difference Between Ruby Symbols and Strings.

    Votez les 30 juin et 7 juillet, en connaissance de cause. http://www.pointal.net/VotesDeputesRN

    • [^] # Re: String... symbol

      Posté par  . Évalué à 4.

      Oulà attention ! Les Symbol ne sont pas que des String immuables.

      Les Symbol sont également des "singletons". Il t'es garanti qu'une seule instance d'un même symbol existe. Si tu crée deux symboles identiques la seconde instantiation te renverra en fait la première instance.

      Jusque là rien de grave. Par contre ça implique que les Symbol ne sont jamais déalloués par le GC. Autrement dit il ne faut jamais créer un symbol à partir d'une entrée utilisateur sans quoi tu t'exposes à un déni de service.

      • [^] # Re: String... symbol

        Posté par  (site web personnel) . Évalué à 4.

        Ok, il y a un truc un peu similaire en Python, c'est l'utilisation de la fonction builtin intern().

        Sauf qu'à partir de la version 2.3 ces chaînes "internes" ont perdu leur côté "immortel" jusqu'à la fin du process, donc désallouées si plus utilisées.

        L'utilisation de intern() dans Python produit les mêmes avantages que les symboles de Ruby, ça permet des comparaisons directement sur l'identité de l'objet, donc plus rapide. Par contre l'utilisation en Ruby est plus directe en en faisant un élément syntaxique du langage là où Python n'en fait qu'un simple outil à partir d'une fonction.

        Votez les 30 juin et 7 juillet, en connaissance de cause. http://www.pointal.net/VotesDeputesRN

        • [^] # Re: String... symbol

          Posté par  . Évalué à 2.

          Oui c'est exactement ça. D'ailleurs en Ruby

          "My String".to_sym
          
          

          Est un alias de

          "My String".intern
          
          
  • # En bon pythoniste, je m'interroge...

    Posté par  (site web personnel) . Évalué à 4.

    Surtout sur cette phrase : « Sa principale caractéristique est de mettre en avant les besoins humains avant ceux informatiques, et notamment le fun et la productivité. »

    C'est des arguments qui reviennent souvent quand on parle du Ruby, et franchement je ne vois pas en quoi c'est « fun » et en quoi il est plus « humain » qu'un autre langage. Les exemples que je vois me font quand même beaucoup penser à du Python, et ce dernier n'a jamais mis en avant ces aspects-là. D'ailleurs, j'ai un peu du mal à voir les avantages de l'un par rapport à l'autre (mis à part leurs catalogues de projets respectifs).

    • [^] # Re: En bon pythoniste, je m'interroge...

      Posté par  . Évalué à 3.

      Pour les différences :
      http://stackoverflow.com/questions/1113611/what-does-ruby-have-that-python-doesnt-and-vice-versa

      Aussi python a plus de trucs tiers que ruby je trouve (équivalent à PyGTK, pypy, voire Pygame en Ruby ? Pas vraiment…)

      "Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)

      • [^] # Re: En bon pythoniste, je m'interroge...

        Posté par  . Évalué à 6.

        sur le site Rubytoolbox, tu pourras trouver les paquets logiciels (généralement sous forme de GEM) disponibles pour le langage Ruby : https://www.ruby-toolbox.com/ ; on peut y trouver une catégorie GUI-Framework qui contient plusieurs API de programmation d'interfaces graphiques.

        Ce que j'apprécie dans Ruby :

        • les méthodes et les opérateurs à la lecture très aisée :
        # test si un élément est présent dans une liste (array)
        if liste.include? "un élément" { # do whatever you want ... }
        
        # ajouter un élément dans un array
        liste << foobar  # foobar est ajouté en fin de liste
        
        # les méthodes avec l' "!" permettent de changer l'objet plutôt que de travailler sur une copie
        l2 = l1.shuffle  # l1 n'est pas changée ; l1!=l2
        l2 = l1.shuffle! # l1 est mélangée ; l1==l2
        
        
        • la documentation est assez agréable,
        • de nombreux paquets GEM sont directement intégrés dans mes distributions linux préférées ; je préfère faire apt-get install plutot que gem install.
        • j'aime beaucoup quand c'est possible et assez lisible concaténer les appels de méthodes ; ca fait penser aux pipes Unix.
        [1,2,3].shuffle.each {|i| print i}
        
        # vu ici : http://stackoverflow.com/questions/1113611/what-does-ruby-have-that-python-doesnt-and-vice-versa
        puts "backwards is sentence This".split.reverse.join ' '  # > This sentence is backwards
        
        

        Ayant pratiqué le langage PHP pendant des années, je viens tout juste de migrer sur Ruby. Et je me suis surpris à ne plus avoir envie de coder en PHP.

        • [^] # Re: En bon pythoniste, je m'interroge...

          Posté par  . Évalué à 10.

          Vu que personne ne regarde un petit troll discret:

          Ayant pratiqué le langage PHP pendant des années, je viens tout juste de migrer sur Ruby. Et je me suis surpris à ne plus avoir envie de coder en PHP.

          AMHA c'est plus lié à php qu'à ruby

        • [^] # Re: En bon pythoniste, je m'interroge...

          Posté par  . Évalué à 2.

          j'aime beaucoup quand c'est possible et assez lisible concaténer les appels de méthodes ; ca fait penser aux pipes Unix.

          puts "backwards is sentence This".split.reverse.join ' '  # > This sentence is backwards
          

          Ça me fait beaucoup penser à perl :

          say join " ", reverse split ' ', "backwards is sentence This";
          
          

          (c'est écris à l'envers, la notation n'est pas objet et split n'a pas le fonctionnement par défaut de ruby)

          Après ce n'est rien de bien spécifique à ruby, avec de bonnes méthodes n'importe quel langage objet le permet (je parle pas des times et autres).

          Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

      • [^] # Re: En bon pythoniste, je m'interroge...

        Posté par  . Évalué à 2.

        Comme gasche le note, Topaz réutilise pypy pour Ruby, mais bon Topaz c'est très, très jeune.
        Après pypy ne supporte toujours pas Python3..

      • [^] # Re: En bon pythoniste, je m'interroge...

        Posté par  . Évalué à 7.

        (équivalent à PyGTK,

        Ruby-GNOME2 (qui supporte désormais GTK+ 3 contrairement à ce que suggère le nom), QtRuby

        pypy,

        Rubinius

        voire Pygame en Ruby ? Pas vraiment…)

        Gosu

        • [^] # Re: En bon pythoniste, je m'interroge...

          Posté par  . Évalué à 2.

          Merci beaucoup !

          J'en étais resté à rubygame (abandonné) pour mes projets de jeux en Ruby, gosu a l'air énorme. :)

          Le reste est aussi très intéressant.

          "Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)

      • [^] # Re: En bon pythoniste, je m'interroge...

        Posté par  (site web personnel) . Évalué à 2.

        Oui, mais ça ne répond pas à ma question :D

        Comment peut-on dire que c'est plus « fun » et « humain » d'avoir des blocs délimités par end ou de pouvoir appeler une méthode sans les parenthèses ?

        Après, sur le côté plus technique, je trouve qu'il y a vraiment peu de différences entre les deux, à part un peu de sucre syntaxique. Sauf le coup des parenthèses facultatives, qui enlève bêtement un côté super sympa de Python, le fait de pouvoir faire référence dans une variable à une fonction.

        Sinon, je suis bien d'accord avec le message https://groups.google.com/forum/?fromgroups=#!msg/comp.lang.python/xBWUWWWV5RE/gyJRB9cihAIJ

        • [^] # Re: En bon pythoniste, je m'interroge...

          Posté par  . Évalué à 4.

          Les 2 sont tres proches, mais bon lorsque je me suis mis a ruby certaine choses me saoulaient en python, comme le self a se trimbaler, l'utilisation de fonctions au lieu de méthode (cas de len) qui oblige à avoir 2 sens de lecture, une lib standard un peu légère.
          Ruby avait ce coté full objet, permettait plus d'introspection, permettait de faire très simplement des mixins (et proposait pas mal de design patterns en mixin), utilisait des blocs, permettait de faire très facilement de petits dsl, enfin bref permettait de développer rapidement et simplement avec encore moins de prise de tête que python

          Bon par contre c'était il y a 10 ans… et python a évolué depuis (dailleurs j'aimerai bien retrouver les décorateurs en ruby, plus propre que les mixins je trouve)

        • [^] # Re: En bon pythoniste, je m'interroge...

          Posté par  . Évalué à 3.

          Après, sur le côté plus technique, je trouve qu'il y a vraiment peu de différences entre les deux, à part un peu de sucre syntaxique. Sauf le coup des parenthèses facultatives, qui enlève bêtement un côté super sympa de Python, le fait de pouvoir faire référence dans une variable à une fonction.

          Euh c'est très facile à faire en Ruby avec Object#method :
          http://stackoverflow.com/questions/485151/how-can-i-get-a-reference-to-a-method

          Quant à ton lien qui parle du fait qu'en Ruby on peut modifier les classes de bases très facilement (monkey patching) :
          1.Ça a toujours été déconseillé
          2.Ruby 2.0 apporte les refinements pour résoudre le problème.

          "Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)

          • [^] # Re: En bon pythoniste, je m'interroge...

            Posté par  . Évalué à 2.

            2.Ruby 2.0 apporte les refinements pour résoudre le problème.

            C'est encore expérimental.

            Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

    • [^] # Re: En bon pythoniste, je m'interroge...

      Posté par  (site web personnel) . Évalué à 2.

      Une des fonctionnalités sympa de Ruby est de permettre la création de sous-langages (DSL).

      C'est une fonctionnalité utilisée par certaines librairies spécifiques, par exemple Rake, pour écrire des tâches spécifiques à un projet.

      Les outils de déploiement Puppet et Chef utilisent aussi Ruby pour cette fonctionnalité en partie.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.