Code-Kommentare
Ruby hat zwei Arten von Kommentaren: Inline- und Blockkommentare.
Inline-Kommentare beginnen mit dem Zeichen # und reichen bis zum Ende der Zeile.
# On a separate line class Foo # or at the end of the line # can be indented def bar end end
Blockkommentare beginnen mit =begin und enden mit =end. Beide sollten in einer separaten Zeile stehen.
=begin This is commented out =end class Foo end =begin some_tag this works, too =end
=begin und =end dürfen nicht eingerückt werden, dies ist ein Syntaxfehler.
class Foo =begin Will not work =end end
Magic Comments
Während Kommentare von Ruby normalerweise ignoriert werden, enthalten spezielle "Magic Comments" Direktiven, die beeinflussen, wie der Code interpretiert wird.
Top-Level Magic Comments müssen im ersten Kommentarbereich einer Datei erscheinen.
HINWEIS: Magic Comments beeinflussen nur die Datei, in der sie erscheinen; andere Dateien sind davon nicht betroffen.
# frozen_string_literal: true var = 'hello' var.frozen? # => true
Alternative Syntax
Magic Comments können aus einer einzelnen Direktive bestehen (wie im obigen Beispiel). Alternativ können mehrere Direktiven in derselben Zeile erscheinen, wenn sie durch ";" getrennt und von "-*-" umschlossen sind (siehe Emacs' Datei-Variablen).
# emacs-compatible; -*- coding: big5; mode: ruby; frozen_string_literal: true -*- p 'hello'.frozen? # => true p 'hello'.encoding # => #<Encoding:Big5>
encoding Direktive
Gibt an, welche String-Kodierung für String-Literale, Regex-Literale und __ENCODING__ verwendet werden soll.
# encoding: big5 ''.encoding # => #<Encoding:Big5>
Die Standardkodierung ist UTF-8.
Top-Level Magic Comments müssen in der ersten Zeile stehen oder in der zweiten Zeile, wenn die erste Zeile wie eine #! shebang Zeile aussieht.
Das Wort "coding" kann anstelle von "encoding" verwendet werden.
frozen_string_literal Direktive
Gibt an, dass String-Literale einmal zur Parse-Zeit allokiert und eingefroren werden sollen.
# frozen_string_literal: true 3.times do p 'hello'.object_id # => prints same number end p 'world'.frozen? # => true
Der Standardwert ist false. Dies kann mit --enable=frozen-string-literal geändert werden. Ohne die Direktive oder mit # frozen_string_literal: false würde das obige Beispiel 3 verschiedene Zahlen und "false" ausgeben.
Ab Ruby 3.0 werden dynamische String-Literale nicht eingefroren oder wiederverwendet.
# frozen_string_literal: true p "Addition: #{2 + 2}".frozen? # => false
Es muss im ersten Kommentarbereich einer Datei erscheinen.
warn_indent Direktive
Diese Direktive kann die Erkennung von fehlerhafter Einrückung für nachfolgende Anweisungen einschalten.
def foo end # => no warning # warn_indent: true def bar end # => warning: mismatched indentations at 'end' with 'def' at 6
Eine andere Möglichkeit, diese Warnungen anzuzeigen, ist die Ausführung von Ruby mit Warnungen (ruby -w). Die Verwendung einer Direktive, um dies auf false zu setzen, verhindert, dass diese Warnungen angezeigt werden.
shareable_constant_value Direktive
Hinweis: Diese Direktive ist in Ruby 3.0 experimentell und kann sich in zukünftigen Versionen ändern.
Diese spezielle Direktive hilft dabei, Konstanten zu erstellen, die nur unveränderliche Objekte oder Ractor-fähige Konstanten enthalten.
Die Direktive kann eine spezielle Behandlung für Werte angeben, die Konstanten zugewiesen werden.
-
none: (Standard) -
literal: Literale werden implizit eingefroren, andere müssen Ractor-fähig sein. -
experimental_everything: alles wird teilbar gemacht. -
experimental_copy: tief kopiert und teilbar gemacht.
Modus none (Standard)
In diesem Modus keine spezielle Behandlung (wie in Ruby 2.x): kein automatisches Einfrieren und keine Prüfungen.
Es war schon immer eine gute Idee, Konstanten tief einzufrieren; Ractor macht dies zu einer noch besseren Idee, da nur der Haupt-Ractor auf nicht teilbare Konstanten zugreifen kann.
# shareable_constant_value: none A = {foo: []} A.frozen? # => false Ractor.new { puts A } # => can not access non-shareable objects by non-main Ractor.
Modus literal
Im Modus "literal" werden Konstanten, die Literalen zugewiesen werden, tief eingefroren.
# shareable_constant_value: literal X = [{foo: []}] # => same as [{foo: [].freeze}.freeze].freeze
Andere Werte müssen teilbar sein.
# shareable_constant_value: literal X = Object.new # => cannot assign unshareable object to X
Beachten Sie, dass nur Literale, die direkt Konstanten zugewiesen werden, oder solche, die rekursiv in solchen Literalen enthalten sind, eingefroren werden.
# shareable_constant_value: literal var = [{foo: []}] var.frozen? # => false (assignment was made to local variable) X = var # => cannot assign unshareable object to X X = Set[1, 2, {foo: []}].freeze # => cannot assign unshareable object to X # (`Set[...]` is not a literal and # `{foo: []}` is an argument to `Set.[]`)
Die Methode Module#const_set ist nicht betroffen.
Modus experimental_everything
In diesem Modus werden alle Konstanten zugewiesenen Werte teilbar gemacht.
# shareable_constant_value: experimental_everything FOO = Set[1, 2, {foo: []}] # same as FOO = Ractor.make_shareable(...) # OR same as `FOO = Set[1, 2, {foo: [].freeze}.freeze].freeze` var = [{foo: []}] var.frozen? # => false (assignment was made to local variable) X = var # => calls `Ractor.make_shareable(var)` var.frozen? # => true
Dieser Modus ist "experimentell", da er fehleranfällig sein kann, zum Beispiel durch tiefes Einfrieren der Konstanten einer externen Ressource, was zu Fehlern führen könnte.
# shareable_constant_value: experimental_everything FOO = SomeGem::Something::FOO # => deep freezes the gem's constant!
Dies wird vor Ruby 3.1 überarbeitet, um entweder "everything" zuzulassen oder diesen Modus stattdessen zu entfernen.
Die Methode Module#const_set ist nicht betroffen.
Modus experimental_copy
In diesem Modus werden alle Konstanten zugewiesenen Werte tief kopiert und teilbar gemacht. Es ist ein sichererer Modus als experimental_everything.
# shareable_constant_value: experimental_copy var = [{foo: []}] var.frozen? # => false (assignment was made to local variable) X = var # => calls `Ractor.make_shareable(var, copy: true)` var.frozen? # => false Ractor.shareable?(X) #=> true var.object_id == X.object_id #=> false
Dieser Modus ist "experimentell" und wurde nicht gründlich diskutiert. Dies wird vor Ruby 3.1 überarbeitet, um entweder "copy" zuzulassen oder diesen Modus stattdessen zu entfernen.
Die Methode Module#const_set ist nicht betroffen.
Scope
Diese Direktive kann mehrmals in derselben Datei verwendet werden.
# shareable_constant_value: none A = {foo: []} A.frozen? # => false Ractor.new { puts A } # => can not access non-shareable objects by non-main Ractor. # shareable_constant_value: literal B = {foo: []} B.frozen? # => true B[:foo].frozen? # => true C = [Object.new] # => cannot assign unshareable object to C (Ractor::IsolationError) D = [Object.new.freeze] D.frozen? # => true # shareable_constant_value: experimental_everything E = Set[1, 2, Object.new] E.frozen? # => true E.all(&:frozen?) # => true
Die Direktive beeinflusst nur nachfolgende Konstanten und nur für den aktuellen Geltungsbereich.
module Mod # shareable_constant_value: literal A = [1, 2, 3] module Sub B = [4, 5] end end C = [4, 5] module Mod D = [6] end p Mod::A.frozen?, Mod::Sub::B.frozen? # => true, true p C.frozen?, Mod::D.frozen? # => false, false