Ergebnis 1 bis 8 von 8

Thema: Was ist schneller: eval(code) oder procedure object?

Hybrid-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1
    eval dürfte hier schon sehr viel Performance fressen. Zumal du es für jede Zeile neu ausführst (der Overhead also noch größer ist, als würdest du alle Zeilen gleichzeitig evaluieren).

    Erstmal zu deiner Frage mit Procs und Parametern: Natürlich kannst du call Parameter mitgeben:
    Code:
    block = Proc.new do |x, y|
      puts x+y
    end
    block.call(3, 1) #=> 4
    Weiterhin kannst du Procs über instance_eval an einen Objekt-Kontext binden (mir fällt gerade ein: auch eval-Strings kannst du an jedes beliebige Binding binden, in dem du als weiteren Parameter ein Binding übergibst. So gesehen war also meine vorherige Behauptung, Procs wären mächtiger als eval, falsch).

    Code:
    block = Proc.new do |x|
      puts screen_x + x
    end
    $game_player.instance_eval &block
    Hier wird also block innerhalb von $game_player ausgeführt. Er hat also auch Zugriff auf alle Instanzvariablen und Methoden von $game_player, gleichzeitig aber auch Zugriff auf alle lokalen Variablen im Scope.

    btw. gibt es noch eine weitere Möglichkeit, wie du deinen Gegnern "KI-Code" mitgeben kannst:
    Code:
    module KI
      class Aggressive
        def decide_what_to_do(enemy)
          # hier kommt der KI-Code rein
        end
      end
      class Defensive
        def decide_what_to_do(enemy)
          # hier kommt der KI-Code rein
        end
      end
      class Passive
        def decide_what_to_do(enemy)
          # hier kommt der KI-Code rein
        end
      end
      # ...
    end
    
    # ....
    mein_gegner.ki = KI::Defensive.new
    anderer_gegner.ki = KI::Aggressive.new
    # ...
    Diese Lösung ist hochgradig performant (performanter als Procs und deutlich performanter als eval). Außerdem lassen sich deine Gegner-Objekte problemlos abspeichern (Procs lassen sich nämlich nicht abspeichern!). Weiterhin ist das ein recht üblicher Ansatz für derlei Probleme, auch in anderen Programmiersprachen, wo es eval und Procs nicht gibt.

  2. #2
    Ah, vielen Dank. Das ist ein ganzer Haufen von Informationen die für mich sehr sehr nützlich sind.

    Mein Hauptproblem war es eigentlich, dass ich, wenn ich den Code als Text gespeichert hatte und ihn über eval(code) aufrufen ließ auf alle Variablen zugreifen, und den Feind über self ansprechen konnte.
    Als ich versucht hatte es auch Proc Objekte zu übertragen musste ich den Feind, mit meinem begrenzten Wissenstand, als globale Variable definieren um auf ihn zugreifen zu können.

    Nun kann ich also entweder den Code aus dem Proc Objekt über .instance_eval direkt in meinen Feind einbinden als auch Parameter im .call Befehl durchgeben um dadurch meinen Feind als Parameter zu übergeben.

    Eine Frage habe ich jedoch. Für jeden Feind ein neues Objekt der AI Klasse zu erzeugen, wie in deinem letzten Beispiel, anstatt die AI als Konstante zu definieren und jeden Feind auf den selben Code zugreifen zu lassen, ist dieser Weg nicht aufwendiger für den Computer?

    Ich meine, ich könnte das Proc Objekt ja als Konstante speichern und jeden Feind dieses Proc Objekt als AI Code benutzen lassen. Wäre dies nicht besser als eine AI-Instanz im Feind zu erzeugen und zu speichern?

  3. #3
    Du kannst die AI-Objekte auch als Konstanten speichern. Dann verbrauchst du weniger Speicherplatz. Aber das ist jetzt nicht soo~ tragisch, denn soviel Speicher kosten die Objekte nicht.
    Du kannst auch das Singleton-Pattern anwenden und deinen KI-Klassen eine Methode geben, welche immer dieselbe Instanz zurückgibt.
    Code:
    module KI
      class KI
        def self.instance()
          @instance ||= new()
        end
      end
      class Aggressive < KI
        def decide_what_to_do(enemy)
          # ...
        end
      end
      # ...
    end
    # ...
    ki = KI::Aggressive.instance
    ki2 = KI::Aggressive.instance
    ki == ki2 # true
    Du solltest dich auf diese Identität aber nicht verlassen. Beim Abspeichern und Neuladen der KIs haben die wieder eine eigene Instanz. Aber wie gesagt: du sparst dadurch letztlich nur etwas Speicher, mehr nicht.

  4. #4
    Nun, falls es nur Vorteile bringt doch keine Nachteile dann ist es mir recht.

    Vielen Dank für die ausführliche Hilfe.


    Ich habe noch eine kleine Frage, könntest du mir genau erklären was dieses "&" Zeichen in folgender Zeile bedeutet?
    Code:
    $game_player.instance_eval &block
    Dass es nicht funktioniert ohne das Zeichen zu verwenden habe ich bereits feststellen müssen.

    Geändert von Cornix (13.09.2010 um 13:02 Uhr)

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •