Fork me on GitHub
#clojurescript
<
2017-12-02
>
p-himik05:12:58

What is the correct and most appropriate way to implement a multi arity macro in CLJS?

qqq05:12:50

same as in clojure, (defmacro [& args] ...)

noisesmith05:12:36

that's not the right way to implement multi-arity anything though

noisesmith05:12:59

(defmacro foo ([arg] ...) ([arg1 arg2] ...))

p-himik06:12:42

I tried that, but the application of that macro says that I pass incorrect number of arguments.

p-himik06:12:17

(defmacro path-sub
  ([id path]
   (path-sub id nil path))
  ([id input-signal path]
   (let [sub-fn `(fn ~(sub-fn-name id) ~'[db _]
                   (~(if (vector? path) get-in get)
                     ~'db ~path))]
     (if input-signal
       `(reg-sub ~id :<- ~input-signal ~sub-fn)
       `(reg-sub ~id ~sub-fn)))))
9  (sm/path-sub ::scores-panel :scores-panel)
      ^--- Wrong number of args (1) passed to: subs/path-sub

noisesmith06:12:31

when wrong-number doesn't even match the number passed in, that means that it's being called as a function not a macro

noisesmith06:12:37

usually it's off by two though

p-himik06:12:08

path-sub is defined in a clj file, the error is about cljs file, and I don't have path-sub function.

rauh06:12:09

@p-himik You can't call a macro like that. Remember, once in the macro you're running clojure code again.

rauh06:12:24

On line 3:

`(path-sum ~id nil ~path)

noisesmith06:12:45

it really got 3, complains about 1

p-himik06:12:09

@rauh just tried that:

Failed to compile "frontend/static/js/mxc_main.js" in 0.726 seconds.
----  Could not Compile  frontend/cljs/musicxmlcheck/scores/subs.cljs  ----

  failed compiling file:frontend/cljs/musicxmlcheck/scores/subs.cljs

----  Compiler Error : Please see frontend/cljs/musicxmlcheck/scores/subs.cljs  ----
And that's it, no other messages.

noisesmith06:12:46

@rauh that same issue happens in clj - a macro must return the form it emits

rauh06:12:04

@p-himik What's the macroexpand show?

p-himik06:12:50

(macroexpand '(musicxmlcheck.subs/path-sub :a :b))
clojure.lang.ExceptionInfo: failed compiling constant: clojure.core$get@6015df86; class clojure.core$get is not a valid ClojureScript constant. {:constant #object[clojure.core$get 0x6015df86 "clojure.core$get@6015df86"], :type clojure.core$get}

rauh06:12:23

@p-himik Yup, makes sense. Can you spot the error?

p-himik06:12:39

It's probably in (if (vector? path) get-in get)

rauh06:12:06

Yeah, I'm guessing slack swallowed your ticks.

p-himik06:12:38

Nope, the ticks were just not there. 🙂

p-himik06:12:03

It works now, thanks!

rauh06:12:13

Right. Also if you want to know why the original error message is about arities: A macro is a special (but still a normal) function that also takes the environment as the first argument explicitly. When you "invoke" a macro the CLJS/CLJ compiler will automatically provide it with &env. But if you call it you'd have to do it yourself.

noisesmith06:12:41

this is what I meant when I said the macro got invoked as a function

rauh06:12:00

Thought, people usually don't do such hacky things and usually write a function that emits the code. And the macro just does one thing; Call that function. It's a common pattern.

noisesmith06:12:02

the off-by-two is because of &env and &form, the implicit args the compiler passes to the macro

rauh06:12:31

@noisesmith Yeah you're right.

p-himik06:12:45

I see. Now I understand https://stackoverflow.com/questions/25566146/multiple-arity-in-defmacro-of-clojure better. I tried the approach in the SO answer and the approach with anther function, but got stuck on that unquoted get - couldn't figure out what's wrong.

p-himik06:12:02

A message "failed compiling %file%" without any indication of the exact place and/or reason it not fun.

noisesmith06:12:19

it's almost a sure thing, if you ever see "wrong number of args, -1" or if you see it complain about an arg count that is exactly two less than the actual count, a macro got called as if it were a function somewhere (usually because some other macro is broken)

p-himik06:12:13

Got it, thanks.

p-himik06:12:19

Is a form prefixed with #_ still read by the reader? I prefixed a form with #_ and all :require's that were used only in that form, including a namespace alias for one of the keywords there. And now I get an error about an invalid keyword ::mdb/db that's located inside the form escaped with #_.

p-himik06:12:24

Found the answer in the archives. The form is still read, but no result is returned by the reader.

residentsummer08:12:23

Hi! I'm trying to use npm-deps in cljs "1.9.908". Added :npm-deps and :install-deps to compiler options, module seems to be installed (it's there in node_modules dir). But I can't figure out how to require it... Relevant bits:

(task-options!
 cljs {:compiler-options
       {:install-deps true
        :npm-deps
        {:rethinkdb "2.3.3"}}})
cljs.user> (require '[rethinkdb :as r])
clojure.lang.ExceptionInfo: No such namespace: rethinkdb, could not locate rethinkdb.cljs, rethinkdb.cljc, or JavaScript source providing "rethinkdb" at line 1 <cljs repl> {:file "<cljs repl>", :line 1, :column 1, :root-source-info {:source-type :fragment, :source-form (require (quote [rethinkdb :as r]))}, :tag :cljs/analysis-error}
	at clojure.core$ex_info.invokeStatic(core.clj:4617)
--- cut ---
cljs.user> (require '["rethinkdb" :as r])
java.lang.AssertionError: Assert failed: cljs.analyzer/foreign-dep? expected symbol got "rethinkdb"
(symbol? dep)
--- cut ---
cljs.user> (.require js/goog "rethinkdb")
#object[Error Error: goog.require could not find: rethinkdb]
Error: goog.require could not find: rethinkdb
--- cut ---

qqq21:12:11

I have:

(defn rect-new [s]
  (let [elem (.createElementNS js/document  "" "rect")]
    (.setAttributeNS elem nil "x" (::x s))
    (.setAttributeNS elem nil "y" (::y s))
    (.setAttributeNS elem nil "width" (::width s))
    (.setAttributeNS elem nil "height" (::height s))
    (.setAttributeNS elem nil "style" (str "fill: " (::fill s)))
    elem))
and I'm looking at: https://google.github.io/closure-library/api/goog.dom.html What is the best way to convert above code to goog/dom ?

Michael23:12:42

I tried to use this library through the new npm features but had all kind of errors that I didn't manage to solve, even by upgrading to the latest master... https://www.npmjs.com/package/react-stockcharts

Michael23:12:40

So I wonder, is there a way to use it from CLJS by just somehow including it and adding externs as necessary?

Michael23:12:31

Looks like exactly what I've been looking for. Thanks! 😉

raheel23:12:14

would appreciate it, if you let me know if you get things working... I just asked a question about that tutorial in #reagent 😄

Michael13:12:51

Hi Raheel. Yes, this solution worked for me.