Ruby 3.0.0 RC1 veröffentlicht

Wir freuen uns, die Veröffentlichung von Ruby 3.0.0-rc1 bekannt geben zu können.

Sie führt eine Reihe neuer Features und Performanzverbesserungen ein.

Statische Analyse

RBS

RBS ist eine Sprache zur Beschreibung der Typen von Ruby-Programmen.

Typprüfungsprogramme wie TypeProf und andere Werkzeuge mit RBS-Unterstützung werden mithilfe von RBS-Definitionen viel besser in der Lage sein, Ruby-Programme zu verstehen.

Mit RBS ist es nun möglich, die Definitionen von Klassen und Modulen zu beschreiben: Methoden der Klasse, Instanzvariablen und ihre Typen, Vererbungs- und Mix-In-Beziehungen.

RBS soll übliche Ruby-Idiome unterstützen und erlauben, komplexe Typen wie Union Types, überladene Methoden und Generics zu schreiben. RBS unterstützt mithilfe von Schnittstellen-Typen (Interface Types) auch Duck Typing.

Ruby 3.0 enthält das Gem rbs, das das Parsing und die Verarbeitung von in RBS geschriebenen Typendefinitionen ermöglicht.

Nachfolgend ein kleines Beispiel von RBS mit Klassen-, Modul- und Konstantendefinitionen.

module ChatApp
  VERSION: String
  class Channel
    attr_reader name: String
    attr_reader messages: Array[Message]
    attr_reader users: Array[User | Bot]              # `|` bedeutet Union Types, `User` or `Bot`.
    def initialize: (String) -> void
    def post: (String, from: User | Bot) -> Message   # Methodenüberladung wird unterstützt.
            | (File, from: User | Bot) -> Message
  end
end

Siehe die README des rbs-Gems für weitere Informationen.

TypeProf

TypeProf ist ein Typanalysewerkzeug, das mit Ruby ausgeliefert wird.

Momentan fungiert TypeProf als eine Art automatisierte Typerkennung.

Es liest einfachen (nicht typenannotierten) Ruby-Code, analysiert, welche Methoden darin definiert werden und wie sie genutzt werden, und generiert den Prototyp einer Typensignatur im RBS-Format.

Nachfolgend eine einfache Demonstration von TypeProf.

Beispielhafte Eingabe:

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

Beispielhafte Ausgabe:

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

Sie können TypeProf ausführen, indem Sie die Eingabe in der Datei „test.rb“ speichern und das Kommando „typeprof test.rb“ ausführen.

Sie können TypeProf online ausprobieren. (Dies führt TypeProf serverseitig aus, daher bitten wir um Entschuldigung, falls es ausfällt).

Siehe die Dokumentation und die Demos für Details.

TypeProf ist experimentell und noch nicht recht fertig; es wird nur eine Untermenge der Programmiersprache Ruby unterstützt und die Erkennung von Typfehlern ist noch beschränkt. Es wird aber umfassend weiterentwickelt, um die Sprachabdeckung, die Analyseperformanz und die Benutzbarkeit zu verbessern. Jegliche Rückmeldungen sind sehr willkommen.

Ractor (experimentell)

Ractor ist eine dem Aktorenmodell ähnliche Abstraktion für Nebenläufigkeit, um die parallele Ausführung von Code bei gleichzeitiger Beachtung von Thread-Sicherheit zu ermöglichen.

Sie können mehrere Ractors anlegen und sie parallel ausführen. Ractor ermöglicht es, thread-sichere parallele Programme zu schreiben, weil sich Ractors normale Objekte nicht teilen können. Die Kommunikation zwischen Ractors wird stattdessen über Nachrichten abgewickelt.

Um das Teilen von Objekten zu begrenzen, führt Ractor einige Beschränkungen für Rubys Syntax ein (die allerdings nicht eingreifen, wenn nicht mehrere Ractors verwendet werden).

Die Spezifikation und Implementation sind noch nicht abgeschlossen und können sich in Zukunft noch ändern, weshalb dieses Feature als experimentell markiert ist und bei Erstellung eines Ractors mit Ractor.new eine entsprechende Warnung ausgegeben wird.

Das folgende kleine Programm berechnet n.prime? (n ist ein relativ großer Integer) parallel mit zwei Ractors. Sie werden feststellen, dass die Programmausführung auf einem parallel arbeitenden Computer etwa 2-mal so schnell ist wie das entsprechende sequentielle Programm.

require 'prime'
# n.prime? mit den zugesandten Integers in r1, r2 läuft 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

Siehe doc/ractor.md für weitere Details.

Fiber Scheduler

Zur Unterbrechung blockender Operationen wird Fiber#scheduler eingeführt. Das ermöglicht leichtgewichtige Nebenläufigkeit ohne Änderungen bestehenden Codes. Schauen Sie sich für einen Überblick über die Funktionsweise „Warte nicht auf mich: Skalierbare Nebenläufigkeit für Ruby 3“ an.

Momentan unterstützte Klassen/Methoden:

  • Mutex#lock, Mutex#unlock, Mutex#sleep
  • ConditionVariable#wait
  • Queue#pop, SizedQueue#push
  • Thread#join
  • Kernel#sleep
  • Process.wait
  • IO#wait, IO#read, IO#write und verwandte Methoden (z.B. #wait_readable, #gets, #puts usw.).
  • IO#select wird nicht unterstützt.

(Erkläre Async-Gem mit Links). Das folgende Beispielprogramm führt mehrere HTTP-Anfragen nebenläufig aus:

(Erkläre das:)

  1. async ist das äußere Gem
  2. async nutzt das neue Feature
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

Sonstige erwähnenswerte neue Features

  • Einzeiliges Pattern Matching (Musterabgleich) wurde neu gestaltet (experimentell).

    • => wurde hinzugefügt. Es funktioniert wie eine rechtsseitige Zuweisung.

      0 => a
      p a #=> 0
      
      {b: 0, c: 1} => {b:}
      p b #=> 0
      
    • in wurde geändert, sodass es true oder false zurückgibt.

      # version 3.0
      0 in 1 #=> false
      
      # version 2.7
      0 in 1 #=> wirft NoMatchingPatternError
      
  • Find-Idiom wird eingeführt. (experimentell)

    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
    
  • End-lose Methodendefinition wird eingeführt.

    def square(x) = x * x
    
  • Hash#except ist jetzt eingebaut.

    h = { a: 1, b: 2, c: 3 }
    p h.except(:a) #=> {:b=>2, :c=>3}
    
  • Memory View wird als experimentelles Feature eingeführt.

    • Dabei handelt es sich um eine neue C-API, die den Austausch roher Speicherabschnitte, wie ein numerisches Array oder Bitmap-Bilder, zwischen Erweiterungsbibliotheken (C extensions) ermöglichen soll. Die Erweiterungsbibliotheken können auch die Metadaten des betroffenen Speicherabschnitts wie etwa Schnitt, Elementformat usw. teilen. Mit dieser Art von Metadaten können Erweiterungsbibliotheken sogar mehrdimensionale Arrays ordnungsgemäß teilen. Dieses Feature orientiert sich an Pythons Buffer Protocol.
  • Es gab viele Verbesserungen im MJIT. Siehe die NEWS für Details.

  • Das Einfügen langer Code-Abschnitte in IRB ist 53-mal schneller als es mit Ruby 2.7.0 der Fall war. Beispielsweise reduziert sich die Zeit um diesen Beispiel-Code einzufügen von 11,7 auf 0,22 Sekunden.

Sonstige erwähnenswerte Änderungen seit 2.7

  • Schlüsselwortargumente werden von anderen Argumenten abgetrennt.
    • Grundsätzlich wird Code, der unter Ruby 2.7 eine Warnung erzeugte, nicht mehr funktionieren. Siehe dieses Dokument für weitere Details.
    • Übrigens unterstützt Argumentweiterleitung jetzt auch vorangehende Argumente.

      def method_missing(meth, ...)
        send(:"do_#{ meth }", ...)
      end
      
  • Musterabgleiche (case/in) sind nicht länger experimentell.
  • Die Besonderheiten von $SAFE wurden vollständig entfernt. Es handelt sich nun um eine normale globale Variable.
  • In Ruby 2.5 war die Reihenfolge der Backtraces umgekehrt worden. Diese Änderung ist rückgängig gemacht worden, d. h. die Fehlermeldung und die Nummer der Zeile, in der der Fehler auftrat, werden zuerst und die Aufrufer danach ausgegeben.
  • Einige Standardbibliotheken wurden aktualisiert.
    • 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
  • Die folgenden Bibliotheken werden nicht länger mitgeliefert. Installieren Sie die entsprechenden Gems, um diese Features zu nutzen.
    • net-telnet
    • xmlrpc
  • Die folgenden Standardgems sind jetzt mitgelieferte Gems.
    • rexml
    • rss
  • Die folgenden zur stdlib gehörenden Dateien sind nun Standardgems und werden auf rubygems.org veröffentlicht:
    • 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

Siehe die NEWS oder die Commit-Logs für weitere Details.

Mit diesen Änderungen wurden 3889 Dateien geändert, 195560 Einfügungen(+), 152740 Löschungen(-) seit Ruby 2.7.0!

Bitte testen Sie Ruby 3.0.0-rc1 und geben Sie uns Rückmeldungen!

Download

  • 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
    

Was ist Ruby

Ruby wurde zunächst 1993 von Matz (Yukihiro Matsumoto) entwickelt und ist heute quelloffene Software. Es läuft auf mehreren Plattformen und wird weltweit genutzt, insbesondere für die Webentwicklung.