Fork me on GitHub
#clojurescript
<
2018-10-19
>
kingcode04:10:55

Does anyone know what is the simplest way to traverse a <select multiple…> ’s options? It is not a seqable, or even a JS array - I can’t (aget .. ) on it. I would hope to avoid having to use jayq…maybe goog closure? Thanks for any suggestion..

Azzurite06:10:30

you can always (aclone ...) a HTMLCollection (returned by (.-options select-elem) and then it's seqable and a JS array

Azzurite06:10:51

(that's how you would do it in Vanilla JS, so that's always an option)

roman01la08:10:22

array-seq transforms ArrayLike JS structures into a sequence

andrea.crotti10:10:13

assuming I have a project A that is only backend only

andrea.crotti10:10:27

and a project B which can be used as a dependency of A to give some extra functionality, but uses Clojurescript

andrea.crotti10:10:25

the actual JS asset is generated when B builds its jar file, I wonder does A really also need to have Clojurescript as dependency?

andrea.crotti10:10:53

is there a way to avoid getting that extra dependency if it's not really actually used anyway in A?

thheller10:10:02

@andrea.crotti technically no library needs a clojurescript dependency. you only need it when building.

thheller10:10:09

so no A does not need a clojurescript dependency

andrea.crotti10:10:12

yes ok cool @thheller but it will still be included in A jar right?

andrea.crotti10:10:45

it's a transitive dependency since A depends on B

thheller10:10:42

you do NOT need clojurescript once its compiled

thheller10:10:23

so if you include the compiled .js file and use that you no longer need clojurescript dependency at all

andrea.crotti10:10:53

yeah but B doesn't just build a single js file, it's also a backend server, and A depends on B

thheller10:10:55

so clojurescript is a development only dependency

andrea.crotti10:10:45

and yes I agree, but still leiningen would include it in A uberjar as far as I understood

andrea.crotti11:10:03

with all the other transitive dependencies inherited from B

thheller11:10:44

the clojurescript dependency only matters when actually compiling the code

thheller11:10:50

so it should never end up in any uberjar ever

andrea.crotti11:10:14

ah ok if that's how it works cool

thheller11:10:27

it only works that way if you set it up that way

thheller11:10:43

if you just put clojurescript into your normal :dependencies then it will end up in your uberjar

thheller11:10:54

typically you put it into a :dev profile instead

thheller11:10:07

or create a dedicated :cljs profile/alias

thheller11:10:12

whatever setup you prefer really

thheller11:10:24

:scope "provided" in case of A also works

andrea.crotti11:10:30

ah ok I got it, I think in none of the projects we do it that way

andrea.crotti11:10:39

so ok that's the solution

andrea.crotti11:10:08

interestingly I can't find any place where this "advice" is actually documented

andrea.crotti11:10:24

seems like an easy and straightforward thing to do

andrea.crotti11:10:00

I tried on a couple of projects already though and uberjar doesn't work

$ lein with-profile dev uberjar
Compiling ClojureScript...
WARNING: It appears your project does not contain a ClojureScript dependency. One will be provided for you by lein-cljsbuild, but it is strongly recommended that you add your own.  You can find a list of all ClojureScript releases here:

andrea.crotti11:10:14

so I guess something else is missing

thheller12:10:11

the uberjar task should just copy files from the classpath into the final .jar. you probably want to create the .js file in a separate task.

thheller12:10:19

:aliases
{"build-uberjar"
 ["do"
  ["cljsbuild" ...]
  "uberjar"]}

thheller12:10:26

then lein build-uberjar

andrea.crotti13:10:23

ah ok good point

andrea.crotti13:10:46

ah actually I forgot I had that already

:uberjar {:hooks []
             :source-paths ["src/clj" "src/cljc"]
             :prep-tasks [["compile"]
                          ["garden" "once"]
                          ["cljsbuild" "once" "min"]]

             :omit-source true
             :aot :all
             :main elo.api}

andrea.crotti13:10:37

maybe doesn't work simply because cljsbuild running there doesn't pick up the right profile

andrea.crotti13:10:40

ah yes this fixed it - ["cljsbuild" "once" "min"]] + ["with-profile" "dev" "cljsbuild" "once" "min"]]

andrea.crotti13:10:23

even though it didn't work the jar is even bigger now 😄

thheller13:10:45

I think running cljsbuild as part of the uberjar profile is the problem

thheller13:10:10

but I do not use cljsbuild so I'm not really sure what it may be doing

andrea.crotti13:10:52

ah ok I see, I think I just originally did it this way because Heroku simply runs lein uberjar

andrea.crotti13:10:11

by default at least there might be a way to change the build command

isaac12:10:40

# cljs_opts.edn
{:output-dir    "resources/web/js/out"
  :output-to     "resources/web/js/announcements.js"
  :optimizations :none
  :asset-path    "resources/web/js/out"
  :verbose       true
  :pretty-print  true
  :main          app.announcements
  :target        :nodejs
  :modules
  {:ws {:entries   #{}
        :output-to "resources/web/js/ws.js"}}}
(ns app.announcements
  (:require-macros [cljs.core.async.macros :refer [go go-loop]])
  (:require [cljs.core.async :as a :refer [<! >!]]
            [time.core :as t]
            [async.http :as http]
            [clojure.string :as str]
            [cljs.reader :refer [read-string]]
            ["nodemailer" :as mail]
            ["sqlite3" :as sqlite])
  (:import [goog.string format]))

(ns 
  (:require ["ws" :as WebSocket]
            ["pako" :as pako]))
# compiler command
clj -A:cljs -m cljs.main -co cljsc_opts.edn -w src/cljs -c

# throws:
java.lang.Exception: No input matching "pako"
        at cljs.module_graph$canonical_name.invokeStatic(module_graph.cljc:179)
        at cljs.module_graph$canonical_name.invoke(module_graph.cljc:173)
        at cljs.module_graph$inputs__GT_assigned_modules$canon__4705$fn__4706.invoke(module_graph.cljc:216)
        at clojure.core$map$fn__5583$fn__5584.invoke(core.clj:2734)
        at clojure.core.protocols$fn__7852.invokeStatic(protocols.clj:168)
        at clojure.core.protocols$fn__7852.invoke(protocols.clj:124)
        at clojure.core.protocols$fn__7807$G__7802__7816.invoke(protocols.clj:19)
        at clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:31)
        at clojure.core.protocols$fn__7835.invokeStatic(protocols.clj:75)
        at clojure.core.protocols$fn__7835.invoke(protocols.clj:75)
        at clojure.core.protocols$fn__7781$G__7776__7794.invoke(protocols.clj:13)
        at clojure.core$transduce.invokeStatic(core.clj:6804)
        at clojure.core$into.invokeStatic(core.clj:6819)
        at clojure.core$into.invoke(core.clj:6807)
        at cljs.module_graph$inputs__GT_assigned_modules$canon__4705.invoke(module_graph.cljc:216)
        at cljs.module_graph$inputs__GT_assigned_modules$assigns__4709$fn__4711.invoke(module_graph.cljc:225)
        at clojure.core$fn__8072$fn__8074.invoke(core.clj:6760)
        at clojure.core.protocols$iter_reduce.invokeStatic(protocols.clj:49)
        at clojure.core.protocols$fn__7839.invokeStatic(protocols.clj:75)
        at clojure.core.protocols$fn__7839.invoke(protocols.clj:75)
@dnolen this is my ns files & my compiler-options file

thheller12:10:38

@isaac you don't usually use :modules for :nodejs builds. just :main should be enough

isaac13:10:25

yeah, it is usually. but sometimes I want to export a lib

TeMPOraL13:10:26

I'm not sure if this is a hiccup thing, and I can't find anything in its documentation, but I've seen code using syntax like:

[:> someComponent ...]

TeMPOraL13:10:37

anyone recognizes where that :> comes from and what does it mean?

thheller13:10:57

@temporal.pl its a reagent thing for native react components

TeMPOraL13:10:22

I had a hard time typing :> into Google...

domkm16:10:21

Odd question: I have a macro which can be called from ClojureScript. This macro expects a basic function as an argument, which it then calls during macro-expansion (calling must happen at expansion time, not run time). Passing a function and evaling works in Clojure. In ClojureScript, I get a Unable to resolve symbol: SYM in this context for every SYM that is unqualified. Is there a good technique for passing a CLJ function to a CLJ macro from CLJS?

polymeris17:10:53

Does it complain even if the symbol is quoted?

thheller17:10:09

thats not possible

mfikes17:10:48

Perhaps if you control the macro you can make it resolve to the function given some symbols

mfikes17:10:11

(You'd have to change the macro's implementation.)

domkm17:10:23

Thanks for all of the responses. @mfikes Yes, I do control the macro's implementation. @thheller It seems at least sort-of possible because eval will work correctly if I fully qualify relevant symbols. For example, passing the function in like (clojure.core/fn [arg] ...). @polymeris It depends which symbol, see above.

mfikes17:10:32

This appears to work

(defmacro foo [f] ((eval f)))

domkm17:10:54

How are you invoking foo?

mfikes17:10:12

Let me make a gist of the code

thheller17:10:40

well you can do it in a rather limited fashion since the CLJ side can't see anything from the CLJS side

thheller17:10:10

eg. call no functions defined in CLJS and so on

domkm17:10:44

Yeah, understood, that's what I am trying to do. Just having issues with eval of what should be purely clojure code.

thheller17:10:59

question would be why you'd want to do this in the first place. seems mind bending just thinking about it?

domkm17:10:11

Like (eval '(fn [x] ...)) errors in a macro of that macro is expanded from CLJS

domkm17:10:26

Hah, yeah, it's unusual

domkm17:10:28

I am compiling clojure.specs inside of a macro. It has to be in a macro because clojure.spec relies on macros (especially CLJS clojure.spec due to registering specs during macro-expansion for use by instrument). The function passed in is a basic function that can cause the macro to alias some specs. As such, it has to be called from Clojure during macro-expansion.

domkm17:10:54

Thanks @mfikes. Yeah, that will work. That's the fully-qualified and resolvable case. But what if the macro is called like (foo.core/bar (fn [x] ...))?

mfikes17:10:43

Yeah, oddly you can qualify fn and get by: (foo.core/bar (clojure.core/fn [] 1))

domkm17:10:02

Exactly, and that requires qualifying every non-local symbol. A test function I am using is:

(clojure.core/fn [kw]
  #{(clojure.core/keyword
      (clojure.core/namespace kw)
      (clojure.core/str (clojure.core/name kw) "-alias"))})
That works but if any of the syms are unqualified it will fail. I just don't understand why evaling the following in a macro works in Clojure but not ClojureScript:
(fn [kw]
  #{(keyword
      (namespace kw)
      (str (name kw) "-alias"))})

mj_langford19:10:05

I'm trying to do basic json based HTTP calls in a re-frame app using the cljs-ajax library. Is there a generally recommended way I should be marshaling data into and out of json?

mj_langford19:10:14

It seems there is a mode of the cljs-ajax library that avoids core.async. Is that worth using if I don't need it elsewhere in the app?

kingcode21:10:45

Does anyone know how to reference an extern? I am using jayq, but keep getting the ‘can’t find jquery.js’. I am not using optimizations - I’ve tried :compiler {:infer-externs true…}, but to no avail..What’s the simplest way to get this done? Thanks for any comment..

kingcode21:10:21

Thanks @isak, I got the externs file but don’t know where to drop it…should it be inside public/js/? Will read through the docs, but it seems complicated and I am trying to save time….

isak21:10:26

@kingcode it is relative to your source path, so e.g., "src/externs/foo.ext.js"

kingcode21:10:07

@isak OK thx, will try that…

lwhorton21:10:31

can someone explain to me a piece of the . dot special form that doesn’t make sense? why are these equivalent:

(. js/document hasFocus)
(. js/document (hasFocus))

lwhorton21:10:44

is there ever a case where with-parens and without-parens are not equivalent?

lwhorton21:10:13

it can’t have something to do with argument grouping (i think), because you’re not currying arguments

lwhorton21:10:22

for example: document.foo = (x, y) => { console.log(x, y); return function(a) { console.log(a)}} i cannot invoke (. js/document (foo 1 2) 3) as if it were somehow curried (it’s a “dot with extra arguments” error)

thheller21:10:44

its the same in ->. a plain symbol is equivalent to that symbol wrapped in a list

thheller21:10:23

(. js/document foo 1 2 3) would also be valid

thheller21:10:51

equiv to (.foo js/document 1 2 3)

lwhorton21:10:57

> a plain symbol is equivalent to that symbol wrapped in a list oh. is this just part of the macro’s definition?

lwhorton21:10:10

(and other such macros — which would make it a language spec?)

thheller21:10:58

-> ->> .. etc all behave that way

lwhorton21:10:27

that clarifies things a lot, thanks. i’m working on an internal blog post to help out some newbies to the interop stuff

lwhorton21:10:38

and as always, i learn more from teaching than they probably learn from learning

mfikes21:10:19

@lwhorton It appears that the ability to optionally use parens (your example (. js/document (hasFocus))) is useful when writing macros. (I'm curious to see this in practice.)

mfikes21:10:41

This is from https://www.clojure.org/reference/java_interop#dot where it has the sentence "Note that placing the method name in a list with any args is optional in the canonic form, but can be useful to gather args in macros built upon the form."

lwhorton22:10:34

perfect, an exact spot in the documentation/guides is a nice link for a blog post