Fork me on GitHub
#beginners
<
2018-04-16
>
fmn07:04:55

Reading about transducer, it seems it's a powerful way to write composition of map and its siblings. And it's also better in terms of performance compared with the lazy-way ->>. So when do you NOT want to use transducer, other than when dealing with infinite sequence?

sundarj14:04:28

transducers can also be used with infinite sequences:

=> (transduce (comp (filter odd?) (take 10)) conj (range))
[1 3 5 7 9 11 13 15 17 19]

sundarj14:04:06

the only reason to use the normal sequence functions over their transducer variants is convenience

sundarj14:04:05

the performance difference often doesn't matter

sarna07:04:39

hi guys, I'm puzzled by defonce - why isn't it thread safe? - is there a thread safe equivalent of it?

noisesmith12:04:00

agreed with this quote from that log: "defonce at runtime shouldn't happen"

sarna13:04:20

thanks 👍

gcast09:04:09

@funyako.funyao156 In my experience a transducer may not be the best option if the sequences you are processing over are small (flat, ~6 items or less). based on some naive but simple benchmarking of into {} (remove (comp nil? second) {:a 1 :b b :c cl}` and merge {:a 1} (when b {:b b}) (when c {:c c})

gcast09:04:27

at which point the overhead of the transduce dominates the runtime

gcast09:04:03

also nothing special at 6 items, just an arbirary size at which point I started to notice the runtimes tending to favor transduce

cristibalan09:04:27

Hi. I have a situation where I need to pass an arg (a path) to a function about 15 levels down the call chain. For aesthetic reasons I don't want to add an extra arg to all fns down. Is there a known pattern I could use for this? I'm currently considering using an atom, with-redefs or alter-var-root, but they seem kinda heavy handed.

cristibalan10:04:55

Ended up using (def path ^:dynamic nil) and (binding [path "blah"] ...) in the top level fn. Seems like a lighter approach compared to the others.

andre.stylianos10:04:17

This could be somewhat fragile as now the function depends on the context it's run in, not only its input. Also the caller needs to know that you need to bind that variable and that is not explicit.

noisesmith12:04:22

putting def inside a function is a problem also

Chris Bidler13:04:18

Does path have a sensible default value? FWIW Zach Tellman’s Elements of Clojure treats this subject explicitly and the key difference between what he suggests and what you’ve done here is to take in the value of path as a param to the top-level fn and use that param in the binding call

Chris Bidler13:04:07

In this way, you’re using a bound var where you want it, but the value of that bound var is still expressed in terms of input, rather than being a magic number somewhere in your code. You can still test the fn 15 calls down by wrapping your tests in (binding [*path* "/path/to/test/data"] ...)

cristibalan15:04:25

Thanks for the replies and sorry if I wasn't clear enough. The def path is top level, the lower level fn is using this def, and the binding is being set in the main fn from an arg that it receives from the external caller. I think this is what @U07HA15PY recommends as well.

4
cristibalan15:04:42

@U485ZRA58 Thanks for the warning. I'm ok with the function being dependent on the context for now, since it's already an internal fn quite deep inside the ns. Nobody should be using it standalone. If that happens, I could update it to be able to receive the path as argument.

✌️ 4
Denis G13:04:20

Does anybody know what happened to LightTable? Is anybody using it?

sarna13:04:27

it's pretty dead, the author is now working on another thing - http://witheve.com/

sarna13:04:58

which is also pretty dead at this point https://github.com/witheve/Eve > This repository hosts a preview of Eve v0.3 alpha, which is no longer under active development.

Denis G13:04:24

sad. So nobody is interested in contributing to lighttable

Denis G13:04:39

the idea behind it sounds pretty cool

joelsanchez13:04:40

it's so dead it has become the standard reference for dead applications, now you can say "my side project lighttabled"

Denis G13:04:51

😄 😄 😄

sarna13:04:58

just use cider tbh, it's excellent

Denis G13:04:03

focus on functions and code editing itself sounded pretty comfortable

Denis G13:04:30

@U9QTVPNHX cider with emacs?

sarna13:04:53

yep, I'm using spacemacs. no prior lisp/emacs experience

steveh201814:04:50

Proto REPL plugin for http://atom.io is easy to setup too

sarna14:04:31

it is, but in my experience it's really slow and buggy

steveh201814:04:48

In spacemacs, using evil mode (vi compatilbility), I find I'm having to create an extra space at the end of a sexp just to evaluate it with ", e e". Is there a way without having to append that extra space (cummulatively, it's a big time waster)

sarna14:04:11

@UA2UNSUGZ it's at the end of the line, right? move to the beginning of the next line :)

delaguardo14:04:50

@UA2UNSUGZ Add this line into your config file - (setq evil-move-cursor-back nil)

delaguardo14:04:26

inside of spacemacs/user-config

steveh201814:04:42

Thanks guys! To the OP, might want to keep an eye on the progress of Visual Studio Code clojure plugins too.

delaguardo14:04:34

Sad to say, but none of them are even close to cider + emacs level

☝️ 8
Denis G19:04:46

Thanks! 🙂

Kari Marttila15:04:27

I'm having difficulties to figure out how to send JSON Web Token as part of a GET method using cljs-ajax. Something like: (ajax-core/GET url { :format :json :response-format :json :headers { "Accept" "application/json" "Content-Type" "application/json" "Authorization" base64-decoded-token } :handler -handler :error-handler -error-handler } ) For some reason if I add the "Authorization" header it messes the CORS in the backend side. Is there some way to print the actual request ajax-core is sending (like using curl -v (verbose))?

ghadi15:04:13

are you in a browser @kari.marttila?

ghadi15:04:10

if so you can use the network inspector

Kari Marttila15:04:52

Yes. And the Rubber Duck effect seems to be working since I guess I already figured out the problem right after writing the previous post. 🙂 I had to add the "Authorization" header to the allowed headers in my cors handler. Damn. 🙂

Kari Marttila15:04:39

I should buy a real rubber duck, put it on my table and explain the problem to it before I post my questions in this forum. 🙂

joelsanchez15:04:29

open this slack, tick the "Offline" checkbox in devtools, and just write your message as usual

Kari Marttila15:04:02

Thanks for that hint. I'm now examining the http requests in Chrome developer tools / Network tab. I'm an old backend developer and trying to learn some frontend skills using ClojureScript.

joelsanchez15:04:36

it was partially joking, but I'm glad it was a useful hint 🙂

Kari Marttila15:04:15

It was a good hint. I was watching the Console tab in browser and as an old backend developer I was thinking the obvious solution: log the http request in code somehow. I didn't realize that there it was all the time in Developer tools / Network tab. 🙂

joelsanchez15:04:11

it's an amazing tool. you can filter and replay requests. also works for websockets

Kari Marttila15:04:27

Ok. Thanks for sharing that info. I need to check it out in more detail once I have more time.

Sallide18:04:32

How worthwhile is learning typed clojure as a beginner? Will I notice a lot of benefits using it early on or am I better off using regular clojure first?

ghadi18:04:04

learn regular clojure, add spec to your arsenal, then re-evaluate (my 2 cents)

Sallide18:04:25

From what I've read, spec provides runtime checking only though, is that correct?

ghadi18:04:27

rather than splitting the timeline between compile <---> runtime, spec allows you to split it in a different way: development time <--> production time

ghadi18:04:43

spec helps you work out the kinks as you develop

mfikes18:04:08

There is also an effort to do static checking https://github.com/arohner/spectrum

ghadi18:04:45

I just wouldn't dwell on or emphasize the static aspects too much...

ghadi18:04:07

https://www.youtube.com/watch?v=VNTQ-M_uSo8 @stuarthalloway has a great presentation where he hits on the dynamic vs. static stuff in the first <15 min

mfikes18:04:10

Oh. Well, I’d love it if it were built into Cursive.

Sallide18:04:16

Great, thank you both

andy.fingerhut02:04:47

FYI, if you suspect a cyclic dependency is a problem in the future, starting a Clojure/Java REPL and doing (require '[http://some.name.space]) will fail with a list of all namespaces found in a cyclic dependency chain, as long as one is found by require'ing http://some.name.space and all namespaces that it use's or require's, transitively.

andy.fingerhut02:04:19

Eastwood can also detect cyclic dependencies, but it seems will only tell you 2 of the namespaces in the cycle (even if the cycle has more than 2 namespaces in it). Still helps narrow it down.