Fork me on GitHub
#clojurescript
<
2017-12-17
>
sjol00:12:23

Hi, trying to upgrade an old project to clojurescript 1.9.946 and make use of the ability to import javascript modules but although it installs the proper libs when I run fig wheel (1.5.14 ) just running [jayson :as jayson-rpc] gives me

base.js:1357 Uncaught Error: Undefined nameToPath for jayson
    at visitNode (base.js:1357)
    at visitNode (base.js:1355)
    at Object.goog.writeScripts_ (base.js:1369)
    at Object.goog.require (base.js:706)
    at (index):2
I am not sure how to import javascript. I am using lein if I ["jayso" :as jayson-rpc] I get
Assert failed: cljs.analyzer/foreign-dep? expected symbol got "jayson"
is there something I am not doing?

hlolli15:12:24

Is this expected behaviour when overwriting cljs.core function

;;;;;;; file a ;;;;;;
(ns file.a)
(defn + [& vals]
  (prn "Called!")
  (apply cljs.core/+ vals))
;;;;;;;;;; file b;;;;;
(ns file.b
  (:require [file.a :refer [+]]))
(+ 1 2 ) ;; Doesn't print "Called!"
(file.a/+ 1 2) ;; Prints "Called!"
(`+ 1 2) ;; Prints "Called!"
I'd expect if I refer a symbol, given the overwrite warning, that it would really overwrite the cljs.core function.

hlolli15:12:57

from namespace file.b

`+   => file.a/+
`file.a/+ => file.a/+
doesn't seem right.

rauh15:12:24

@hlolli I have a hunch that this might be b/c + is also a macro which is picked up here. but just a guess. So: Does the same happen with --e.g-- map?

hlolli15:12:33

@rauh no, doesn't happen with map

rauh15:12:19

ok probably worth an issue. Try to search in case it already exists.

hlolli15:12:06

ok, I'll look in the jira, good chances I wouldn't find it if it was there, let's see

mfikes17:12:36

Yeah, @hlolli you'd have to also define a + macro. For example

;;;; a.clj ;;;
(ns file.a)
(defmacro + [a b]
  `(do (println "macro called!")
       (+ ~a ~b)))
;;; a.cljs ;;;
(ns file.a
  (:require-macros file.a))
(defn + [& vals]
  (prn "Called!")
  (apply cljs.core/+ vals))
;;; b.cljs ;;;
(ns file.b
  (:require [file.a :refer [+]]))
(+ 1 2 ) ;; Prints "macro called!"
(file.a/+ 1 2) ;; Prints "macro called!"
(`+ 1 2) ;; Doesn't print anything but returns 2
Then, in a REPL, you will see both being overwritten:
cljs.user=>  (require 'file.b)
WARNING: + already refers to: #'clojure.core/+ in namespace: file.a, being replaced by: #'file.a/+
WARNING: + already refers to: cljs.core/+ being replaced by: file.a/+ at line 3 /Users/mfikes/Desktop/src/file/a.cljs
macro called!
macro called!
nil
It is very intersting that your last expression
(`+ 1 2)
prints "Called" for you. This shouldn't happen—I'd recheck your original test. This is essentially applying a symbol to a value which will look it up and if failing, should return the not-found value 2. For example
(`blah 34 77)
will return 77, no matter what else is defined.

mfikes17:12:11

If that last bit didn't make sense, consider that

(`blah {`blah 100} 77)
returns 100.

hlolli17:12:29

ah yes @mfikes yes you're right, I got confused, because when the plus fails I get "[object Object][object Object]" because I'm attempting to use the plus sign to do more than it should. But with the syntax quote, I just get the return value of the expression, which is the return value I was expecting from this operation, and that confused me, the print statement is not called.

hlolli17:12:53

I wish I could edit my jira ticket, to remove this part, and the formatting 🙂 But as you say, rewriting the macro is maybe a must @mfikes do you see this as a bug, or is the macro replacement just something that I'd have to do?

mfikes17:12:07

FWIW, if you change that to

(#'+ 1 2)
this would instead force it to go through the var, thus printing "Called!"

mfikes17:12:57

I don't see it as a bug, in that things are working as intended. Perhaps it warrants a warning. Hrm.

noisesmith17:12:59

I assume if you replaced (+ x y) with (apply + [x y]) that would also force the non-macro version

mfikes17:12:05

One thing that could happen is that you could overwrite some core function, and then later if a core macro were introduced for performance reasons, it would be a breaking change. That would not be bueno.

mfikes17:12:37

Yes @noisesmith then + is higher-order

noisesmith17:12:45

having one symbol bound to a macro and also a function seems like it was asking for trouble in the first place?

noisesmith17:12:00

unless we take the principled position that one should never replace things in cljs.core / clojure.core I guess

Alex Miller (Clojure team)21:12:25

We should not take that position

mfikes17:12:55

Perhaps the symbol resolution mechanics in CloureScript could be revised so that it doesn't greedily do macroexpansion in that case. Hmm.

mfikes17:12:53

I think those core macros are only there for performance, and their existence is intended to be transparent.

hlolli17:12:20

isn't this problem essentially a cljs.analyzer problem with the namespace? If a symbol is rewritten, in my case with a function, then for that namespace all pointers to the + as macro should be removed?

mfikes17:12:14

I could see that position being taken.

mfikes17:12:19

@hlolli One workaround is to (:refer-clojure :exclude [+]) in every file you either define or refer a non-core version of +.

hlolli17:12:11

@mfikes nice. What I'm attempting to do, will make purists grown. But I'd like to use this + symbol for a transpiler I'm working on, the target language uses + extensivly (throwing warning is a good thing therefore). I think I'll end up with some ugly hack to simplify it in the end 🙂