Die Programmiersprache Ruby

Blog| Forum| Wiki  

Inhaltsverzeichnis

self << class

Herkunft: [1]

Idee: murphy

Erste Lösung: Fnordor

Frage

Welche Ausgabe erzeugt dieses (syntaktisch korrekte) Ruby-Programm?

class << self
  def
    << _end_
    print _end_
  end
end

self << class
  Def
    <<-'end'
    print _end_
  end
end

(Antwort ganz unten.)

Der Code ist absichtlich verwirrend eingerückt, und ist ein Beispiel für ziemlich schlechten und ziemlich interessanten Ruby-Code. Interessant ist vor allem die (korrekte) Syntax self << class, die die Umkehrung des Ruby-Idioms class << self darstellt.

Erklärung des Codes

Zuerst zum ersten Block:

# Klasse von self bearbeiten.
# self ist hier das main-Objekt; fügt man ihm Methoden hinzu,
# so verhalten sie sich wie globale Methoden, allerdings public.
class << self
  # Definiere die Methode <<
  def
    # die einen parameter "_end_" erwartet.
    << _end_
    # Die Methode gibt einfach den Wert von _end_ aus.
    print _end_
  end
end

Jetzt haben wir eine Methode <<, die wir auch mit Empfänger (self) aufrufen können, weil sie public ist.

Übersichtlicher kann man den Code so schreiben:

class << self
  def <<(arg)
    print arg
  end
end

Dasselbe hätte man auch so erreichen können:

def self.<<(arg)
  print arg
end

Im zweiten Block rufen wir diese Methode auf:

# Rufe die Methode mit dem Argument class ... end (Rückgabewert des class-Blocks.)
# Hier wird also tatsächlich eine Klasse definiert.
self << class
  # Und zwar die Klasse Def (Großschreibung ist zwingend.)
  Def
    # Die folgenden 3 (!) Zeilen tun gar nichts; sie sind nur ein Heredoc,
    # also ein mehrzeiliger String, der durch <<-'xyz' ... xyz begrenzt wird.
    <<-'end'
    print _end_
  end
  # Dieser String ist der letzte Ausdruck in der Klassendefinition.
  # Also ist er auch der Rückgabewert.
end

Übersichtlicher, ohne Heredoc:

self << (class Def
  "    print _end_\n"
end)

Oder auch so, ohne überflüssige Klassendefinition:

self.<<("    print _end_\n")

Im Ganzen also:

def self.<<(arg)
  print arg
end

self.<<("    print _end_\n")

Kommentare

WoNáDo wies darauf hin [2], dass das Beispiel als Eselsbrücke zum Merken der class << self-Syntax dienen kann.

Tatsächlich ist das Rätsel nur dadurch entstanden, dass murphy ausprobieren wollte, ob man auch self << code zum Laufen bekommen könnte.

Übrigends unterscheiden sich die beiden Blöcke außer im vertauschten class und self lediglich in 4 Zeichen.

Antwort

Ausgabe:

    print _end_