@p-himik was recommending pinging this channel about this, as it might relate known bugs. Is this currently not possible?
^ Related to https://clojure.atlassian.net/browse/CLJS-364
Like, not even possible in a deftype, reify or specify situation? It might not have to be a defrecord, just be map-like
I realized we probably already did this for defrecord? I guess you didn’t look there first?
hmm? I presumed records already impl the one and two arity of invoke for map lookup like with maps in the call position
That record has no fields on it when constructed. This is leaning into record's ability to take on new fields after being instantiated. So we're not talking about the arity of the fields vector here in defrecord creation but that of the returned record
What I meant was don’t records have to implement IFn and the apply stuff? I’m not saying it’s the best way rather as reference for doing it
Well I did look at the implementation of defrecord out of curiosity. I didn't see that it had IFn
Yeah I don't think they have IFn
variadic-fn is what I want, right?
Or do you mean just re implement defrecord and repurpose its variadic field declaration vector to be a parameter vector?
there are some special properties added to normal fns to make them work, specifically cljs$lang$applyTo
this existed before IFn was a thing - so that suggests a gap.
but you can probably make it work by adding this property (and a couple others)
I would examine cljs.core/apply for details
finally, probably this will be a bit ugly and yeah we should probably update the protocol to fill the gap
see if you can make it work, and feel free to open a issue
Okay, this appears to be working:
~@(if-cljs
&env
['cljs.core/IAssociative
`(~'-assoc
[this# k# g#]
(let [new-afn# (~(symbol (str "map->>" afname)) (into (assoc {} k# g#) this#))]
(set! (.-cljs$lang$applyTo new-afn#)
(fn [inner-this#] (apply af.fect/run-af new-afn# inner-this#)))
new-afn#))]
[])
I'm using a clj macro file and a cljc file in that setuplooks like -contains-key? is still impl'ed after the change
For posterity: not pretty, but it's handling both clj and cljs:
(defn if-cljs
[env then else]
(if (:ns env) then else))
(defmacro daf [afname ctx]
`(do (defrecord ~(symbol (str ">" afname)) []
~@(if-cljs &env ['cljs.core/Fn 'cljs.core/IFn] ['clojure.lang.IFn])
~@(if-cljs &env
(->> (range 22)
(map (fn [n]
(let [args (for [i (range n)] (symbol (str "arg" i)))]
(if (empty? args)
`(~'-invoke
[this#]
(af.fect/run-af this#))
(if-not (< 21 (count args))
`(~'-invoke
[this# ~@args]
(af.fect/run-af this# ~@args))
`(~'-invoke
[this# ~@args]
(apply af.fect/run-af this# ~@args))))))))
(->> (range 22)
(map (fn [n]
(let [args (for [i (range n)] (symbol (str "arg" i)))]
(if (empty? args)
`(~'invoke
[this#]
(af.fect/run-af this#))
`(~'invoke
[this# ~@args]
(af.fect/run-af this# ~@args))))))))
~@(if-cljs
&env
['cljs.core/IAssociative
`(~'-assoc
[this# k# g#]
(let [new-afn# (~(symbol (str "map->>" afname))
(merge (into {} this#)
(assoc {} k# g#)))]
(set! (.-cljs$lang$applyTo new-afn#)
(fn [inner-this#] (apply af.fect/run-af new-afn# inner-this#)))
new-afn#))]
[`(~'applyTo
[this# args#]
(apply af.fect/run-af this# args#))]))
(def ~afname
(~(symbol (str "map->>" afname)) ~ctx))
~@(if-cljs &env
[`(set! (.-cljs$lang$applyTo ~afname)
(fn [this#] (apply af.fect/run-af ~afname this#)))]
[])
~afname))@dnolen Here's a repo showing the idea as a deftyped thing in cljs: https://github.com/johnmn3/step-up/blob/main/src/step_up/alpha/user.cljs
The docs are scant at the moment, but if you're interested, that's the direction the API is going in