2 votes

Une alternative à la macro cond-> threading qui fait référence au dernier état threadé dans le prédicat ?

Disons que j'ai ce fn

(let [{:keys [a b c d] :as params} {:a 1 :b 1 :c nil :d nil}] 
  (cond-> params
    a       (update :b inc)
    (= b 2) (assoc :c "here")
    c       (assoc :d "here")))

ce que je reçois

;;=> {:a 1, :b 2, :c nil, :d nil}

ce que je veux :

;;=> {:a 1, :b 2, :c "here", :d "here"}

Syntaxe possible :

(let [params {:a 1 :b 1 :c nil :d nil}] 
  (cond$-> params
    (:a $)       (update :b inc)
    (= (:b $) 2) (assoc :c "here")
    (:c $)       (assoc :d "here")))

Cette solution ou une solution similaire est-elle déjà mise en œuvre quelque part ?

3voto

erdos Points 1149

Vous voilà avec une mise en œuvre simple :

(defmacro cond$->
  ([value] value)
  ([value cond body & clauses]
   (assert (even? (count clauses)))
   `(cond$-> (let [~'$ ~value]
               (if ~cond (-> ~'$ ~body) ~'$))
             ~@clauses)))

Il crée simplement un formulaire sur la première condition et le premier corps. Si la condition correspond, alors la valeur de l'élément suivant cond$-> l'appel sera body Dans le cas contraire, la valeur originale est utilisée. Il utilise la récursion pour traiter toutes les clauses.

En général, il est préférable de laisser l'utilisateur choisir le symbole qui sera utilisé pour lier la valeur :

(defmacro cond-as->
  ([value sym] value)
  ([value sym cond body & clauses]
   (assert (even? (count clauses)))
   `(cond-as-> (let [~sym ~value]
                 (if ~cond ~body ~sym))
               ~sym
               ~@clauses)))

(let [params {:a 1 :b 1 :c nil :d nil}]
  (cond-as-> params $
             (:a $)       (update $ :b inc)
             (= (:b $) 2) (assoc $ :c "here")
             (:c $)       (assoc $ :d "here")))

1voto

Alan Thompson Points 325

Je peux voir comment cela pourrait être utile. Vous pouvez trouver mon point de vue sur le sujet ici :

(let [params {:a 1 :b 1 :c nil :d nil}]
  (cond-it-> params
    (:a it)        (update it :b inc)
    (= (:b it) 2)  (assoc it :c "here")
    (:c it)        (assoc it :d "again")))

;=> {:a 1, :b 2, :c "here", :d "again"}

Mise en œuvre :

(defmacro cond-it->
  [expr & forms]
  (let [num-forms (count forms)]
    (when-not (even? num-forms)
      (throw (IllegalArgumentException. (str "num-forms must be even; value=" num-forms)))))
  (let [cond-action-pairs (partition 2 forms)
        cond-action-forms (for [[cond-form action-form] cond-action-pairs]
                            `(or (when ~cond-form) ~action-form)) ]
    `(it-> ~expr ~@cond-action-forms)))

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X