Fork me on GitHub
#cljs-dev
<
2024-03-28
>
john15:03:16

@p-himik was recommending pinging this channel about this, as it might relate known bugs. Is this currently not possible?

john15:03:11

Like, not even possible in a deftype, reify or specify situation? It might not have to be a defrecord, just be map-like

dnolen17:03:25

there are some special properties added to normal fns to make them work, specifically cljs$lang$applyTo

dnolen17:03:58

this existed before IFn was a thing - so that suggests a gap.

dnolen17:03:13

but you can probably make it work by adding this property (and a couple others)

dnolen17:03:21

I would examine cljs.core/apply for details

dnolen17:03:44

finally, probably this will be a bit ugly and yeah we should probably update the protocol to fill the gap

dnolen17:03:00

see if you can make it work, and feel free to open a issue

👍 1
john21:03:02

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 setup

john21:03:44

looks like -contains-key? is still impl'ed after the change

john21:03:01

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))

dnolen14:03:57

I realized we probably already did this for defrecord? I guess you didn’t look there first?

john14:03:47

hmm? I presumed records already impl the one and two arity of invoke for map lookup like with maps in the call position

john15:03:11

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

dnolen20:03:30

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

john21:03:30

Well I did look at the implementation of defrecord out of curiosity. I didn't see that it had IFn

john21:03:57

Yeah I don't think they have IFn

john22:03:53

variadic-fn is what I want, right?

john20:04:51

Or do you mean just re implement defrecord and repurpose its variadic field declaration vector to be a parameter vector?

john02:04:51

The docs are scant at the moment, but if you're interested, that's the direction the API is going in