cljs-dev 2024-03-28

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

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

👍 1

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

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

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