2017-12-02 2 views
0

Ich möchte ein Clojure Vektormakroformular schreiben #[...] Ich kann wie #[(inc %1) %2] verwenden, das (fn [a b] [(inc a) b]) oder #(vector (inc %1) %2) entspricht.Schreiben einer Clojure # [...] Vektor Funktion Makro

Ist dies ein spezieller Datenleser, oder kann dies mit defmacro geschrieben werden?

+1

dies nicht möglich ist, finden Sie https://stackoverflow.com/q/20677055 und https: //stackoverflow.com/q/32453062. – glts

+1

Keine Benutzer-Leser-Makros in Clojure. Etwas Ähnliches könnte mit getaggten Literalen gemacht werden. Sonst '# (do [(inc% 1)% 2])' – cgrand

Antwort

1

Nur für ein Lachen, schrieb ich auf, was wahrscheinlich am nächsten ist, du wirst zu einer Lösung kommen. Es definiert kein Lesemakro, aber es definiert ein Makro, das fast die gesuchte Syntax zulässt.

Ich hatte das Rad ein bisschen neu zu erfinden für % Stil impliziter Parameter zu erlauben, da ich nicht #() missbrauchen lassen könnte arbeiten:

(defn arg-list 
    "Returns a lazy-seq of (%, %2, %3, ...) strings." 
    ([] (arg-list 1)) 
    ([n] (lazy-seq 
     (cons (str "%" (if (> n 1) n)) 
       (arg-list (inc n)))))) 

(defmacro lambda 
    "Use as you would #(). (map (lambda (* % 2)) [1, 2, 3])" 
    [& body] 
    (let [arg-syms (->> (arg-list) (take 5) (mapv symbol))] 
    `(fn [& ~arg-syms] 
     [email protected]))) 

Dies definiert eine regelmäßige Makro, das den #() Leser Makro nachahmt. Es wird zu einer Variadic-Funktion ausgewertet, bei der die ersten 5 Argumente in der Liste an "Prozent" -Symbole gebunden sind. Es ermöglicht % Stil Parameter:

(mapv (lambda (* % %2)) [1 2 3] [1 5 9]) 
[1 10 27] 

Dann können Sie nur, dass ein Makro zu definieren, verwenden, die fast das tut, was Sie suchen:

(defmacro vec-f [& elems] 
    `(lambda (vec ~(vec elems)))) 

(mapv (vec-f (inc %) %2) [1 2 3] [1 5 9]) 
[[2 1] [3 5] [4 9]] 

Aber ich kann nicht sagen, dass ich seine Verwendung empfehlen.

  • Es eignet sich nicht für die Lesbarkeit.

  • Statt ArityException s werfen, werden die verpassten Argumente standardmäßig nur auf nil über Destrukturierung

  • Es erlaubt nur %5 up; obwohl das eine fest codierte Grenze ist, die erhöht werden kann. Mit der aktuellen "var-arg-Methode" kann ich keine beliebige Anzahl von Parametern berücksichtigen. Der Versuch, eine unendliche Liste zur Kompilierungszeit zu realisieren, wird natürlich in Tränen enden. obwohl

Als Proof of Concept, zeigt es, was Sie nach heißt fast möglich.

Sie sollten nur

#(vector (inc %1) %2) 

verwenden stattdessen oder, wie in den Kommentaren vorgeschlagen

#(do [(inc %1) %2])