3 Stimmen

können Sie einen Block inline mit Ruby definieren?

Ist es möglich, einen Block in einer Inline-Anweisung mit Ruby zu definieren? Etwas wie dies:

tasks.collect(&:title).to_block{|arr| "#{arr.slice(0, arr.length - 1).join(", ")} and #{arr.last}" }

Stattdessen:

titles = tasks.collect(&:title)
"#{titles.slice(0, titles.length - 1).join(", ")} and #{titles.last}"

Wenn Sie sagen tasks.collect(&:title).slice(0, this.length-1) Wie kann man "this" auf das vollständige Array verweisen lassen, das an slice() übergeben wurde?

Im Grunde bin ich nur auf der Suche nach einem Weg, um das Objekt von einer Anweisung in eine andere zurückgegeben, nicht notwendigerweise Iteration über sie übergeben.

4voto

Chuck Punkte 228137

Sie verwechseln die Übergabe eines Rückgabewerts an eine Methode/Funktion und den Aufruf einer Methode mit dem zurückgegebenen Wert. Der Weg zu tun, was Sie beschrieben haben, ist dies:

lambda {|arr| "#{arr.slice(0, arr.length - 1).join(", ")} and #{arr.last}"}.call(tasks.collect(&:title))

Wenn Sie es so machen wollen, wie Sie es versucht haben, ist die beste Lösung instance_eval , mit dem Sie einen Block im Kontext eines Objekts ausführen können. Das wäre also:

tasks.collect(&:title).instance_eval {"#{slice(0, length - 1).join(", ")} and #{last}"}

Ich würde jedoch weder das eine noch das andere tun, da es länger und weniger lesbar ist als die Alternative.

1voto

Ich bin mir nicht sicher, was du genau vorhast, aber:

Wenn Sie sagen, tasks.collect(&:title).slice(0, this.length-1), wie können Sie "this" auf das vollständige Array beziehen, das an slice() übergeben wurde?

Verwenden Sie eine negative Zahl:

tasks.collect(&:title)[0..-2]

Auch in:

"#{titles.slice(0, titles.length - 1).join(", ")} and #{titles.last}"

Ich glaube, Sie haben etwas Seltsames mit Ihren Zitaten vor sich.

1voto

krdluzni Punkte 799

Ich verstehe nicht wirklich, warum Sie das wollen, aber Sie könnten eine Funktion zu den Ruby-Klassen hinzufügen, die einen Block nimmt und sich selbst als Parameter übergibt...

class Object
  def to_block
    yield self
  end
end

Zu diesem Zeitpunkt können Sie anrufen:

tasks.collect(&:title).to_block{|it| it.slice(0, it.length-1)}

Natürlich sollte die Änderung der Klasse Object nicht auf die leichte Schulter genommen werden, da die Kombination mit anderen Bibliotheken schwerwiegende Folgen haben kann.

0voto

tadman Punkte 200181

Obwohl es hier viele gute Antworten gibt, suchen Sie vielleicht eher nach einem Ziel wie diesem:

class Array
  def andjoin(separator = ', ', word = ' and ')
    case (length)
    when 0
      ''
    when 1
      last.to_s
    when 2
      join(word)
    else
      slice(0, length - 1).join(separator) + word + last.to_s
    end
  end
end

puts %w[ think feel enjoy ].andjoin # => "think, feel and enjoy"
puts %w[ mitchell webb ].andjoin # => "mitchell and webb"
puts %w[ yes ].andjoin # => "yes"

puts %w[ happy fun monkeypatch ].andjoin(', ', ', and ') # => "happy, fun, and monkeypatch"

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X