Fork me on GitHub
#clojurescript
<
2018-02-28
>
tony.kay01:02:27

Does anyone know a way to alias a namespace without requiring it in cljs? E.g. (alias 'a 'some.long.thing) I want the alias, but I don’t want the require (the alias is for convenience, and a require will create a loop)

noisesmith01:02:36

tony.kay you can do it by using an empty ns form - I've seen it done at least - there may be unexpected consequences there though

tony.kay01:02:54

can you give an example?

noisesmith01:02:59

that is, create the ns with an empty ns form and then alias it

tony.kay01:02:45

Clojure has alias, cljs does not (I think because nses are not reified)

noisesmith01:02:04

but :as uses alias (or it does in clj...)

noisesmith01:02:26

adds this to his "reasons cljs is a bit odd" list

tony.kay01:02:29

ns is a special form. On the JVM a Namespace is an instance of a class that is essentially a map-like thing. In cljs, I htink it is just an internal construct used during compile.

tony.kay01:02:48

So, on the JVM you can actually dynamically manipulate it

dpsutton01:02:15

Just out of curiosity why do you want an alias without requiring?

mfikes01:02:28

@tony.kay I don't think you can. We hit this problem before and had to ditch a use of alias in this code so that it could be processed by ClojureScript, and at the time I recall there being no good way to do it https://github.com/clojure/clojurescript/commit/8477f19dcf67a8f305b46f2fd2e793586e027263

tony.kay01:02:33

@dpsutton I use namespaced symbols on multimethod dispatch, but the multimethods sometimes need to access the code where they’re also used, creating a require loop…but the dispatch just uses the symbol as data, so being albe to alias would save some typing.

tony.kay01:02:56

Thanks Mike. I figured there was some internal reason it isn’t supported.

mfikes01:02:58

Having said that, it makes me wonder if alias couldn't be made to work in ClojureScript (at least if constrained in a static way)

mfikes01:02:43

Maybe only top-level or somesuch. :thinking_face:

mfikes01:02:11

You can do it in self-hosted ClojureScript

cljs.user=> (defn alias
       #_=>  [alias namespace-sym]
       #_=>  (swap! cljs.env/*compiler* update-in
       #_=>   [:cljs.analyzer/namespaces (.-name *ns*) :requires]
       #_=>   assoc alias namespace-sym)
       #_=>  nil)
#'cljs.user/alias
cljs.user=> (alias 'cs 'clojure.string)
nil
cljs.user=> ::cs/foo
:clojure.string/foo
cljs.user=> (var cs/reverse)
#'clojure.string/reverse
Perhaps something similar could work in the JVM analyzer (it might even need to be a special form).

tony.kay02:02:16

seems like it could, but feels a bit hacky unless it were in the ns form, and that thing is already such a mess

mfikes04:02:49

Perhaps the reason alias doesn’t exist is due to lack of runtime reification of namespaces, etc., but ultimately we ended up with a limited form of the var special form in ClojureScript, albeit with some static restriction—perhaps the same could happen for alias, but there probably just hasn’t been enough people asking for it, given that the times you could use it are extremely rare.

jeaye05:02:05

Two CLJS versions were pushed out yesterday, with no changes to the change log and no announcement. Anyone have info on what they contain?

jeaye05:02:07

I pinged @dnolen on IRC earlier, but didn't hear anything back. Versions 1.10.63 and 1.10.64.

Desmond06:02:39

Hi, what's the most straightforward way to load my cljs namespaces in a repl? I've been trying to get cljs-bootstrap (https://github.com/swannodette/cljs-bootstrap) going but I hit some opaque errors. This doc (https://clojurescript.org/reference/repl) makes the browser version look easy I couldn't find a clear answer on how to get the cljsc compiler working. Any suggestions?

sggdfgf10:02:13

does clojurescript async have <!!

thheller10:02:37

@faxa no. it is not possible to do blocking operations in JS.

jannis11:02:02

Hi! I’m trying to use npm modules directly in ClojureScript. For this, I ran yarn add @cljs-oss/module-deps apollo-client in a new directory. I then created a file src/foo.cljs with the following content: (ns foo (:require apollo-client)). I’m starting it with clj -Sdeps '{:deps {org.clojure/clojurescript {:mvn/version "1.10.64"}}}' -m cljs.main -r, then in the repl, I evaluate (require 'foo :reload). The result is a stacktrace that begins with java.lang.IllegalArgumentException: /Users/jannis/node_modules/graphql/language/printer.js is not a relative path. I’m happy to dive deeper and find a solution. But I wanted to check first: is this a known issue? I don’t know how npm modules are loaded yet but I suspect it comes from this:

./node_modules/apollo-client/index.js:export { print as printAST } from 'graphql/language/printer';

benzap11:02:09

@jannis I'd also be interested in hearing about how to setup externs, it's my task for today 🙂

benzap11:02:30

Is there any reason to use yarn over npm, or are they pretty much the same tools?

jannis11:02:41

@benzap People might shout at my but yeah, they are pretty much the same tool in that they both manage npm dependencies in your project and can run your package.json commands etc.

benzap11:02:12

yeah, I assumed that yarn has the benefit of being a bit faster, but they still pull from npm dependencies, right?

andlrb11:02:21

@benzap yarn adds some extra functionality on top of npm, it was developed in order to resolve some of npm's shortcomings. Think of Yarn as an improved installer that still relies upon the same npm structure.

benzap11:02:36

is it hard to get started with yarn over npm?

andlrb11:02:25

Not at all.

benzap11:02:34

alright, i'll give it a shot

andlrb11:02:42

A major problem with npm is that it automatically runs code from dependencies and permits packages to be added on the fly. But since Yarn only installs from your yarn.lock or package.json files it’s more secure, it also makes use of checksums before installation to ensure the integrity of each package. And although I'm not a big fan of Facebook, they're one of the largest software companies in the world... so bugs usually get fixed very quickly.

benzap11:02:26

Oh that's interesting, I never knew it was created by facebook, i'm a big fan of react

benzap12:02:15

So one difference i'm noticing, it appears that the clojurescript compiler allows you to include dependencies right in the compiler options under the option :npm-deps

benzap12:02:27

I just started setting up yarn, so i'm not familiar with how this affects external inference when compared to managing the node_modules yourself

jmckitrick12:02:24

@benzap I’m working on something similar. I’m struggling with 2 different react components, and it seems each will require a different import procedure. Does that make any sense?

sh4z12:02:04

Is there an easy way to have cljsbuild swap an atom variable when as i compile? I'd like to have two different builds of my app and the only difference is :admin in my state atom is true/false

thheller12:02:36

@jlindeberg88 you can use goog-define together with :closure-defines. it seems a little insecure to do this though as a savvy user might just flip the setting and become an admin?

sh4z12:02:33

Thanks I'll look into that! That shouldn't matter since the non admin-version is for users with no privileges to access any of the backend structure

jannis13:02:11

Interesting, I tried https://github.com/clojure/clojurescript/tree/master/samples/string-requires-npm-deps without :target :nodejs (swapping out react-dom/server for react-dom). It didn’t work out of the box (`goog.require` failed to resolve react and react_dom) but once I added those two names to the right goog.addDependency calls in out/cljs_deps.js it worked! I wonder how we can make this work out of the box?

jannis13:02:52

It seems different tweaks are needed for different packages. 1. react and react_dom needed to be added to the provides section of the dev bundle addDependencies manually 2. graphql didn’t show up in cljs_deps.js in the first place; changing it to point to index.js instead of index.mjs in its package.json "module" field fixed that but there are still references to mjs files in cljs_deps.js that can’t be resolved.

dnolen13:02:53

@jeaye yeah no announce for now, cut some releases so users could do some testing of the new cljs.main feature. We’re close, but some finesse things to do - there will be a changelog, proper announce soon

benzap13:02:21

@jannis, i'm attempting to use lein-cljsbuild with similar arguments, i'll let you know how it plays out

benzap13:02:13

@jannis try adding :infer-externs true to your build options

benzap13:02:46

I can't seem to find an article which was an example of using npm dependencies with lein, it also used the new require functionality to pull in dependencies as strings (to get around issues with naming)

benzap13:02:12

This was a few months ago, so I wonder if maybe they removed that functionality, and they're going a different direction

benzap13:02:39

Seems like the focus seems to revolve around the new clj build tool

jannis13:02:19

@dnolen Hey David, sorry to ping you directly. I’m wondering how far the latest CLJS release (1.10.64) is from being able to include “arbitrary” npm packages in browser-targeting builds. I’ve spent the last couple of days trying to package Apollo for cljsjs, which required build changes to almost all JS libraries involved (…), so I’m eager to understand how far we are from not having to go through that anymore—and what I can do to help. 🙂

dnolen13:02:37

@jannis no idea - too many considerations

dnolen13:02:24

however I’m thinking about a couple of debug tools + some documentation to help people more easily contribute to ClojureScript / Closure Compiler

dnolen13:02:46

so we can get more contribution to improve the feature

jannis13:02:35

@dnolen It must be super complex to be able to pull packages in, given how different they are. Documentation what the current baseline of support is would be great (to set expectations for instance; I currently don’t understand what is possible and what isn’t).

dnolen13:02:37

@jannis it’s actually not complicated 🙂

benzap13:02:30

I find it incredibly confusing starting out, i'm guessing it's one of those things that becomes simple once you get it working once

dnolen13:02:49

Almost all issues that aren’t Closure are issues with indexing, could be easier to debug

dnolen13:02:27

Closure issues of course have to solved by reporting / PRs

jannis13:02:37

Indexing means what in this case?

dnolen13:02:44

indexing node_modules

jannis13:02:02

Using the new release and the cljs build API, it seems a bunch of problems simply arise from dependencies not being inserted correctly into cljs_deps.js. Is this what you mean?

dnolen13:02:44

I mean that’s way later in the pipeline

dnolen13:02:58

so if some went wrong earlier, of course later steps will be wrong

jmckitrick13:02:41

@pesterhazy That did the trick! Accessing (.-default foo)

fabrao13:02:11

Hello all, is there any way to call function from string?

jmckitrick13:02:11

How can I determine which libraries need that approach? And is using webpack and :foreign-libs the best way to do that?

jannis13:02:00

@dnolen Got it. If I wanted to debug how the packages I’m trying to depend on are indexed, where would I best start? Is module_deps.js the right/earliest place?

jannis13:02:40

@dnolen Thanks btw 🙂

fabrao13:02:22

I used it:

(defn ->js [var-name]
      (-> var-name
          (str/replace #"/" ".")
          (str/replace #"-" "_")))

(defn invoke [function-name & args]
      (let [fun (js/eval (->js function-name))]
           (apply fun args)))

(ns go-report.pg.cadastro.grupo)
(defn ^:export ui [] [:div "Result"])
(eval/invoke "go-report.pg.cadastro.grupo/ui") is getting Uncaught TypeError: Cannot read property 'ui' of undefined

benzap13:02:52

@fabrao try comparing the same eval with a hand-written eval in the javascript console

fabrao14:02:49

@benzap As I tested now, I have to reference the namespace to call it. In this case, is there any way to use require dynamicly?

fabrao14:02:40

I´m doing some menu references that I want to be dynamic. Now I have to use static references any time I include menu item referenced to view

benzap14:02:15

I believe you can just use the clojure method require

benzap14:02:44

if i'm understanding correctly, you want to pull in certain namespaces dynamically after some user action?

fabrao14:02:46

like :on-click #(show-view "namespace.ref")

benzap14:02:02

(require '[go-report.pg.cadastro.grupo :as grupo]) (grupo/ui)

benzap14:02:09

why does it need to be invoked by a string?

fabrao14:02:02

because I don´t want to use (require '[go-report.pg.cadastro.grupo :as grupo]) (grupo/ui) anytime I create other view

benzap14:02:57

I don't understand, can't you just list all of your required namespaces in the (ns) form?

benzap14:02:32

or is this one of those "I can't be bothered" situations?

fabrao14:02:49

Today I use

(defmulti pagina (fn [x] x))

(defmethod pagina :cadastro/sistema []
  [sistema/ui])

(defmethod pagina :cadastro/usuario []
  [usuario/ui])

(defmethod pagina :cadastro/cliente []
  [cliente/ui])

(defn ui []
  [:div.centrar {:style {:width "100%" :height "100%" :background-color "#293E6A"}}
   [menu/ui]
   [pagina @(rf/subscribe [:controle/pagina])]])

benzap14:02:26

I think what you're looking for is a macro

fabrao14:02:51

Any new pagina I have to include in require and reference it as defmethod

benzap14:02:22

yeah, you probably want a macro 🙂

fabrao14:02:22

so, If I can do it dynamic, it will help a lot

fabrao14:02:07

but, even using macro I have to include the namespaces

benzap14:02:41

hmm, i'm not sure

fabrao14:02:10

I think I´ll give up, too complicate 🙂

benzap14:02:19

Yeah, I see what you're getting at, but there are a ton of edge cases that would drive me crazy 🙂

benzap14:02:11

I'm going nuts trying to find an article outlining a new way to require within clojurescript

benzap14:02:44

Instead of defining :foreign-libs, you could just include a string within the namespace (ns) form, no?

benzap15:02:13

Perfect, thank you!

conan15:02:33

Hi folks, I'm getting the following error when trying to take a value from a core.async channel returned by cljs-http, any ideas on how to go about debugging it? Uncaught #error {:message "Invalid keyword: .", :data {:type :reader-exception, :ex-kind :reader-error}}

conan15:02:16

Maybe there's some javascript being interpreted by the cljs reader? My knowledge here is limited, any pointers would be 💯

jmckitrick15:02:40

Once I follow those instructions for :npm-deps and run the build, @mfikes is there a way to discover the exact name of the namespace I need in the require form?

mfikes15:02:23

Hmm… I don’t have a lot of experience using NPM or JavaScript. I would go digging through the source.

mfikes15:02:49

Or read the documentation describing the module that you are tying to use.

benzap15:02:01

@jmckitrick i'm in the same boat

benzap15:02:25

@conan you should post a small snippet of what's producing the error

conan15:02:32

it's this: (<! (http/request request))

conan15:02:51

i think there must be something wrong in the request map

conan15:02:05

i'll try removing bits one by one until there's nothing left

benzap15:02:16

Yeah, I was going to say, it might be something you're sending. It probably has a try/catch, and produces the error as a return on the channel

Chris16:02:39

Is it possible to pass namespace symbols as parameters in cljs? I’m trying to do this:

(map #(ns-publics %) ['ns.1 'ns2 ...])

Chris16:02:16

I get this error though: Argument to ns-publics must be a quoted symbol (core/and (seq? quoted-ns) (= (first quoted-ns) (quote quote)) (core/symbol? (second quoted-ns)))

Chris16:02:48

That’s what I was thinking

dnolen16:02:26

Runtime var meta programming is not a thing in CLJS

Chris16:02:59

Right, because there is no notion of directory structure in js

Chris16:02:29

Among other things

dnolen16:02:31

Not quite, there are no vars in CLJS

Ryan Radomski16:02:19

Isn't there a way to inspect namespaces at macro-expansion time?

dnolen16:02:41

Not at runtime though, compile time works

dnolen16:02:25

Which includes macros

Ryan Radomski16:02:52

Is this all documented somewhere? I think I learned that on the Google Group

Ryan Radomski16:02:00

In a similar thread

Chris17:02:37

okay, so it seems like there is not a way to autogenerate information on functions in clojurescript. The only way to get this info is to have it done at compile time right? So I’d have to explicitly call ns-publics on each namespace manually. And moreover I’d have to call meta on every function within those namespaces manually.

jplaza18:02:21

Hey people! Is there any way to compile a CLJS to a node modules ready output? I wrote a small lib in CLJS and would like to be able to use it in a nodejs project

richiardiandrea19:02:46

@jplaza I have only tried with the :node-library profile of shadow-cljs: it allows you to specify things to export. I cannot say anything about vanilla because back then when I tried I went directly to shadow-cljs for this feature.

jplaza19:02:36

Cool! Thanks a lot @richiardiandrea exactly what I was looking for

gonewest81819:02:23

Let’s say I want to create an uberjar that launches an nrepl server with com.cemerick/piggieback middleware. Why does the following throw an exception as it compiles?

gonewest81819:02:14

(defproject smoketest "0.1.0-SNAPSHOT"
  :dependencies [[org.clojure/clojure "1.9.0"]
                 [org.clojure/tools.nrepl "0.2.12"]
                 [com.cemerick/piggieback "0.2.2"]
                 [cider/cider-nrepl "0.17.0-SNAPSHOT"]]
  :main smoketest.core
  :profiles {:uberjar {:aot :all}})

gonewest81819:02:16

Above is project.clj. And next is src/smoketest/core.clj

gonewest81819:02:46

(ns smoketest.core
  (:require [clojure.tools.nrepl :as nrepl]
            [clojure.tools.nrepl.server :as server]
            [cemerick.piggieback])
  (:gen-class))

gonewest81820:02:03

That’s literally it. The compiler throws an exception:

Compiling smoketest.core
clojure.lang.ExceptionInfo: Call to clojure.core/ns did not conform to spec:
In: [1] val: ((require [clojure.string :as string] [cljs.source-map.base64 :as base64])) fails spec: :clojure.core.specs.alpha/ns-form at: [:args] predicate: (cat :docstring (? string?) :attr-map (? map?) :clauses :clojure.core.specs.alpha/ns-clauses),  Extra input
 #:clojure.spec.alpha{:problems [{:path [:args], :reason "Extra input", :pred (clojure.spec.alpha/cat :docstring (clojure.spec.alpha/? clojure.core/string?) :attr-map (clojure.spec.alpha/? clojure.core/map?) :clauses :clojure.core.specs.alpha/ns-clauses), :val ((require [clojure.string :as string] [cljs.source-map.base64 :as base64])), :via [:clojure.core.specs.alpha/ns-form], :in [1]}], :spec #object[clojure.spec.alpha$regex_spec_impl$reify__2436 0x527a8665 "clojure.spec.alpha$regex_spec_impl$reify__2436@527a8665"], :value (cljs.source-map.base64-vlq (require [clojure.string :as string] [cljs.source-map.base64 :as base64])), :args (cljs.source-map.base64-vlq (require [clojure.string :as string] [cljs.source-map.base64 :as base64]))}, compiling:(cljs/source_map/base64_vlq.clj:1:1)

mikerod20:02:26

@gonewest818 Looks like some ns header is wrong

mikerod20:02:43

Using require instead of :require

mikerod20:02:01

Maybe one of these project versions you are using isn’t compatible with clj 1.9

gonewest81820:02:12

It appears to be piggieback itself, although that doesn’t really make sense to me.

gonewest81803:03:09

nice dig, thanks for that.

mikerod03:03:11

No problem

ag20:02:10

so I can use (keyword "foo") and it creates :foo, how can I make it ::foo? i.e. I need fully qualified keyword bound to current namespace. I thought I could do something like (keyword (ns-name *ns*) "foo") but that didn't do the trick

dpsutton20:02:24

if you str the ns-name is works for me

dpsutton20:02:43

(keyword (str (ns-name *ns*)) "bob") => :breeze.mast.repl/bob

ag20:02:48

@dpsutton (ns-name *ns*) doesn't work for me in Clojurescript

dpsutton20:02:07

oh sorry. i'm in clj land. didn't notice the channel

ag20:02:26

cljs.user> (ns-name *ns*)
#object[TypeError TypeError: Cannot read property 'name' of null]
   cljs$core$ns_name (jar:file:/Users/ag.ibragimov/.m2/repository/org/clojure/clojurescript/1.9.946/clojurescript-1.9.946.jar!/cljs/core.cljs:11177:11)
nil

ag20:02:57

that is strange... it works in Lumo

ag20:02:06

but not in the browser

mikerod20:02:24

@ag isn’t Lumo self-hosted? In your standard cljs, the namespace (and var) info isn’t reified at runtime. It is only available at compile/macroexpansion time

mikerod20:02:29

I haven’t tried it, but it would seem to me that you could get it compiled into your js if you did something like

(def this-ns-name-str (namespace ::x))

mikerod20:02:23

Or in a macro body you could do similar things , like (:ns &env)

mikerod20:02:08

There is also, cljs.env ns that may have some things

ag20:02:32

okay, thanks for explaining it to me :spock-hand:

richiardiandrea20:02:23

nice link to SO, saved 😄 I also do this, seems to work fine:

(defmacro self-ns-name
  "Return the namespace name as string (at compile time - macro)."
  []
  (str *ns*))

mikerod20:02:46

Also, I see cljs.analyzer/*cljs-ns*

mikerod20:02:02

Which you’d see at compile time

mikerod20:02:10

I’m not sure if that is more reliable than *ns*

mikerod20:02:20

For some reason I was thinking that *ns* may have caveats, but I don’t know why

dpsutton20:02:45

> You can disable the Rebel readline by adding :readline false to your :figwheel config. i don't think readline works in emacs. Will CIDER users need to add this config for 0.15?

pesterhazy20:02:05

CIDER doesn't use an inferior process (i.e. communicate with a subprocesss via stdin/stdout) so it shouldn't be affected by rebel-readline, AFAICT

noisesmith20:02:20

@pesterhazy if you use cider-jack-in it does create an inferior process, but the process buffer (and all process output) is hidden by default, most cider users aren't likely to interact with it

noisesmith20:02:54

cider doesn't try to send input to that buffer though, as far as I know, so maybe the readline wouldn't matter

pesterhazy20:02:02

right, what I meant was that cider-jack-in doesn't talk to the repl via the process's stdin/out

noisesmith20:02:11

well it does read the stdout

bhauman21:02:21

@dpsutton CIDER calls lein repl so rebel-readline will not be engauged

dpsutton21:02:46

i tried it in the emacs terminal emulator and it was ... quirky 🙂

dpsutton21:02:51

but amazing on the command line

bhauman21:02:53

and then it connects to the nrepl connection

dnolen22:02:04

@jannis clj -e "(require '[cljs.closure :as cc] '[clojure.pprint :refer [pprint]]) (pprint (cc/index-node-modules-dir))" > npm.edn one liner

jannis22:02:08

@dnolen Sweet, yeah, I've done something similar in the meantime: wrap the function with redefs to capture it's I/O. My next question would be what kind of things or patterns I should be looking for in the output.

jannis22:02:07

Also, does this output go straight into Closure or are there other intermediary steps that could break things?

dnolen22:02:13

nothing 🙂

dnolen22:02:19

these are used as inputs to Closure

dnolen22:02:35

so if you want to require something and it doesn’t work, it would have broken here

jannis22:02:49

Ok, I'll see if I can spot any problems tomorrow.