2016-05-10 10 views
1

Gibt es eine einfache Möglichkeit, einen "For-Loop-Header" zu ändern, abhängig von den Paketen, die ein Benutzer hat? Zum Beispiel ist @progress für das Hinzufügen eines Fortschrittsbalkens in Juno/Atom (gerade herausgefunden!) Gut, während wir auch Dinge wie @simd, @acc und @parallel haben. Was ich also in dieser Schleife haben möchte, ist, eine Menge dieser Makros bedingt durch einen booleschen Wert vom Benutzer oder abhängig von der Verfügbarkeit zu setzen. Allerdings, wenn ich eine einfache if isdefined(@progress) @progress for ... elseif accelerate @acc for ... elseif @parallel for ... end oder etwas von dieser Art, würde ich immer für den gleichen Code einfügen. Gibt es einen eleganteren Weg dies zu tun? Außerdem möchte ich vielleicht einige kombinieren, und sobald Sie anfangen, die brauchbaren Kombinationen zu betrachten, die am Ende viel Code sind!Julia: Bedingt für For-Loop-Makros

+0

Sie können, wenn elseif Kette in ein Makro leicht machen, vielleicht genannt '@ myfor' oder so etwas. Dann schreiben Sie diesen Code nur einmal, wenn Sie das Makro definieren. Davon abgesehen bin ich mir nicht sicher, ob die Anwendung aller verfügbaren Makros für Makros eine für alle passende Lösung ist. Ich mag es, expliziter zu sein und die Makros vor den Loops zu schreiben, die ich auf – spencerlyon2

+0

anwenden möchte. Das Problem mit dem Schreiben von allen ist, dass es eine Menge von ihnen geben wird, und viele verschiedene Kombinationen. Ich schreibe einen Finite-Elemente-Solver, und was ich tun möchte, ist boolesche Schlüsselwortargumente, wenn es parallel ist, ob man einen Fortschrittsbalken setzt usw. und alle richtigen Makros in der Schleife sind. –

Antwort

2

Die Pkg.installed Methode wird Fehler, wenn das Paket nicht installiert ist. Es dauert eine Zeichenfolge, und mit der anderen Möglichkeit ist für diese Art der Sache wirksam im catch-Block nach dieser Zeile des dekorierten Ausdrucks Rückkehr:

macro optional_something(pkg, expr) 
    try 
     Pkg.installed(string(pkg)) == nothing && return expr 
     esc(quote 
      @time $expr 
     end) 
    catch 
     expr 
    end 
end 

# this won't add the macro @time 
@optional_something XXX rand(1000)  

# this will 
@optional_something Plots rand(1000) 
+0

Gibt es eine Möglichkeit, dass dies geändert werden könnte, um einen booleschen Wert zu verwenden? Die booleschen Werte würden von Schlüsselwortargumenten stammen, die an die Funktion übergeben wurden, um der Funktion einige andere Makros zu nennen, die in die Schleife eingefügt werden sollen. Einige von ihnen werden wegen Paketabhängigkeiten sein (und ich mag, dass dies das automatisch macht!), Aber andere werden nur die Wahl sein. Aber da Makros zur Kompilierungszeit ausgeführt werden, bin ich nicht sicher, was es tun wird, wenn es kompiliert wird. –

+0

Sie meinen Laufzeitwerte verwenden, um zu bestimmen, welchen Code das Makro erzeugt? Nein ... das geht nicht, da diese Werte zur Kompilierzeit offensichtlich nicht verfügbar sind. Sie könnten jedoch ein Makro erstellen, das je nach Wert einen if/then-Block erzeugt. Ich lasse es als Übung;) –

+0

Dokumentation ist falsch dann: 'Hilfe?> Pkg.Installed installiert (Pkg) -> Void | Versionsnummer Wenn pkg installiert ist, geben Sie die installierte Versionsnummer zurück, andernfalls geben Sie ** nichts ** zurück. ', aber es wird stattdessen Fehler zurückgegeben, wenn nicht installiert. – SalchiPapa