Frage

Ich mache einen Rahmen für die Angabe von Prozessen, die Entscheidungen einbeziehen. Ich habe es zu arbeiten, wo jede Wahl eine Insel ist. Ich würde es vorziehen, dass subchoices ‚fork‘ die Eltern Wahl, so dass alle Optionen richtig berücksichtigt werden.

choose :one => lambda {
    choose [a, b]
    if a
      raise "Illegal"
    end
  },
  :two => ....

Zur Zeit wäre es immer wählen ‚a‘ (die für sich genommen besser aussieht), sondern führt zu Problemen weiter unten. Aktion:. Eine mit der Option 'b' wird nie in Betracht gezogen

Ich habe über callcc läuft (nicht tragbar für alle Ruby-Implementierungen von dem, was ich gelesen habe) und Fasern (neu in 1.9 und nicht zur Verfügung steht, davon ausgegangen werden kann) als Dinge, die davon überzeugt sein könnten, zu arbeiten, aber ich bin nicht verrückt nach zwei Implementierungen mit oder über die schwarze Magie der eine von ihnen, wirklich.


beenden ich den einfachen Weg nehmen und den Rest der Berechnung als Block vorbei. Das wurde ein bisschen weniger schmerzhaft, wenn ich eine Ähnlichkeit zu einer bestehenden Struktur sah. Ich hoffe nur, die Einschnitte nicht aus der Reihe bekommen.

Der eigentliche Fall ist wesentlich komplizierter - es gibt Nebenwirkungen, aber sie sind in einem versioniert Schlüssel-Wert-Speicher enthält. Ich bin auch alle Möglichkeiten aufzuzählen und die Auswahl des besten ein, so kann es nicht nur auf Erfolg stoppen.

War es hilfreich?

Lösung

zurück, wie versprochen.

Hier sind ein paar Ideen:

  • Sie könnten Kette die Entscheidungen zusammen mit Ausbeute ein, um Traversal der Permutationen zu tun. Mit anderen Worten, wählen könnte eine Reihe von verschachtelten Iteratoren aus den Optionen an sie übergeben bauen, und sie würden nur in der Kette zum nächsten ergeben. den beiliegenden Blockes Verlassen bringt Sie direkt zurück nach der Ausbeute; wenn Sie mehr (zum Beispiel Fehlerursachen) benötigen könnten Sie erhöhen und Rettung.
  • Eine flippige Anordnung der drei ‚s r (Rettung, zu erhöhen, und versuchen Sie es erneut) könnte es tun, wieder mit der Idee, dass die Option Körper nisten wählen oder sie in einer verschachtelten Struktur eingebettet werden.
  • Wenn die Optionen billig und frei von Nebenwirkungen sind, möchten Sie vielleicht auf nur schauen alle Permutationen produziert und Iterieren durch sie.
  • Wenn sie nicht frei von Nebenwirkungen sind, können Sie irgendeine Art von Pseudo-Monade Lösung versuchen, wo Sie lazily lambdas für jede Permutation erzeugen.
  • Mehr oder weniger gleichwertig (je weiter entfernt von Ihrer ersten Frage verirrt) Sie ihnen einen Index (am einfachsten, wenn Sie die Mächtigkeit jeder Wahl bestimmen können, aber möglich mit einem segmentierten Index in jedem Fall) zuweisen möglicherweise in der Lage und iterate durch die Indizes.
  • Fasern zurückportiert wurden 1.8.x

Aber alles in allem denke ich, dass die beste Antwort wäre, die Funktionalität, die Sie in einer Klasse oder Funktion wollen wickeln, setzt es mit

Andere Tipps

Sie können durch die Lösungen [diesen Quiz] [1] für Ideen suchen.

- MarkusQ

[1]: http://www.rubyquiz.com/quiz70.html "das Quiz"

P. S. Ich bin auf dem Weg zu einer Präsentation, aber ich werde prüfen, und bieten mehr, wenn ich zurückkomme, wenn niemand sonst auf der Platte hat intensiviert.

Wie gewünscht, hier ist ein Beispiel dafür, was ich meine, durch die Entscheidungen zusammen Chaining mit Ausbeuten. Eine nackten Knochen Implementierung könnte wie folgt aussehen:

def choose_one_of_each(choices,results,&block)
    if choices.empty?
        yield results
      else
        c = choices.dup
        var,val = c.shift
        choose(val) { |v|
            choose_one_of_each(c,results.update(var => v),&block)
            }
      end
    end

def choose(options,&block)
    case options
      when Hash  then choose_one_of_each options,{},&block
      when Range then options.each { |item| yield item rescue nil }
      else            options.each { |item| yield item rescue nil }
      end
    end

Und Sie es wie folgt verwenden würde (etwas aus Ihrem Beispiel erweitert, um zu zeigen, wie die Teile zusammenwirken):

a = 7
b = 'frog'
choose(
    :one => [a,b], 
    :two => ['stay','go','punt'], 
    :three => {:how => ['in the car','in a boat','by magic'],:how_fast => 0..2 }
  ) do |choices|
     raise "illegal" if choices[:one] == a
     raise "You can't stay fast!" if choices[:two] == 'stay' and choices[:three][:how_fast] > 0
     raise "You go that slow!"    if choices[:two] == 'go'   and choices[:three][:how_fast] < 1
     print choices.inspect,"\n"
     end

Was so etwas wie diese produzieren würde (wegen des Drucks):

{:three=>{:how=>"in the car", :how_fast=>0}, :one=>"frog", :two=>"stay"}
{:three=>{:how=>"in the car", :how_fast=>0}, :one=>"frog", :two=>"punt"}
{:three=>{:how=>"in the car", :how_fast=>1}, :one=>"frog", :two=>"go"}
{:three=>{:how=>"in the car", :how_fast=>1}, :one=>"frog", :two=>"punt"}
{:three=>{:how=>"in the car", :how_fast=>2}, :one=>"frog", :two=>"go"}
{:three=>{:how=>"in the car", :how_fast=>2}, :one=>"frog", :two=>"punt"}
{:three=>{:how=>"in a boat", :how_fast=>0}, :one=>"frog", :two=>"stay"}
{:three=>{:how=>"in a boat", :how_fast=>0}, :one=>"frog", :two=>"punt"}
{:three=>{:how=>"in a boat", :how_fast=>1}, :one=>"frog", :two=>"go"}
{:three=>{:how=>"in a boat", :how_fast=>1}, :one=>"frog", :two=>"punt"}
{:three=>{:how=>"in a boat", :how_fast=>2}, :one=>"frog", :two=>"go"}
{:three=>{:how=>"in a boat", :how_fast=>2}, :one=>"frog", :two=>"punt"}
{:three=>{:how=>"by magic", :how_fast=>0}, :one=>"frog", :two=>"stay"}
{:three=>{:how=>"by magic", :how_fast=>0}, :one=>"frog", :two=>"punt"}
{:three=>{:how=>"by magic", :how_fast=>1}, :one=>"frog", :two=>"go"}
{:three=>{:how=>"by magic", :how_fast=>1}, :one=>"frog", :two=>"punt"}
{:three=>{:how=>"by magic", :how_fast=>2}, :one=>"frog", :two=>"go"}
{:three=>{:how=>"by magic", :how_fast=>2}, :one=>"frog", :two=>"punt"}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top