Fork me on GitHub
#clojurescript
<
2018-03-30
>
xiongtx00:03:10

@dnolen @mfikes Is the new :aot-cache supposed to speed up builds for a single project, or only for another project that uses the same compiler/options? @rads and I didn’t see much difference when using the cache on a single cljs project.

dnolen00:03:39

it only affects cold builds the first time

dnolen00:03:44

you won’t recompile dependencies

dnolen00:03:58

the biggest impact is of course for REPLs, much faster to start

dnolen00:03:50

but there’s also benefit for projects

dnolen00:03:00

since if you blow away out you’re not going to recompile the world

dnolen00:03:06

just your stuff

zaphodious04:03:34

I have a cljs vector of url strings, and I'd like to pass it into cache.addAll(), which takes a js array. Apparently clj->js isn't working. How else would I do this?

zaphodious04:03:07

nevermind, I think I found it. transforming to a seq first seems to work.

borkdude11:03:48

It sounds awesome this AOT cache, since cljs is now the main part of our build time

borkdude11:03:16

So turning on :aot-cache is a kind of “pray it works if my deps don’t use macros which rely on the environment at build time” feature?

robert-stuttaford11:03:26

any idea how i’d verify that shared-aot working?

borkdude11:03:10

Does the AOT cache also have a benefit if you’re compiling advanced?

robert-stuttaford11:03:14

afaik it caches the stuff that’s happening in “output-dir” for each jar, so that your output-dir only has your project’s files; ie the stuff that happens before advanced compilation’s reduction process

borkdude11:03:39

@robert-stuttaford I guess it should populate ~/.cljs or something? After I compiled it remained empty

robert-stuttaford11:03:44

guess it’s time to read the source 🙂

borkdude11:03:43

On my system it remained empty, so I guess something is not working Scratch that. ls -la ~/.cljs/.aot_cache is populated.

borkdude11:03:54

Are there any libraries that are known to be problematic with aot-cache right now?

borkdude11:03:03

Hmm, cold compilation in boot didn’t get faster though the second time. Still 1 minute for :none.

robert-stuttaford11:03:12

all i know is that the issue is with macros that read the environment. not specifically aware of any libs that do that

dnolen12:03:23

Figwheel, dev-tools, the env macro thing

borkdude12:03:39

I do use dev-tools. Guess I’ll turn it off for now.

dnolen12:03:48

it’s pretty much not usable for existing development until those libraries change to goog-define

dnolen12:03:20

it’s enabled by default only for cljs.main

dnolen12:03:33

so greenfield stuff can avoid problematics libs

dnolen12:03:18

@borkdude cold compilation won’t be faster the second time

dnolen12:03:42

:aot-cache makes REPLs and fresh builds faster (you had to blow away the local cache)

robert-stuttaford12:03:59

ahh i’ll try clearing it all first and then compare

borkdude12:03:14

define fresh build / cold compilation the second time

dnolen12:03:33

first compile will be faster

dnolen12:03:37

same as REPLs starting faster

borkdude12:03:54

first compile provided there’s already something in the cache, I assume?

dnolen12:03:04

there always will be

dnolen12:03:09

things get compiled once to get into the cache

dnolen12:03:25

i.e. you would only compile Figwheel one time ever

dnolen12:03:31

or cljs-devtools etc.

borkdude12:03:52

that’s what I meant. First time compiling with aot-cache on will take longer than the second time.

borkdude12:03:02

if you’ve never ran before with that option

robert-stuttaford12:03:07

rm -rf ~/.cljs/.aot_cache
time make compile
clojure -m cljs.main -co "{:source-map \"resources/js/app.js.map\"}" -d resources/js/out -t browser -O advanced -o resources/js/app.js -c bridge.main
make compile  84.16s user 2.49s system 298% cpu 29.012 total
time make compile
clojure -m cljs.main -co "{:source-map \"resources/js/app.js.map\"}" -d resources/js/out -t browser -O advanced -o resources/js/app.js -c bridge.main
make compile  84.46s user 2.67s system 317% cpu 27.429 total

borkdude12:03:38

but I couldn’t tell the difference.

dnolen12:03:54

@robert-stuttaford advanced is always a wash

robert-stuttaford12:03:16

ahh 🙂 ok, then yes, basically on hold until figwheel catches up

robert-stuttaford12:03:22

good to know, thanks

dnolen12:03:42

we know it works 🙂

dnolen12:03:58

it’s the reason browser REPL starts in 1.5-3 seconds

robert-stuttaford12:03:17

👍 i’m stoked!

dnolen12:03:36

but again, it’s not going to make your build faster in general

dnolen12:03:58

just fresh builds, and the most impact is for dev - :none

robert-stuttaford12:03:35

👍 i’m with you. particularly valuable for devs who work on several projects, or when switching around between branches - i.e. all of us, heh

dnolen12:03:19

yes stuff like that

borkdude12:03:27

incremental compilation is already very good, also when switching between branches

dnolen12:03:57

it’s more impactful for switching between build ids

dnolen12:03:07

we cache according to specific compile options

borkdude12:03:03

in my dev init function:

(set! s/*explain-out* expound/printer)
(s/check-asserts true)
(stest/instrument)
makes life a lot easier when you’re refactoring stuff 🙂

robert-stuttaford12:03:25

https://github.com/robert-stuttaford/bridge/blob/master/test/bridge/test/util.clj#L8-L27 sets your tests up such that they have what they need without messing with those values, @borkdude, for use with (use-fixtures :once test-setup)

robert-stuttaford12:03:43

makes for easier tdd in general

borkdude12:03:47

We don’t write front end tests 😛

borkdude12:03:29

I know, controversial, but we write browser tests for now (with etaoin, recommended!)

borkdude12:03:48

I run those and when an fdef throws, I know I have to fix something there

robert-stuttaford12:03:55

oh, heh, i have what you said in dev/user.clj as well. forgot this is #clojurescript -grin-

joshkh12:03:50

can anyone provide some tips for debugging the Undefined nameToPath for [node module] error? i'm using cljs 1.10.238 with :npm-deps {:interactjs "1.3.3"} :install-deps true in my build config.

borkdude12:03:23

@joshkh the most obvious thing I can think of is checking whether node_modules is populated?

joshkh12:03:56

good start! yup, it's there.

borkdude12:03:09

what does your require look like?

dnolen12:03:49

@joshkh that usually means there’s something about that library that prevents it from working

dnolen12:03:24

one thing that’s known not work is any library with scoped deps in its dep graph

joshkh12:03:24

ah, so it's not using a common export method

dnolen12:03:10

oh trick is to :pretty-print true in your compiler options

dnolen12:03:21

and look at out/node_modules and see if Google Closure messed it up

joshkh12:03:00

i'll give that a shot, thanks.

joshkh12:03:50

since you're here and very much the right person to ask, i was wondering about about this scenario: i have a cljs project that makes use of npm-deps, and the project itself a dependency of a larger cljs project. compiling the parent project doesn't/can't trigger any process that installs npm deps for those found in its dependencies.

joshkh12:03:40

the only work around i found was to copy the npm-deps key to the parent project (which is fine in my case). but that seems like a "gotcha" for someone else that might not be aware that one of their dependencies has an npm dependency.

dnolen12:03:31

already solved

dnolen12:03:37

we support upstream :npm-deps

dnolen12:03:50

you need a deps.cljs file in your JAR

dnolen12:03:05

just like CLJSJS packages, but they only use :externs :foreign-libs keys

dnolen12:03:11

you can put :npm-deps in there too

joshkh12:03:31

perfect! thank you.

joshkh13:03:00

cheers, thanks

borkdude13:03:49

(I didn’t know this myself, so thanks for asking)

danielo51514:03:50

Fast question, what is the cljs equivalent of Array.find(predicate) ?

danielo51514:03:47

some maybe ?

tankthinks14:03:24

Yes, I would use some

danielo51514:03:17

But the docs are a bit confusing to me, seems that it returns whatever the predicate returns

danielo51514:03:20

Is that correct ?

dnolen14:03:22

there’s nothing exactly like find, filter + first is probably closest?

tankthinks14:03:26

@rdanielo, I usually see (some #(when (even? %) %) [1 2 3]) or if the predicate is membership (some #{2} [1 2 3])

tankthinks14:03:46

I like some if it’s set membership and prefer filter + first in other cases … just my preference

danielo51514:03:21

Well, filter + first seems like the correct approach. However I'm worried about performance, I don't want to filter the entire collection just to pick the first element

spinningtopsofdoom15:03:58

Filter is lazy so calling first with filter will run through the collection until you get to the an element that has not been filtered

spinningtopsofdoom15:03:14

for example (take 2 (filter even? (range))) => (0 2)

dnolen15:03:54

@rdanielo unlike JS most sequence stuff in Clojure(Script) is lazy

danielo51515:03:47

Even in runtime ?

danielo51515:03:10

Regarding macros, is there any difference between:

(some-> stuff
          :data 
          first 
          :stacks
          req/get)
And
(some-> stuff
    (:data)
    (first)
    (:stacks)
    (req/get))
??

dnolen15:03:51

@rdanielo lazy means runtime 🙂

robert-stuttaford15:03:05

@rdanielo why not macro-expand both forms and compare? 🙂

dnolen15:03:41

short answer, threading macros wrap naked forms

danielo51515:03:43

@dnolen Obviously (stupid question from my side), hahaha, is just that I can't imagine how that could be a reality at JS runtime

dnolen15:03:14

this is not lazy like Haskell - just sequence abstraction is lazy in Clojure(Script)

danielo51515:03:15

@robert-stuttaford because I am absolute noob and I didn't know about macro expand

robert-stuttaford15:03:33

feel the learn, @rdanielo - welcome!

dnolen15:03:45

(some-> x y) is equivalent to (some-> x (y))

dnolen15:03:08

but true for all -> ->> macros

danielo51515:03:42

So this is equivalent too (-> x a b c) (-> x (a) (b) (c))

danielo51515:03:57

Can I use this the same way as a function pipe or it is slightly different ?

danielo51515:03:02

This seems to be wrong:

(defn Get [url] 
 (let [c (chan)] 
  (req/get url 
    #(>! c (js/JSON.parse (.-body %2))))))
It requires a go block. My question is, should I just use >!! or a go block, and if I use a go block, whre should I put the go statement? Inside the lambda? outside ?

john15:03:25

so, >!! isn't available in cljs

john15:03:17

I think in your example, you may want to have the function return the c and wrap the req/get form in a go block. Then execute Get in another go block of another function, and within that other go block you can then pull the value out of the c that is returned.

john15:03:23

and print it or pass it to another function, while in that go block. Unfortunately, as with js promises, once you enter the go context, you have to continue pushing things through more go contexts

danielo51515:03:28

How to use outside it's clear

danielo51515:03:33

At the end I put the go block inside the lambda

danielo51515:03:02

Well, sounds exactly the same trap as promises or monads

danielo51515:03:25

I end up with this

(defn Get [url] 
 (let [c (chan)] 
  (req/get url 
    #(go (>! c (js/JSON.parse (.-body %2)))))
  c))

john15:03:31

same, but from within a go block, you can write idiomatic code, which is nice.

danielo51515:03:20

Well, I'm used to promises, so they are cool to my eye :grinning_face_with_one_large_and_one_small_eye:

john15:03:31

hmm, maybe you don't need a go block for the put? I can't remember. I don't use core.async that often, but you're on the right track.

john15:03:30

You'll definitely need a go block for the take, when you want to handle the result

danielo51515:03:33

And according to the stack trace I need the go block for the put too

danielo51515:03:57

Is this a correct usage of the #js macro ?

danielo51515:03:13

(#js { "auth": 
        #js { "user": usr,
              "pass": pass,
              "sendImmediately": false}})

danielo51515:03:24

(it is inside a function which should return that

john15:03:44

you appear to be converting js into js

john15:03:01

you want to pass map-like things to #js

john15:03:11

but you are correct that #js is only one level deep, and you have to nest them to handle nested maps. clj->js will do it recursively

danielo51515:03:05

What is the cheaper way to create a js object ? This seems to work:

(defn makeAuth [usr pass] 
  #js { :auth
        #js { :user usr
              :pass pass
              :sendImmediately false}})

john15:03:25

also, #js is a data reader, so you don't use it as a function, in the function position

john15:03:47

it probably calls a macro, but it operates on the thing at read time

john15:03:03

there you go, yea

john15:03:21

#js will be "cheaper"

dnolen15:03:22

#js {...} and js-obj are more less equivalent, js-obj is a bit fancier in that keys can be expressions I believe

dnolen15:03:33

but also, unless you’re calling this a billion times a second

dnolen15:03:36

performance is irrelevant

john15:03:50

(compared to clj->js)

dnolen15:03:35

right but clj->js is fine if you’re not converting massive payloads

danielo51515:03:07

In my case, I will

john15:03:16

yeah, I'm usually working with nested things, so I'll grab for cljs->js most of the time anyway

dnolen15:03:40

@rdanielo then neither clj->js nor #js will help you anyway

danielo51515:03:44

So I will use native JS methods to fetch basic data types (strings, and that stuff) and then #js macro for small payloads I will send

dnolen15:03:48

and you’ll want to use Transit

dnolen15:03:27

wire format for Clojure(Script)

dnolen15:03:33

to avoid marshalling to JS stuff

john15:03:38

@rdanielo in your case, you will need to be worried about the performance of the conversion?

danielo51515:03:28

I am worried about js->clj, because I'm talking to an API which is, what was the name

danielo51515:03:48

That APIs that sends you all available actions and all available relative links...

john16:03:05

swagger?

danielo51516:03:09

@dnolen any link to that transit ?

dnolen16:03:16

first rewind

dnolen16:03:29

the question you should ask yourself is should I bother converting

dnolen16:03:40

if in the end most of your stuff is JSON already

dnolen16:03:57

if the answer is yes, stop marshalling

dnolen16:03:00

just deal with JSON

john16:03:41

Yeah, that's a tough judgment call. I want all my things to be persistent data structures. I want to Clojurify all the things. But if all I'm really doing is going to be pushing JSON out the other end anyway, passing through js values and operating on them raw can be more performant.

danielo51516:03:48

I'm using a native js request library, but it returns the body as string, so I can convert it to whatever JSON format I want

john16:03:50

It's just not very clojury

danielo51516:03:05

So I would prefer to convert to a native cljs format if possible

john16:03:45

nothing is going to be faster than JSON.parse(... but again, if this isn't a performance bottleneck, perhaps your data belongs in clojure-land. If your app basically consumes and produces JSON, or it needs to be super performant...

dnolen16:03:59

why use JS stuff if there’s equivalent CLJS stuff

dnolen16:03:03

swimming upstream

john16:03:01

you mean transit? To get a quicker conversion?

danielo51516:03:26

So it is transit a cljs tool ? Something like the binary format that google uses ?

dnolen16:03:25

we’re talking about too many things here because we’re trying to understand what you’re trying to accomplish

dnolen16:03:48

Some basic rules of thumb

dnolen16:03:51

1) if a ClojureScript library for something you want exists, just use it

dnolen16:03:59

otherwise you will have to convert to JS for no reason

dnolen16:03:16

2) If you can’t avoid 1), don’t waste time coverting - deal with JSON

dnolen16:03:20

the stuff about Transit is tangential

dnolen16:03:43

if you’re a newcomer you may be inclined to use some JS thing you used before

dnolen16:03:56

this isn’t a good idea, unless you must

dnolen16:03:59

it’s also unnecessary since many popular typical tasks have ClojureScript equivalent

dnolen16:03:17

even if you can’t find a ClojureScript thing - you still shouldn’t use whatever JS thing you used before

dnolen16:03:25

you should use Closure Library

dnolen16:03:53

you’re life will be much simpler

danielo51516:03:33

@dnolen I agree with you on all points. however I didn not found any good http library for clojurescript targeting node, that's why I'm using a js one. Also all the examples I saw about this topic (cljs on node +http apis) uses a JS library, no one uses a cljs library

john16:03:22

ah yeah, nodes a bit of a different beast. I take it the goog..xhr stuff doesn't work over there?

danielo51516:03:41

No, node does not have xhr

danielo51516:03:49

It has other better alternatives, IMO

dnolen16:03:57

I’m surprised there’s a not a thin wrapper for Node.js net stuff

danielo51516:03:28

@dnolen me too. There is one, but it is 4 years old

danielo51516:03:31

Why does bootstraped cljs tools can't use core.async ? If they all compile down to JS ?

john16:03:01

maybe there should be a node corollary

dnolen16:03:16

not going to put any Node.js stuff in ClojureScript

dnolen16:03:23

community can and should sort it out on their own

john16:03:16

a community thing could definitely follow the patterns in . I'd probably prefer to consume that.

john16:03:24

I'm not sure what the specific reasons were, but it's usually because some macro stuff from a clj lib needs some mangling over on the cljs side, when a particular lib doesn't port over cleanly (or interop stuff)

dnolen16:03:35

I’m really not sure about that

dnolen16:03:44

Ring spec is near universal

danielo51516:03:44

@john, I know. I am just curious

danielo51516:03:34

Dam, error messages are horrible. What is this supposed to mean ?

Exception in thread "Thread-37" java.lang.IllegalArgumentException: No matching method found: printStackTrace for class java.net.SocketException
There is no info about what caused the error

dnolen17:03:20

there should be a full stacktrace

dnolen17:03:07

maybe but just as there the full stacktrace would tell you something

dnolen17:03:32

paste that somewhere

dnolen17:03:56

also describe what you are doing, currently we’re are about as informed as you are 🙂

dnolen17:03:07

what REPL? Browser, Figwheel, something else?

danielo51518:03:41

At the end I figured the error by executing the resulting javascript and taking a look at the js stack trace wich was a bit nicer

danielo51518:03:32

The problem was trying to execute a function partially applied which was not a function, but a partially applied string 🤪

danielo51518:03:37

(def (partial arg1 arg2)) instead of (def (partial fun arg1 arg2))

john18:03:49

That Java socket exception is unreasonably unhelpful though. I think the repl side may have been able to do a better job here.

john18:03:25

But you do need to provide def a symbol to bind a value to.

kingcode18:03:17

How would one refer to an external (possibly non-Google-closure compatible) Module? I am trying to create a new React class using `(require ’[react]) (def myComponent (reify React.Component (render [] (fn ...)))) but I get a NullPointerException for the reify form (I assume React.Component can’t be found) I know React.createClass is deprecated, and that there is a react-create-class patch for npm, but I just have a vanilla clojurescript app. Thanks for any comment...

nenadalm19:03:50

easiest way to use js libraries is via cljsjs https://cljsjs.github.io/. You can find React there with instructions how to call it.

mikerod20:03:29

@U06BUCH6D If cljsjs doesn’t have anything for you, you can read through https://gist.github.com/jmlsf/f41b46c43a31224f46a41b361356f04d for more on the subject. In that post it references one possible way to use webpack for the foreign (non-goog-closure module) bundling and then how to include it (with lein and cljsbuild). That particular part of the story is https://github.com/pesterhazy/presumably/blob/master/posts/double-bundle.md

mikerod20:03:22

If you are using Reagent (or re-frame) then https://github.com/reagent-project/reagent/blob/master/docs/InteropWithReact.md may also shed some insight

kingcode21:03:14

Thank you @U0LK1552A and @U662GKS3F - I will look into the doulbe-bundle solution. My ultimate intent is to understand how to get to the “metal” of js interop when forced to extend a non-cljsjs, non-goog-closure compliant, 3rd party lib class without having to be a JS ninja. For example, when trying to sell clojurescript in the enterprise, or to a JS crowd.

mikerod21:03:40

@U06BUCH6D work has been going on in cljs itself to have stronger support for NPM based deps. The goal here is to just be able to include them and have them “just work” I believe. However, there are still a lot of tricks there. It isn’t advanced enough to deal with how many NPM modules are structure or something like that.

kingcode21:03:53

Thanks @U0LK1552A. I am surprised that this seemingly basic scenario of declaring a subclass (in JS) of a loaded external JS lib - either via npm module or vanilla JS, could be so arduous…It would be a good idea IMO to have the clojurescript main docs document that stuff, if it is not already (I couldn’t find it in the guides)…thanks.

mikerod21:03:46

Yeah, it is a hassle still. The JS ecosystem of packaging and modules is pretty confusing as it is

mikerod21:03:16

It looks like cljs has a goal to get it to become a smoother process, but it is a long road it looks like

mikerod21:03:47

It probably isn’t thoroughly doc’ed in cljs main docs yet, just because it isn’t part of the core compiler to do something like “double bundle”

mikerod21:03:13

There is also shadow-cljs you can look at. It is a “build tool” that I believe has a goal of smoothing the JS ecosystem integration

kingcode22:03:31

@U0LK1552A Thanks! Will study shadow-cljs carefully, and your explanations…meanwhile I found a cljsjs solution which works for my small use-case, but only after clicking around tediously: cljsjs/create-react-class works, bbbbBBUT…doesn’t show how the “drop-in” replacement is invoked: it turns out the syntax is NOT js/React.createClass, or js/createClass, but actually one has to type js/createReactClass .. Unless one is familiar with cljsjs clj->camel case conversion patterns, that not intuitive.

kingcode22:03:47

latest create-react-class works with React 16.3.0 fortunately..

kingcode22:03:58

I think once understood shadow-cljs should make it possible to cover all use cases for sure.

mikerod22:03:03

I haven’t tried messing with cljsjs/create-react-class, so I wouldn’t have much to add on that without looking at it more.

mikerod22:03:31

Yeah, I havent’ used shadow-cljs as of yet. I think the “double bundle” approach is fine for me currently. I think it depends on your circumstances what is most appropriate really.

kingcode22:03:05

Is it safe to assume that React is not google closure compliant? It seems to be the case.

mikerod22:03:55

It isn’t written as google closure modules at least. However the cljs NPM integration apparently works on React.

mikerod22:03:18

A mix of cljs and google closure are involved in supporting npm packages I think

kingcode01:03:34

cool…thank you.

nenadalm06:03:40

React seems to work with closure compiler based on https://github.com/facebook/react/issues/7551.

danielo51519:03:55

Hello. One question regarding channels, if a function that just makes a get request and returns a channel, it is a good idea to close the channel immediately after the response arrives ?

john19:03:16

I don't think so

john19:03:35

I believe after closing a chan, you can't do any more takes on it. Did you try it?

john19:03:56

Ah, I was incorrect

john19:03:18

In which case, yeah, that's probably a good idea

john19:03:16

If you know you won't need to leave it open.

danielo51519:03:16

Yes, exactly. When you make a get request and you get a response you usually don't want to take anything else from there

danielo51519:03:27

Is this a correct map ?

danielo51519:03:37

(map :name collection)

danielo51519:03:23

I'm getting nil all over the place. I also tried mapv because I'm not sure if it is a list or a vector. It is a converted array. In any case the result is the same, a list of nils

john19:03:56

What are you trying to achieve there? Are you trying to map :name across the collection of maps, pulling out the value of the :name key for each one?

danielo51520:03:08

But seems that js->clj is cheating on me

danielo51520:03:26

Looks like it is converting an array of objects into an array of vectors...

danielo51520:03:36

How can I check the type of something ?

john20:03:54

I'll give you 3 guesses 😉

john20:03:01

(type ...

danielo51520:03:59

It is not very helpful

danielo51520:03:05

#object[Function]

danielo51520:03:11

does not mean anythign to me

john20:03:27

try (js-keys ... to see what's in there

john20:03:52

if it's a js obj

john20:03:27

mmm, before the clj->js

danielo51520:03:53

Actually what I'm doing is js->clj, now I'm getting a better answer

danielo51520:03:54

cljs.core/PersistentHashMap

john20:03:00

Well, calling js-keys on a js object should work...

danielo51520:03:22

Show I'm getting a vector of hashMaps

danielo51520:03:32

So I sholud be able to map over it right ?

danielo51520:03:40

The way I posted

john20:03:44

not with a :name

john20:03:51

you could with an inc

john20:03:57

if it was a vector of numbers

danielo51520:03:05

It is a vector of hashMaps

john20:03:35

ah, do they have :name keys? try mapping keys across to see what all the keys of each map are

danielo51520:03:26

Here is my pipeline: (convert is js->clj with keyworize)

(->> response
                                .-data
                                convert
                                (map keys)
                                println))

danielo51520:03:45

Indeed it contains name keyword:

danielo51520:03:52

((:description :group :system :rancherCompose :name :baseType :transitioningMessage :type :created :state :transitioningProgress :actions :dockerCompose :createdTS :binding :externalId :previousEnvironment :id :kind :outputs :transitioning :answers :environment :uuid :serviceIds :templates :previousExternalId :healthState :startOnCreate :accountId :removed :links)...

danielo51520:03:31

Can it be a problem in how I am constructing the pipeline ?

john20:03:01

Does every map have a :name? If so, and you're still getting nils, you first need to determine whether those vals are in fact nil, and the function is working correctly

danielo51520:03:24

I tried to include a lambda, but the behavior was weird too

danielo51520:03:35

I think the problem is how I'm using the pipeline

john20:03:57

How many maps are in the vector and how many values/nils are returned?

danielo51520:03:58

It is now working :face_with_rolling_eyes:

danielo51520:03:23

(->> response
                                .-data
                                convert
                                (map :name)
                                println))

danielo51520:03:32

Seems exactly the same..

danielo51520:03:19

Well, now to the next challenge

danielo51520:03:38

To find the first that matches certain criteria...

danielo51520:03:35

I was using some before

danielo51520:03:47

But someone suggested me (first (filter....

john20:03:35

some is more idiomatic

danielo51520:03:17

At first it was the obvious choice to me

danielo51520:03:50

But then I realized that the predicate must return the value or you will get just a boolean

danielo51520:03:03

And that is not very idiomatic to me, a predicate should just return true or false

john20:03:44

Well, the choice of some is independent of whether you choose to have your function return a boolean or a logically truthy thing, right? You'd just need to define a function to pass its argument through, if some condition about it is true, right?

danielo51520:03:17

Yes, exactly

dabrazhe20:03:42

hi. does anyone know a good boilerplate code/starter for Electron and clojurescript integration?

danielo51520:03:48

I think shadow-cljs has one on their main page

danielo51520:03:37

Can somebody tell me why I have to make a take at the end of this function ? Knowing that Get returns a channel... Why I can't just allow that to passthrough ? This works:

(defn getStacks [baseUrl envName] 
  (let [url (str baseUrl "/v2-beta", "/projects?name=" envName)]
    (go (some-> (<! (Get url))
          .-data   
          jFirst
          .-links
          .-stacks
          Get
          (<!)))))
But this does not
(defn getStacks [baseUrl envName]
(let [url (str baseUrl "/v2-beta", "/projects?name=" envName)]
  (go (some-> (<! (Get url))
    .-data
    jFirst
    .-links
    .-stacks
    Get))))

thheller20:03:04

@rdanielo go returns a channel that then returns a channel. so without the take your consumer would need to take twice

dabrazhe20:03:41

Thanks. I found this one, but it does not seem to work, i am not even getting the first page, just a menu https://github.com/YurySolovyov/eion

danielo51520:03:28

@thheller you are right. So the go block always returns a channel, right ?

danielo51520:03:53

Would it be the same to make (<! Get) right ?

danielo51520:03:16

But where is that take being injected ? Looks like magic to me

thheller20:03:23

go always returns a channel that will only ever receive one value. which is the final result of the go

thheller20:03:35

that value will be your Get result

thheller20:03:59

there is no take being injected?

danielo51521:03:21

Ok, more clear now

dnolen22:03:03

transit-clj & transit-cljs now support writing metadata, it’s pretty interesting

👍 16
mikerod22:03:27

Oh, that is interesting indeed

mikerod22:03:38

I didn’t even know that idea was on the table

dnolen22:03:00

other languages will have to sort out where to put it or throw it away - but for Clojure(Script) it’s pretty cool

mikerod22:03:19

yeah, it could be useful

mikerod22:03:57

At on point in the past, I was using Fressian for clj to clj serialization and I implemented a bunch of handlers and included metadata in that impl

mikerod22:03:56

Because it was desirable to have it over the wire. I was really just distributing data to more processes to do work on it. Made sense in that case.

danielo51522:03:06

Cool! I don't need any metadata right now, but it is good to know

justinlee22:03:43

has anybody ever tried or given thought to doing DCE in clojurescript itself? i realize there’s a better solution with closure, but I was just curious if there was anything about it

dnolen22:03:36

Not that I know

darwin22:03:31

This would be pretty difficult thing to do. You can have some javascript code compiled along with your clojurescript code. That thing would have to understand both cljs and js to be usable in such scenarios 🙂

justinlee23:03:27

yea i’m sure it’d be very difficult. i was kind of just musing about something along the lines of a first pass. like something that bails when it’s in trouble but might do really well because it understands clojurescript better than clojure understands the compiler output. probably a stupid idea. as i say, just curiosity

justinlee23:03:20

i just came across the clojure typed project and it made me think that the idea of doing static analysis on clojurescript seemed plausible and interesting given that the code is basically already handed to you as an AST

darwin23:03:40

@lee.justin.m ferret does some simple treeshaking and other optimizations, doesn’t look like awful lot of code when you operate on clojure-like-ast: https://ferret-lang.org/#outline-container-sec-3

darwin23:03:18

IMO interesting (more serious) area of exploration would be to take clojurescript compiler and instead of javascript emit untyped ocaml Parsetree and then apply their pipeline with BuckleScript, see here: https://github.com/facebook/reason/blob/master/src/README.md#repo-walkthrough

darwin23:03:48

but optimizations wouldn’t be the main benefit IMO, I believe this way we could eventually get something like “optionally typed clojure”, plus compilation to native (via ocamlc)

justinlee23:03:25

wow that’s a gnarly idea

justinlee23:03:42

omg ferret is written in a literate style. that’s amazing and crazy.

😮 4
richiardiandrea23:03:30

Yeah that's super cool