Skip to content

Instantly share code, notes, and snippets.

@joinr
Created June 12, 2023 06:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save joinr/3402d2d2da9ca371d053ed175f1589c1 to your computer and use it in GitHub Desktop.
Save joinr/3402d2d2da9ca371d053ed175f1589c1 to your computer and use it in GitHub Desktop.
partial function application with named args
(defprotocol INominal
(partial-nominal [this args]))
(defn ->args [xs]
(let [arg->idx (zipmap xs (range (count xs)))]
(reduce (fn [acc k] (assoc acc k :binding/unbound))
(sorted-map-by (fn [l r]
(compare (arg->idx l) (arg->idx r)))) xs)))
(defn supply [params xs]
(let [remaining (atom xs)]
(map (fn [arg]
(if (identical? arg :binding/unbound)
(let [nxt (first @remaining)]
(swap! remaining rest)
nxt)
arg))
(vals params))))
(defrecord mypartial [^clojure.lang.IFn f params]
clojure.lang.IFn
(applyTo [this args]
;;merge the args into free params.
(.applyTo f (seq (supply params args))))
INominal
(partial-nominal [this args]
(mypartial. f (into params args))))
(defmacro pfn [args & body]
`(let [f# (fn ~args ~@body)]
(mypartial. f# (->args '~args))))
;; (let [f (pfn [a b c] (+ a b c))
;; f2 (partial-nominal f '{a 1 c 3})]
;; (apply f2 [1]))
;; 5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment