Rubys Ertragsmerkmal in Bezug auf die Informatik



functional-programming yield (3)

Ich habe vor kurzem Rubys Blöcke und nachgiebige Funktionen entdeckt, und ich habe mich gefragt: Wo passt das in Bezug auf die Informatiktheorie? Ist es eine funktionale Programmiertechnik oder etwas spezifischeres?

https://src-bin.com


Answer #1

Es gibt mehr zu geben und zu blockieren als bloßes Looping.

Die Serie Enumerating Enumerable enthält eine Reihe von Funktionen, die Sie mit Aufzählungen ausführen können, z. B. die Frage, ob eine Aussage für ein Mitglied einer Gruppe wahr ist oder ob sie für alle Mitglieder gilt, oder nach einem oder allen Mitgliedern, die eine bestimmte Bedingung erfüllen .

Blöcke sind auch für den Gültigkeitsbereich von Variablen nützlich. Anstatt nur bequem zu sein, kann es mit gutem Design helfen. Zum Beispiel der Code

File.open("filename", "w") do |f|
  f.puts "text"
end

stellt sicher, dass der Dateistream geschlossen ist, wenn Sie damit fertig sind, auch wenn eine Ausnahme auftritt, und dass die Variable außerhalb des Gültigkeitsbereichs ist, sobald Sie damit fertig sind.

Ein Gelegenheits-Google hatte keinen guten Blogpost über Blöcke und Renditen in Ruby. Ich weiß nicht warum.

Antwort auf Kommentar :

Ich vermute, es wird wegen des Blockendes geschlossen, nicht weil die Variable den Gültigkeitsbereich verlässt.

Nach meinem Verständnis passiert nichts Besonderes, wenn die letzte Variable, die auf ein Objekt zeigt, ihren Gültigkeitsbereich verlässt, abgesehen davon, dass dieses Objekt für die Garbage Collection geeignet ist. Ich weiß nicht, wie ich das bestätigen kann.

Ich kann zeigen, dass das Dateiobjekt geschlossen wird, bevor Müll gesammelt wird, was normalerweise nicht sofort geschieht. Im folgenden Beispiel können Sie sehen, dass ein Dateiobjekt in der zweiten puts Anweisung geschlossen ist, es wurde jedoch kein Speicherbereinigungsvorgang durchgeführt.

g = nil
File.open("/dev/null") do |f|
  puts f.inspect # #<File:/dev/null>
  puts f.object_id # Some number like 70233884832420
  g = f
end
puts g.inspect # #<File:/dev/null (closed)>
puts g.object_id # The exact same number as the one printed out above,
  # indicating that g points to the exact same object that f pointed to

Answer #2

Ich denke 'coroutine' ist das Stichwort, nach dem Sie suchen.

ZB http://en.wikipedia.org/wiki/Yield

Ertrag in Computer- und Informationswissenschaft:

  • in der Informatik ein Rückkehrpunkt (und Wiedereintritt) einer Coroutine

Answer #3

Die yield Ruby ist kein Iterator wie in C # und Python. yield selbst ist eigentlich ein wirklich einfaches Konzept, sobald Sie wissen, wie Blöcke in Ruby funktionieren.

Ja, Blöcke sind eine funktionale Programmierfunktion, auch wenn Ruby nicht ordnungsgemäß eine funktionale Sprache ist. Tatsächlich verwendet Ruby die Methode lambda , um lambda zu erstellen, die der Lisp-Syntax für das Erstellen anonymer Funktionen entlehnt werden. Dies sind Blöcke. Aus Sicht der Informatik sind Rubys Blöcke (und Lisps Lambda-Funktionen) closures . In Ruby benötigen Methoden normalerweise nur einen Block. (Sie können mehr passieren, aber es ist umständlich.)

Das Ergebnisschlüsselwort in Ruby ist nur eine Möglichkeit, einen Block aufzurufen, der einer Methode übergeben wurde. Diese beiden Beispiele sind gleichwertig:

def with_log
  output = yield # We're calling our block here with yield
  puts "Returned value is #{output}"
end

def with_log(&stuff_to_do) # the & tells Ruby to convert into
                           # an object without calling lambda
  output = stuff_to_do.call # We're explicitly calling the block here
  puts "Returned value is #{output}"
end

Im ersten Fall gehen wir nur davon aus, dass es einen Block gibt und sagen, dass wir ihn anrufen sollen. Auf der anderen Seite umschließt Ruby den Block in ein Objekt und übergibt ihn als Argument. Der erste ist effizienter und lesbarer, aber sie sind tatsächlich gleich. Sie würden beide so nennen:

with_log do
  a = 5
  other_num = gets.to_i
  @my_var = a + other_num
end

Und es würde den Wert @my_var , der schließlich @my_var zugewiesen wurde. (OK, das ist also eine völlig blöde Funktion, aber ich denke, dass Sie die Idee bekommen.)

Blöcke werden in Ruby für viele Dinge verwendet. An fast jeder Stelle, an der Sie eine Schleife in einer Sprache wie Java verwenden würden, wird sie in Ruby durch Methoden ersetzt, die Blöcke blockieren. Zum Beispiel,

[1,2,3].each {|value| print value} # prints "123"
[1,2,3].map {|value| 2**value}    # returns [2, 4, 8]
[1,2,3].reject {|value| value % 2 == 0} # returns [1, 3]

Wie Andrew feststellte, wird es häufig auch zum Öffnen von Dateien und vielen anderen Orten verwendet. Wenn Sie über eine Standardfunktion verfügen, die benutzerdefinierte Logik verwenden kann (z. B. Sortieren eines Arrays oder Bearbeiten einer Datei), verwenden Sie grundsätzlich einen Block. Es gibt auch andere Verwendungen, aber diese Antwort ist bereits so lange, dass ich befürchte, dass es bei Lesern mit schwächeren Konstitutionen zu Herzinfarkten kommt. Hoffentlich klärt dies die Verwirrung zu diesem Thema.





yield