Fork me on GitHub
#clojurescript
<
2017-11-03
>
madstap00:11:03

I think I read somewhere that you still have to use externs with :npm-deps'd libraries...

darwin00:11:13

it think some historical clojurescript transformed :npm-deps into :foreign-libs which wasn't part of :advanced optimizations, newly it seems to be according to that article

madstap00:11:33

Would love for someone to prove me right or wrong

darwin00:11:40

maybe you were reading some historical articles which are not correct anymore with latest clojurescript

darwin00:11:21

I'm sorry I'm not familiar with this stuff, @anmonteiro should be the right person to ask 🙂

madstap00:11:21

If I do use cljs-oops anyways, will it screw something up?

darwin00:11:28

it won't work, your PrismicJS brought by :npm-deps is subject to advanced optimizations name mangling, original "plain" dev names no longer exist in your advanced build

darwin00:11:21

you would have to take your PrismicJS out of :npm-deps and include it by hand in html script tag, then cljs-oops would be a great match, but you won't get :advanced optimizations for it

madstap00:11:51

Gonna try and change it to normal js interop then

darwin00:11:59

@madstap you have two options 1) use normal cljs interop with :npm-deps and latest clojurescript 2) use cljs-oops and manage PrismicJS outsite :npm-deps via html script tags

darwin00:11:22

1) is preferrable if PrismicJS works well with :npm-deps

madstap00:11:39

Got it, thanks!

madstap00:11:56

I changed it and now there's a new error.

madstap00:11:45

Gonna try just using it with script tags and oops and see if that works.

darwin00:11:10

that will work for sure

scaturr01:11:52

is it possible to require node modules in scripts meant for the browser? like for an electron app?

scaturr01:11:05

many of those examples use node modules like path

scaturr01:11:28

but target node adds the shebang stuff to the top of the script which makes the browser choke

Miloslav04:11:13

Hi everyone! Is ns-resolve macro or function?

Miloslav04:11:58

Can't find that in docs

Miloslav04:11:23

Will it affect performance?

Miloslav05:11:28

Btw I'm not going to use it for resolving components. I looked up how re-com components organized, and that's just fine. I'm going to do it the same way

phronmophobic05:11:29

ns-resolve is a function

phronmophobic05:11:50

what are you using ns-resolve for?

Miloslav05:11:23

I was trying resolve components with it, but re-com way seems a lot better

noisesmith05:11:16

ns-resolve is a little bit slower than using something directly, and using it to avoid having to use require is a bad idea (referencing prior conversation in this channel to infer that's what's going on here)

vargaradu12:11:10

have you guys made a time-zone selector that plays well with clj-time/cljs-time?

vemv12:11:04

do you mean a <select> element offering a list of timezones? seems trivial, just make its <option> values have a format cljs-time understands

vargaradu15:11:27

it’s not so trivial as it may seem to get that list of options. Joda Time specifies that is uses the Olson database (http://joda-time.sourceforge.net/timezones.html)

vargaradu15:11:13

My question is: how can it be accessible throught cljs-time ? Entering manually the options is not a good solution (there was an update in the timezones in 2011), also +1 +2 is no good (daylight savings, +4.30 type timezones, etc)

vemv15:11:54

there are updates to the TZs every year 🙂 A few (non-clojure) libraries I know are built out of http://www.iana.org/time-zones

vemv15:11:42

I reckon that a server-side clojure or java library exists. You could build the list in compile-time leveraging the JVM libs

vargaradu16:11:53

hmm yes, but a client side solution would be more conveniant than syncing with the server for those constants. maybe there’s a javascript library that fits with what joda is expecting

vemv12:11:58

(defrecord Foo)

(-> (->Foo) type pr-str)

vemv12:11:18

this returns "Foo" under unoptimized compilation

vemv12:11:38

but "bB" or something like that under :advanced

vemv12:11:57

any way to preserve this info in a clean manner?

vemv12:11:03

would be useful for logging

mfikes12:11:13

@melvoloskov Seems like you sorted things out, but FWIW, there is no ns-resolve in ClojureScript.

mfikes13:11:59

I'm curious: Do ClojureScript devs consider using if-some and when-some over if-let and when-let when you know you only need a nil check? In other words, for performance reasons, rather than a need to distinguish nil and false. Or is it generally still preferred to stick with the *-let variants and rely on the Clojure definition of falsey. I could see an argument that using *-some simply to avoid cljs.core.truth_ as being a premature optimization, and it being preferable to primarly only use *-some when you need its semantics (not perf).

leonoel13:11:43

I always default to the *-some version because of semantics (it's more specific)

mfikes13:11:12

@leonoel Thanks—I suppose you would then use *-let if you were using a bit of optional config from a map, and wanted a nil result of get to be semantically equivalent to an explicit false

leonoel13:11:18

in this case I prefer to use the arity-3 get

mfikes13:11:50

Yeah, *-let is a bad example for that one, as you don't really need the value

mfikes13:11:12

Just trying to think of where you might use *-let 🙂

leonoel13:11:31

tbh I never really got the point of conflating the idea of boolean with the idea of "being something"

leonoel13:11:02

both are binary concepts, but I prefer to make the conversion explicit

mfikes13:11:26

It might be the case that *-let is used out of habit, but if you scrutinize the needed semantics *-some nearly always fits. In other words it might be hard to find a case where *-let is actually what is needed (unless you are interacting with something that conflated the concepts, I suppose)

leonoel13:11:42

I'm a bit too young then, *-some functions existed before my clojure-birth

mfikes13:11:57

Hah. I think they also existed before my Clojure-birth, but I learned a lot of Clojure by reading code that was written before *-some. Perhaps the truth is that *-let could be use a lot less given *-some.

mfikes13:11:08

Now, I'm really interested in a good example where *-let is semantically exactly what is required 🙂

leonoel13:11:20

me too 🙂

pesterhazy14:11:49

How do I turn

[:a (js/Promise. (fn [resolve] (resolve :b))) (js/Promise. (fn [resolve] (resolve :c))) :d]
into
[:a :b :c d]
?

sundarj14:11:56

if those are native Promises, you're out of luck

sundarj14:11:24

Promise.all(["a", "b", Promise.resolve("c")]).then(arr => console.log(arr))
you can do this to get a flat array inside a Promise

qqq14:11:14

(mapv #(if (keyword? %) % ((deref %) identity)) ... ) ?

pesterhazy14:11:16

@qqq, clojurescript!

qqq14:11:38

I'm missing something -- why does cljs change this ?

pesterhazy14:11:52

clojurescript doesn't have blocking deref

qqq14:11:38

ah, so the best you can get is a (js/Promise. [:a 😛 :c :d]) ?

pesterhazy14:11:02

I get a smiley face in my promise??

qqq14:11:39

(js/Promise. [:a :b :c :d])

qqq14:11:50

is that the best we can do due to no blocking deref ?

pesterhazy14:11:09

I have a vector with some elements being promises; I want to do something the upshot of which is that I get the same vector, but with the promises replace by their results

sundarj14:11:44

you can't pull values out of promises - the state is private

sundarj14:11:17

the best you can do is access the flat array inside another promise

sundarj14:11:31

at least with native promises: if you use another promise library, they may have public state

pesterhazy14:11:54

yeah I'm using native promises

pesterhazy14:11:21

I'll end up doing something based on Promise.all - it doesn't have to be synchronous

sundarj14:11:29

yeah Promise.all works

sundarj14:11:47

figured you wanted it outside of a promise

pesterhazy14:11:47

I can't figure out how to check is a value is a promise

sundarj14:11:01

why do you need to do that?

pesterhazy14:11:33

well I need to walk the vector to extract all slots that need to be replaced

sundarj14:11:22

Promise.all works on a mixed array of promises and plain values

sundarj14:11:37

even if it did not, you could just map Promise.resolve over the array

pesterhazy14:11:39

@sundarj ah sorry I missed the thread

sundarj14:11:47

no worries

zignd14:11:48

Just curious, there is no equivalent to JavaScript's await keyword in ClojureScript?

pesterhazy14:11:50

there's core.async but that's a different model than promises

zignd14:11:20

Oh, I see

zignd15:11:27

@mccraigmccraig this alet macro seems very useful and would probably help in that case @pesterhazy showed

mccraigmccraig15:11:20

i've not used alet from funcool/promesa - i have used alet from funcool/cats, which is similar but more general - it's awesome

ajs15:11:11

What are the advantages of async/await over core.async?

pesterhazy15:11:22

@zignd, @sundarj, came up with this snippet for resolving deeply nested data structrures:

(defn deep-resolve [xs]
  (let [ks (->> xs
                (tree-seq coll? seq)
                (filter #(.-then %)))
        p (js/Promise.all (into-array ks))]
    (.then p
           (fn [vs]
             (let [m (zipmap ks vs)]
               (walk/postwalk #(if (contains? m %)
                                 (m %)
                                 %) xs))))))

sundarj15:11:37

instead of filtering by .-then, i would just (map js/Promise.resolve)

pesterhazy15:11:27

@sundarj wouldn't that make everything into a promise?

pesterhazy15:11:06

hmm then the idea would be to postwalk twice, but only to transform the leaf values

sundarj15:11:25

it would, yes. but it also means you don't lose the plain values, which i personally wouldn't want

pesterhazy15:11:05

think of a structure like

{:foo [(js/Promise.resolve 1) 2]}

pesterhazy15:11:29

it should work with a deeply nested structure like this as well

sundarj15:11:11

i must admit to not knowing how tree-seq and postwalk work yet

pesterhazy15:11:27

I agree that filtering by .-then is weird

sundarj15:11:08

it is how things like http://npm.im/is-promise also detect promises to be fair

souenzzo16:11:48

A promise could never return a lambda 😮

sundarj15:11:14

but i figure if you don't care whether something is a plain value or a promise then Promise.resolve is the way to go

souenzzo16:11:33

There is plans/make sense make promises work with deref logic?

mccraigmccraig18:11:37

@souenzzo in clojure promise-like things (e.g. clojure.core/promise and manifold/deferred) tend to support deref, but not in cljs - deref is blocking and so not a good fit for js execution model

souenzzo19:11:54

@mccraigmccraig promises now can deref'ed by await x = myPromise()

mccraigmccraig19:11:18

oh i see, that's not really a deref though - that's like alet or async/await in funcool/promesa http://funcool.github.io/promesa/latest/#async-await-syntax

phronmophobic21:11:37

cljsjs has small amount of info about creating externs, https://github.com/cljsjs/packages/wiki/Creating-Externs

phronmophobic21:11:28

although, the best case scenario is if the library you want is already available in cljsjs

phronmophobic21:11:18

the externs for react-grid-layout were created using http://jmmk.github.io/javascript-externs-generator/

phronmophobic21:11:53

not sure how fully featured that option is, but it can hopefully help get you started

gleisonsilva21:11:02

I've use that, but I can't get rid of the error:

$("#fluxo").treetable();
VM7812:1 Uncaught TypeError: $(...).treetable is not a function
    at <anonymous>:1:13

gleisonsilva21:11:22

I'm trying to create a externs for the treetable jquery plugin

phronmophobic21:11:23

that’s an example of externs for another jquery plugin

gleisonsilva21:11:06

but I can't figure out the name for the object

gleisonsilva21:11:27

I've tried jQuery, but doesn't work

phronmophobic21:11:47

is jQuery being included in the javascript somewhere on the page?

phronmophobic21:11:57

and being loaded before the code that is using it?

phronmophobic21:11:37

how are you referencing jquery from your cljs code?

gleisonsilva21:11:02

i'm not referencing from cljs yet.. just trying in browser console

phronmophobic21:11:54

if it’s not working in the browser console, then problem probably isn’t with the externs

phronmophobic21:11:12

as that’s a closure compiler thing

gleisonsilva21:11:43

works in browser console if I remove my cljs script tag

gleisonsilva21:11:02

Once my cljs script is loaded, doesn't work anymore

gleisonsilva21:11:09

do you know how i can check if the externs configuration are been loaded?

gleisonsilva21:11:39

this is how is my project.clj:

:cljsbuild {:builds
              [{:id "dev"
                :source-paths ["src"]

                ;; the presence of a :figwheel configuration here
                ;; will cause figwheel to inject the figwheel client
                ;; into your build
                :figwheel {:on-jsload "sghi-dashboards.core/on-js-reload"
                           ;; :open-urls will pop open your application
                           ;; in the default browser once Figwheel has
                           ;; started and complied your application.
                           ;; Comment this out once it no longer serves you.
                           :open-urls [""]}

                :compiler {:main sghi-dashboards.core
                           :asset-path "js/out"
                           :output-to "resources/sghi/js/sghi_dashboards.js"
                           :output-dir "resources/sghi/js/out"
                           :source-map-timestamp true
                           ;; To console.log CLJS data-structures make sure you enable devtools in Chrome
                           ;; 
                           :preloads [devtools.preload]
                           :optimizations :none
                           :externs ["resources/externs/treetable.ext.js"]}}

phronmophobic21:11:11

you should be able to just look at the output file

phronmophobic21:11:19

resources/sghi/js/sghi_dashboards.js

gleisonsilva21:11:31

what I should look for?

gleisonsilva21:11:51

when running with figwheel, my resources/sghi/js/sghi_dashboards.js just have the google closure thing

phronmophobic21:11:03

you have optimizations set to :none

gleisonsilva21:11:16

@darwin I didn't knew that

phronmophobic21:11:26

often, without optimizations, you don’t even an externs file

darwin21:11:39

forget about externs and get your life back 🙂

gleisonsilva21:11:41

@smith.adriane yes... i'm trying everything now...

phronmophobic21:11:57

so I would look at the output and try to figure out why jQuery is no longer there

gleisonsilva21:11:41

when using figwheel (dev build), should I find the references for treetable below out folder?

phronmophobic21:11:06

the references for treetable won’t show up in out folder

phronmophobic21:11:39

the closure compiler uses the externs file during optimization to prevent from renaming variables

phronmophobic21:11:27

for eg, if you had a method name that was really long, the closure compiler can rename it in the outputfile js file to produce a smaller output

gleisonsilva21:11:27

so, if i'm running the dev build, without optimizations, this would not be needed, right?

phronmophobic21:11:12

I don’t think you need an externs file if you’re not compiling with optimizations on

gleisonsilva21:11:58

worked! I've just moved the references of .js files after my own .js (.cljs file)

gleisonsilva21:11:44

this works:

<script src="js/sghi_dashboards.js" type="text/javascript"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.js" type="text/javascript"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-treetable/3.2.0/jquery.treetable.js" type="text/javascript"></script>

gleisonsilva21:11:16

if the reverse order, don't

phronmophobic21:11:41

weird, are you including jquery as one of your cljs dependencies?

gleisonsilva21:11:53

maybe indirect

gleisonsilva21:11:55

:dependencies [[org.clojure/clojure "1.8.0"]
                 [org.clojure/clojurescript "1.9.229"]
                 [org.clojure/core.async "0.2.391"
                  :exclusions [org.clojure/tools.reader]]
                 [cljs-ajax "0.5.8"]
                 [reagent "0.6.0"]
                 ;;[com.cognitect/transit-cljs "0.8.239"]
                 [cljsjs/d3 "3.5.5-0"]
                 [cljsjs/c3 "0.4.11-0"]
                 [cljsjs/bootstrap "3.3.6-1"]
                 [lein-doo "0.1.6"]

phronmophobic22:11:48

i might try keeping the same script tag order while commenting out the jquery script tag

phronmophobic22:11:03

otherwise, you might be including two jquery’s

gleisonsilva22:11:31

thank you very much!

phronmophobic22:11:33

you can also do `lein deps 🎄

phronmophobic22:11:43

lein deps :tree

gleisonsilva22:11:02

i will do this now

gleisonsilva22:11:34

[cljsjs/bootstrap "3.3.6-1"]
   [cljsjs/jquery "1.9.1-0"]

phronmophobic22:11:15

and if you ever get the externs figured out for treetable, you can send a pull request to the cljsjs folks to save others the trouble. they’re pretty friendly

ajs22:11:21

is the order of directories in source-paths honored, such that in this example, "src" will be compiled (and evaluated) first, followed by the second env ns? :source-paths ["src" "env/prod/cljs"]

ajs22:11:34

i'm just curious how the reagent-frontend-template "knows" to run the env/prod/cljs ns first, since there is no main

noisesmith22:11:19

I’d look for what the script tag in the html loads, you can work back from that

noisesmith22:11:02

for example I don’t use main for that - I have a script tag that ensures my js is loaded, and another that invokes my top level function with inline js (providing args as apropriate to the client)

ajs22:11:10

eh, just says "app.js"

ajs22:11:50

the reagent template has namespaces in dev/ and prod/ which actually load the main app. the dev setup has :main, but the prod does not, yet the prod namespaces still calls the core entry function, so was curious how that works

noisesmith22:11:10

there’s no other tag that invokes something defined by app.js? if not, there must be some automatic magic in the reagent-frontend-template code

juhoteperi22:11:32

the cljs file in prod/ just calls the init fn on toplevel

juhoteperi22:11:48

toplevel code from all ns is evaluated when loading the app in browser

ajs22:11:24

both dev and prod call (core/init!) but the dev setup uses :main to do this, while prod does not. I was curious the reason for this.

urbank23:11:13

Do cljsjs requires even make sense in a cljc file ?

phronmophobic23:11:47

for eg, if you had a function like save!

phronmophobic23:11:01

you could implement in cljs via a jquery ajax call

phronmophobic23:11:15

and in clojure by writing to a database

urbank23:11:53

Yes, right. I though something was incompatible because it complained that it couldn't find the cljsjs library.. it was my error