Ruby 3.0.0 RC1 est disponible

Nous sommes heureux de vous annoncer la sortie de Ruby 3.0.0-rc1.

Cela introduit un certain nombre de nouvelles fonctionnalités et d’améliorations de performance.

Analyse statique

RBS

RBS est un langage qui décrit les types de programmes Ruby.

Les vérificateurs de type, y compris TypeProf et d’autres outils prenant en charge RBS, comprendront mieux les programmes Ruby avec des définitions RBS.

Vous pouvez écrire la définition des classes et des modules: les méthodes qui sont définies dans la classe, les variables d’instance et leurs types, et les relations d’héritage / mix-in.

Le but de RBS est de prendre en charge les modèles couramment observés dans les programmes Ruby et de vous permettre d’écrire des types avancés, notamment les unions de type, les surcharges de méthode et les génériques. Il prend également en charge le duck typing avec interface types.

Ruby 3.0 arrive avec la gemme rbs, qui inclue l’analyse et le traitement des définitions de type écrites en RBS.

Le code ci-dessous est un petit exemple de RBS une classe, un module et des définitions de constantes.

module ChatApp
  VERSION: String
  class Channel
    attr_reader name: String
    attr_reader messages: Array[Message]
    attr_reader users: Array[User | Bot]              # `|` means union types, `User` or `Bot`.
    def initialize: (String) -> void
    def post: (String, from: User | Bot) -> Message   # Method overloading is supported.
            | (File, from: User | Bot) -> Message
  end
end

Voir le README de la gemme rbs pour plus de détails.

TypeProf

TypeProf est un outil d’analyse de type inclus dans Ruby.

Actuellement, TypeProf permet une sorte d’inférence de type.

Il lit du code Ruby sans annotation de type, analyse quelles méthodes sont définies, comment elles sont utilisées et génère un prototype de la signature de type au format RBS.

Voici une simple démo de TypeProf.

Un exemple d’entrée :

# test.rb
class User
  def initialize(name:, age:)
    @name, @age = name, age
  end
  attr_reader :name, :age
end
User.new(name: "John", age: 20)

Un exemple de sortie :

$ typeprof test.rb
# Classes
class User
  attr_reader name : String
  attr_reader age : Integer
  def initialize : (name: String, age: Integer) -> [String, Integer]
end

Vous pouvez lancer TypeProf en sauvegadant le code dans un fichier “test.rb” et en appelant la commande “typeprof test.rb”.

Vous pouvez aussi essayer TypeProf en ligne. (Cela lance TypeProf coté serveur, donc désolé si cela ne fonctionne pas !)

Voir la documentation et les démos pour plus de détails.

TypeProf est expérimental et n’est pas encore mature. Seulement un sous ensemble du langage Ruby est supporté et la détection des erreurs de typage est limitée. Mais il continue de croître rapidement pour améliorer la couverture des fonctionnalités du langage, les performances d’analyse et la convivialité. Tout commentaire est le bienvenu.

Ractor (expérimental)

Ractor est un modèle d’acteur permettant une abstraction pour la concurrence. Il fournit un outil permettant l’exécution de code de façon thread-safe.

Vous pouvez créer plusieurs ractors et les lancer en parallèle. Ractor vous permet de créer des programmes thread-safe puisque les ractors ne partagent pas d’objets normaux. La communication entre ractors se fait par passage de messages.

Afin de limiter le partage d’objet, Ractor introduit plusieurs restrictions sur la syntaxe de Ruby (sans plusieurs ractors, il n’y a pas de restriction).

La spécification et l’implémentation ne sont pas matures et pourront donc changer. Cette fonctionnalité est marquée comme expérimentale et montre l’avertissement “experimental feature” au premier Ractor.new.

Le bout de code suivant calcul n.prime? (n est un entier relativement grand) en parallèle avec deux ractors. Vous pouvez vérifier que le programme est deux fois plus rapide que celui séquentiel.

require 'prime'
# n.prime? with sent integers in r1, r2 run in parallel
r1, r2 = *(1..2).map do
  Ractor.new do
    n = Ractor.receive
    n.prime?
  end
end
# send parameters
r1.send 2**61 - 1
r2.send 2**61 + 15
# wait for the results of expr1, expr2
p r1.take #=> true
p r2.take #=> true

Voir doc/ractor.md pour plus de détails.

Fiber Scheduler

Fiber#scheduler est introduit pour intercepter des opérations de blocage. Cela permet une concurrence légère sans changer le code existant. Voir “Don’t Wait For Me, Scalable Concurrency for Ruby 3” pour avoir un aperçu du fonctionnement.

Les classes et méthodes prises en charge :

  • Mutex#lock, Mutex#unlock, Mutex#sleep
  • ConditionVariable#wait
  • Queue#pop, SizedQueue#push
  • Thread#join
  • Kernel#sleep
  • Process.wait
  • IO#wait, IO#read, IO#write et les méthodes rattachées (e.g. #wait_readable, #gets, #puts etc.)
  • IO#select n’est pas prise en charge.

(Expliquer la gem Async avec des liens). Cet exemple de code permet de faire plusieurs requêtes HTTP de façon concurrente. (Expliquer ceci :)

  1. async est une gemme externe
  2. async utilise cette nouvelle fonctionnalité
require 'async'
require 'net/http'
require 'uri'
Async do
  ["ruby", "python", "c"].each do |topic|
    Async do
      Net::HTTP.get(URI "https://www.google.com/search?q=#{topic}")
    end
  end
end

Autres ajouts notables

  • Le filtrage par motif en une ligne est changé (expérimental).

    • => est ajouté. Il peut être utilisé comme une affectation à droite.

      0 => a
      p a #=> 0
      
      {b: 0, c: 1} => {b:}
      p b #=> 0
      
    • in est changé pour retourner true ou false.

      # version 3.0
      0 in 1 #=> false
      
      # version 2.7
      0 in 1 #=> raise NoMatchingPatternError
      
  • Le pattern Find est ajouté. (expérimental)

    case ["a", 1, "b", "c", 2, "d", "e", "f", 3]
    in [*pre, String => x, String => y, *post]
      p pre  #=> ["a", 1]
      p x    #=> "b"
      p y    #=> "c"
      p post #=> [2, "d", "e", "f", 3]
    end
    
  • La définition de méthode sans le mot clé end est ajoutée.

    def square(x) = x * x
    
  • Hash#except est désormais inclus.

    h = { a: 1, b: 2, c: 3 }
    p h.except(:a) #=> {:b=>2, :c=>3}
    
  • Memory view est ajoutée en tant que fonctionnalité expérimentale

    • C’est un nouvel ensemble d’API C pour échanger une zone mémoire brute, comme un tableau de nombre ou une image bitmap, entre des bibliothèques d’extension. Les bibliothèques d’extension peuvent également partager les méta données de la zone mémoire comprenant la forme, le format de l’élément, etc. En utilisant ce type de métadonnées, les librairies d’extension peuvent même partager des tableaux multidimensionnels de façon appropriée. Cette fonctionnalité a été conçue en utilisant le protocole tampon de python.

Amélioration des performances

  • Plusieurs améliorations sont implémentées dans MJIT. Voir NEWS pour les détails.
  • Coller du code dans IRB est 53 fois plus rapide qu’en Ruby 2.7.0. Par exemple, le temps nécessaire pour coller cet exemple de code passe de 11.7 secondes à 0.22 secondes.

Autres changements notables depuis la version 2.7

  • Les arguments de mot-clé sont séparés des autres arguments.
    • En principe, le code qui affiche un avertissement dans la version 2.7 de Ruby ne fonctionnera pas. Voir le document pour plus de détails.
    • La transmission d’arguments prend désormais en charge les arguments principaux.
      def method_missing(meth, ...)
        send(:"do_#{ meth }", ...)
      end
      
  • La fonctionnalité $SAFE a été completement supprimée. C’est désormais une variable globale.
  • L’ordre de la backtrace a été inversé depuis la version 2.5 de Ruby, mais cela a été remis comme avant. Cela se comporte comme la version 2.4 de Ruby. Le message d’erreur et le numéro de ligne où l’exception apparait sont affichés en premiers. Les appelants sont affichés après.
  • Plusieurs bibliothèques standard ont été mises à jour.
    • RubyGems 3.2.2
    • Bundler 2.2.2
    • IRB 1.2.6
    • Reline 0.1.5
    • Psych 3.2.1
    • JSON 2.4.1
    • BigDecimal 3.0.0
    • CSV 3.1.9
    • Digest 3.0.0
    • Fiddle 1.0.4
    • StringIO 3.0.0
    • StringScanner 3.0.0
  • Les librairies suivantes ne sont plus incluses. Il faut installer les gemmes correspondantes pour utiliser leurs fonctionnalitées.
    • net-telnet
    • xmlrpc
  • Les gemmes suivantes sont désormais incluses avec Ruby.
    • rexml
    • rss
  • Les fichiers stdlib suivants sont désormais des gemmes et sont disponibles sur rubygems.org.
    • English
    • abbrev
    • base64
    • drb
    • debug
    • erb
    • find
    • net-ftp
    • net-http
    • net-imap
    • net-protocol
    • open-uri
    • optparse
    • pp
    • prettyprint
    • resolv-replace
    • resolv
    • rinda
    • set
    • securerandom
    • shellwords
    • tempfile
    • tmpdir
    • time
    • tsort
    • un
    • weakref
    • digest
    • io-nonblock
    • io-wait
    • nkf
    • pathname
    • syslog
    • win32ole

Voir NEWS ou les logs de commit pour plus de détails.

Avec ces changements, 3889 fichiers changés, 195560 insertions(+), 152740 suppressions(-) depuis Ruby 2.7.0!

S’il vous plait, essayez Ruby 3.0.0-rc1 et faites nous des retours !

Téléchargement

  • https://cache.ruby-lang.org/pub/ruby/3.0/ruby-3.0.0-rc1.tar.gz

    SIZE: 19488885
    SHA1: 34ede2128a90ef3217d9cab9efcdf20fc444f67c
    SHA256: e1270f38b969ce7b124f0a4c217e33eda643f75c7cb20debc62c17535406e37f
    SHA512: 798926db82d27366b39be97556ac5cb322986b96df913c398449bd3ece533e484a3047fe35e7a6241dfbd0f7da803438f5b04b805b33f95c73e3e41d0bb51183
    
  • https://cache.ruby-lang.org/pub/ruby/3.0/ruby-3.0.0-rc1.tar.xz

    SIZE: 14341128
    SHA1: deff34cf67373dca166e9961051b6c4723aaaec6
    SHA256: f1adda082f9291e394d25ed32975abbef90962dc4c8b11130586a0151558e79a
    SHA512: f4f13dbfa1c96088eb3dbfba0cb1fe99f4e17197ee2d4b78fbe16496780797a10daa3f2ff9c38d2d7b316974101eccf45184708ad05491fb49898b3a7cc6d673
    
  • https://cache.ruby-lang.org/pub/ruby/3.0/ruby-3.0.0-rc1.zip

    SIZE: 23902334
    SHA1: e3e20b4d0ec895e579ae416f2b7552c6be3596f7
    SHA256: 25ced95fa544af6a64d348dc5eace008edfda22f55ed1f6ad9f932b344e6196d
    SHA512: c81b3bf7ce582bf39fd7bc1e691d0777ed4cf38ca6b4d54bc9edaef076ae8bcecb6a86ebfd773591f7d8533e772517033c762d35fdc8b05cb4db4488c2bacec2
    

Ruby, c’est quoi ?

Ruby a été initialement développé par Matz (Yukihiro Matsumoto) en 1993 puis est devenu open source. Il fonctionne sur de nombreuses plates-formes et est utilisé partout dans le monde, en particulier pour le développement web.