Fork me on GitHub
#tools-deps
<
2024-06-02
>
mwolf17:06:00

what's the typical method for resolving symbols read from deps.edn? suppose I had the following in deps.edn -- evil-inc/revenge is an API which takes an option map (containing :plot-fn and :plot-args fields) as an argument:

{:aliases {:hax {:exec-fn evil-inc/revenge,
                 :exec-args {:plot-fn evil-inc/take-over-world,
                             :plot-args {:scheme "ai-bot-swarm"}}}}}
... and in evil_inc.clj:
(defn revenge [{:keys [plot-fn plot-args]}]
  ;; `plot-fn' is a *symbol* here -- 'evil-inc/take-over-world -- not the actual `take-over-world' function
  (let [{:keys [scheme]} plot-args]
    (plot-fn scheme)))
given the command line clj -X:hax the clojure cli code correctly resolves :exec-fn to the revenge fn in the evil-inc namespace, but :exec-args contains {:plot-fn 'evil-inc/take-over-world} -- the symbol rather than the function -- and the call (plot-fn scheme) breaks. is there a better method for resolving symbols read from a deps file than splattering (resolve x) calls everywhere a fn is used? (actually, I'd probably go with (defn maybe-resolve [x] (if (symbol? x) (resolve x) x)) ... but that still seems too inelegant)

aisamu17:06:09

Perhaps worth noting: :ns-default might throw a wrench on a simple resolve call

seancorfield18:06:24

:ns-default isn't going to affect how the :exec-args are handled, only how the CLI itself resolves the function name (symbol) on the command-line.

seancorfield18:06:41

Inside your own code @UUL3S6N3Z yes, you'll need resolve to turn a symbol into a Var (and therefore a function, if it is defn'd). You probably want requiring-resolve to allow for it to be in a different namespace that has not yet been loaded. The :exec-args are just EDN data, so it's entirely up to the program how to process that data, so it should have full knowledge of the data. It's typically for -X-invoked functions to be an API that maps data (EDN) to Clojure, and part of that is requiring namespaces and resolving functions. If :plot-fn is intended to be treated as a function, then it's always going to come into your "exec API" as a symbol and you're always going to need to call requiring-resolve on it -- and then in general, your "exec API" would call into some internal function(s) passing in the fully-processed "exec args":

(defn revenge [args]
  (impl/revenge (update args :plot-fn requiring-resolve)))
(for example)

Alex Miller (Clojure team)18:06:16

Agree with all that, but an aside - this is often a thing people run into and we’ve been thinking about making var quote rehydrate on read as one approach

1
👍 2
namenu06:06:00

Is that only planned for :exec-args? We have #var tagged-literals extensively in our edn files and read them with {:readers {'var requiring-resolve}} option. It's not a huge hassle, but it would be nice to have it built in.

Alex Miller (Clojure team)12:06:21

This would be general reader functionality