Fork me on GitHub
#cljs-dev
<
2017-05-13
>
favila05:05:47

Is there a technique for a cljc to import a class only when the target lang is Clojure? Closest I can get is an import when cljc is run as clj, which means an unnecessary import when target is cljs (i.e. During macro-time cljs)

anmonteiro05:05:59

@favila what about doing it in a macro that knows which context it’s being expanded in?

anmonteiro05:05:33

(when (nil? (:ns &env)
  (import ...))

favila05:05:29

I get an analyzer exception from cljs that it can't find the class

favila05:05:58

Which doesn't make sense. Is import special in some way?

anmonteiro05:05:57

oh hrm, it might be

favila05:05:25

Let me make a minimal repro

anmonteiro05:05:32

happy to look at it

favila05:05:36

ok, compiling this:

(ns clj-only-import.core)

(defmacro when-clj-target [body]
  #?(:clj
     (when-not (:ns &env)
       body)))

(when-clj-target
  (import '(java.util UUID)))

favila05:05:12

I get this: Caused by: clojure.lang.ExceptionInfo: No such namespace: java.util.UUID, could not locate java/util/UUID.cljs, java/util/UUID.cljc, or Closure namespace "java.util.UUID" at line 9 src/clj-only-import/core.cljc {:file "src/clj-only-import/core.cljc", :line 9, :column 3, :tag :cljs/analysis-error}

favila05:05:06

this is the contents of compiled js:

favila05:05:15

// Compiled by ClojureScript 1.9.473 {}
goog.provide('clj_only_import.core');
goog.require('cljs.core');
clj_only_import.core.when_clj_target = (function clj_only_import$core$when_clj_target(_AMPERSAND_form,_AMPERSAND_env,body){
return null;
});

clj_only_import.core.when_clj_target.cljs$lang$macro = true;

favila05:05:26

so I'm not sure why the analyzer is upset

favila05:05:51

All I can think is that imports are looked up eagerly, before macroexpansion

favila05:05:13

OK, here is what I think is happening

favila05:05:39

I think the class names are looked up by the reader

favila05:05:22

if I do this instead all is well:

favila05:05:59

(ns clj-only-import.core)

(defmacro when-clj-target [body]
  #?(:clj
     (when-not (:ns &env)
       body)))

#?(:clj (when-clj-target
  (import '(java.util UUID))))

favila05:05:34

note the :clj reader condition to ensure cljs never even reads it

favila05:05:00

but then I have the same problem if I try to use UUID

favila05:05:33

(when-clj-target
  (def my-uuid (UUID/fromString "8668a394-1caf-4e1f-a622-fd8fa5929b3f")))

favila05:05:59

will warn:

WARNING: No such namespace: UUID, could not locate UUID.cljs, UUID.cljc, or Closure namespace "" at line 12 src/clj_only_import/core.cljc
WARNING: Use of undeclared Var UUID/fromString at line 12 src/clj_only_import/core.cljc

favila05:05:10

so I have to do double-protection, which is OK I guess

favila05:05:29

but it seems strange that class names are different

thheller08:05:21

@dnolen any idea why the analyzer would analyze cljs.core twice? currently fighting some :redef-in-file warnings when I change the behaviour of declare. https://dev.clojure.org/jira/browse/CLJS-1992?focusedCommentId=45595&amp;page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-45595