#clojure log - Jan 06 2016

The Joy of Clojure
Main Clojure site
Google Group
IRC
List of all logged dates

0:15 sdegutis: Do any of yall use components for /everything/ in your system?

2:59 BRODUS: anyone ever use the functions in cider-client.el? trying to understand why 'cider-nrepl-request:eval' only contains a session id in the callback...

3:21 owlbird: which web server has a better performance, I tried ring-jetty-adapter, but it was worse than Tomcat/Java.

3:42 kungi: owlbird: there is a clojure web server benchmark here: https://github.com/ptaoussanis/clojure-web-server-benchmarks

3:49 qsys: about transitioning from Java to Clojure: most, if not all, books and tutorials about Clojure spent a great deal about data structures, immutability, ... rather early. Java interop, classes, reification and such all come later. That scares Java devs quite often. So well, just an idea, wouldn't it be useful to have a book/tutorial/manual that starts with making classes etc in Clojure, and building up to data structures later?

3:50 Start from 'do it the Java-way in Clojure' and simplify it by introducing clojure concepts step by step?

3:50 TEttinger: qsys, good in principle, but bad for making good clojure code

3:51 you can use amap in place of map when using arrays instead of vectors, but... it will be uglier

3:51 clojure the clojure way tends to be vastly shorter than clojure the java way or java the java way

3:51 qsys: Yeah, it's true it's not good clojure code, but it's about learning.

3:52 TEttinger: but... learning bad ways is not good

3:52 qsys: allright... better than not learning at all?

3:53 owlbird: For my experience (a Java programmer) to learn Clojure, should get used to write little method, combining them with 'apply/map/reduce/filter...'

3:53 qsys: right - bad Java code is kind a commonplace (and accepted)

3:54 the thing is: if it's very different from what people know, most of them don't have the courage to continue the 'learning process'

3:54 TEttinger: I'd rather have java people program in java using clojure-like libs. https://github.com/rschmitt/dynamic-object and https://github.com/rschmitt/collider for example

3:55 qsys: Starting from what people know might help some people out

3:55 BRODUS: the clojure way kind of expects you to keep the java interop to a minimum.

3:55 TEttinger: those two libs might be a good starting point to introduce clojure syntax etc

3:56 owlbird: But Clojure is a little slower than java, and the tech leader has no reason to choose a worse performance language

3:57 TEttinger: it depends, it can be drastically faster to write

3:57 qsys: so, rather than starting 'java code in clojure', starting coding like clojure in java :p. Might be fun :)

3:58 BRODUS: i may be wrong but I think scala kind of expects you to use both scala and java

3:58 mpenet: owlbird: by that logic we'd all be doing assembly

3:58 qsys: well, little slower, don't know about that... might be, sometimes. I don't worry about that: bad java code might be much slower/less stable than good clojure code

3:58 owlbird: I saw a lot of performance comparison, if a Java programmer want a better language, why don't choose Scala or Nginx/luajit

3:58 TEttinger: because nginx isn't a language

3:58 owlbird: which is more practical

3:58 mpenet: owlbird: if it makes his team 10x more productive for 5% perfs hit (random value) he'd jump ship

3:59 owlbird: Nginx is not, bug openresty does

3:59 but

3:59 qsys: I only know: I don't have the instability/performance problems many of my collegues have

4:00 I use clojure code (although I shouldn't, 'cause it's not allowed, since it's not Java, but so far, I could defend myself by saying I'm using 'Java technology', since it runs on the JVM)

4:01 Some wanted to learn clojure, but the moment I start talking about data structures, immutability, etc, most of them just see the point anymore - it's just too far from what they know to be 'true'

4:03 so I was planning to make a kind of crash course, but well, I can't jump in clojure like that... it should be 'from what they know up to clojure'

4:04 noncom|2: BRODUS: no, scala does not actually... it can replace java

4:04 qsys: scala can replace Java, like Ceylon, or like Kotlin (which even has a 'java to kotlin converter' built-in)

4:04 algernon: qsys: I'd like to disagree. I held a two-day clojure crash course for C# developers last year, and started with data structures, clojure benefits, etc. So not with what they already knew and were familiar with. First day we did stuff the Clojure way only. Second day, we had some idiomatic C# -> idiomatic Clojure exercises.

4:05 qsys: it was a huge success, despite half of the team being very scpetic about clojure, lisp and the JVM up front.

4:06 qsys: allright... maybe it works in a crash course. I only know it doesn't work when I just have to explain 'on-the-fly'. So, well, I probably just have to try :p

4:06 algernon: qsys: if your developers are open to new ideas, starting at idiomatic clojure works suprisingly well. if they're not, well, it won't work either way :P

4:06 qsys: yeah, on the fly explanation is hard. never managed to sell clojure that way, either

4:07 qsys: well... there's a condition there :p. It's not only the devs - let's say about half of them is open to new ideas - but it's even more about tech leads, architects and well, managers, that are extremely afraid of 'new ideas'

4:08 mpenet: from my exp. they need to dig into a new project 100% in clojure, and build from there, trying to mix things up at the beginning is hard.

4:08 powered: java developers don't see the point of immutability?

4:09 qsys: Anyway, just giving it a try and jump right into clojure in a crash course might work. I'm curious how this will be...

4:09 mpenet: I mentored a team in a large company doing critical stuff (satellite related), they were producing quite good code after a dozen days or so, and were *very* impressed with the language.

4:09 algernon: perhaps I'm lucky, but I never found that to be a problem. showing big names recruiting clojure programmers convinced all managers I had to deal with. tech leads listened to reason, and to devs saying "we want to go with these stuff"

4:09 qsys: powered: well, some do, some don't, some others don't really know what you talk about. That's the bad thing these days: they learn 'frameworks', not coding, or paradigms, or ...

4:10 algernon: (that = tech leads, architects, managers)

4:10 noncom|2: powered: it's not about immutability.. there comes the whole "another language" thing with "oh my it's lisp" thing

4:11 and most programmers that i worked with were so brainwashed by oop that immutability was an almost unexisting concept for them

4:11 coz objects have state, you know..

4:11 qsys: true...

4:11 powered: the string type is immutable in java, so they should at least be familiar with the concept

4:11 qsys: noncom|2: that's the thing: they call Java oop, no mather how non-oop they are doing :p

4:12 noncom|2: oh yeah :) and when trying to solve oop shortcommings, they just apply more oop

4:12 mpenet: functional programming/immutability isn't hard really. You just manage state differently but it's way easier to learn that how to do OOP in a not awful way

4:12 base concepts are very simple

4:12 powered: it's all about applying them in the right way

4:13 qsys: mpenet: true, not difficult, but it is for people that are brainwashed. They only know 1 paradigm... and that is the only true one, for them.

4:13 noncom|2: mpenet: it is, scientifically, but real world programmers are not always about science..

4:15 mpenet: I am not sure, yes, it's different and requires to let some experience behind, but knowing oop doesn't make it much harder really. Programming is about knowing algos/ds and so on, not much about how to code in [insert language].

4:16 noncom|2: theoretically yes. in practice it comes down to neuroplasticity, bias, age, self, and other biological factors

4:16 mpenet: some people are a bit frustrated at the beginning because they're used to do it another way, but (from my exp), they get over it quickly

4:17 noncom|2: well those are lucky who are open-minded :)

4:18 qsys: lucky, and well, sometimes unlucky ;)

4:21 abunuwas: ~@i-blis

4:21 clojurebot: Huh?

4:23 qsys: mpenet: to me, programming is about knowing as much paradigms as possible. The more you know, the better you can solve problems, the cleaner you right code... I personally don't care about language, or features.

4:25 anyway, I take it as a challenge to jump right into clojure for a clojure crash course :p

4:28 owlbird: programming is about earning money, which depends on business mostly, and a couple of languages, Java is more easy to learn and to hire a newbee ;)

4:28 It's not fancy, but it works well

4:30 noncom|2: yeah, to me commercial programming is often like coal mining

4:32 qsys: lol

4:32 BRODUS: noncom|2: you should say that to a coal miner

4:34 qsys: owlbird: I don't consider 'good' Java easy to learn, and even harder to learn to good clojure... probably because of all the Java-junk on the web, in books etc. But true, it's easy to hire a brainless Java-code-monkey, who lets his ide vomit code that's very susceptible to bad performance and instability :).

4:38 owlbird: qsys: There were too many java courses and frameworks, Spring / Play, even a people who don't know much about programming can do the works by watching samples. Yes, the performance is awful some times, but business is changing too fast.

4:40 mpenet: people were saying the same about c/c++ when java came out :)

4:40 owlbird: Sometimes, I think nginx, luajit is more suitable to build a prototype, which is also fast to develop and run. by building code into a yum package, it's also to maintain different versions.

4:41 qsys: yes, and that's the problem: when someting changes, it takes 'ages' to adopt. Real-life example: A few years ago, I got a request from another team to change something in their code. It was a translation into french, 1 sentence had to change somewhere in a properties file. The programmer that had to do that, estimated that it would take 1 day to do that.

4:41 mpenet: (or asp/php/perl for web thingies)

4:43 qsys: It took me about 1 hour to import the project, 25 seconds to change the sentence, 30 minutes to take out a few errors in the code and 25 minutes to rebuild the project :p - and it took another 3 weeks before it was released, due to the 'release cycle'. That's, sadly, the way things are programmed very often...

4:43 and that's the only truth for many.

4:45 ... but that's not about clojure, and since this is channel #clojure and not #whining, I'd better stop whining about it :p.

4:46 powered: 25 minutes to rebuild because it's so much code, or because people push code with compiler errors in it?

4:47 qsys: more about too much code: too much useless code, no errors, loads of warnings etc.

4:48 owlbird: I have seen enough stupid codes from another team, and the programmers are struggling everyday.... but their business is growing 300% every year, how can you blame them " What a stupid code"? TAT

4:51 qsys: owlbird: I agree with you... if they grow 300%/year, it's fine with me. I don't blame them (although I wouldn't be satisfied if the code is instable and not performant, but that's personnal). However, if they grow 300%, they might be able to grow 400%/year if the code would be less messy?

4:52 mpenet: It's all theorical bs really, I have seen "capable" outsourced teams of java devs kill a well funded project over time.

4:53 it's very dependant on the context and many other factors

4:56 Growing toxic code is never good. Can win you some time at the beginning but you almost always end up paying a high price

4:59 schmir: dammit. I've got 400k lines of toxic RosiSQL code that should be reimplemented. my life sucks.

5:03 qsys: schmir: ;)

6:25 ridcully_: schmir: that's a whole lotta rosi

6:41 t0by: ridcully_ wins one internets

6:43 schmir: ridcully_: yes, but at least I'm using clojure for the new implementation

8:22 juanjo: yesterday i was able to compile clojure, thanks!

8:22 how can i run the compiled version of it instead the system installed one?

8:24 java -cp clojure-${VERSION}.jar clojure.main

8:24 sorry, it was in the readme :/

9:20 * juanjo is trying to get int clojure-dev list

9:26 jsabeaudry: Can this be written better https://www.refheap.com/113414 ?

9:34 vijaykiran: jsabeaudry: what does sub return ?

9:37 jsabeaudry: vijaykiran, my guess would be the publication, let me check

9:39 vijaykiran, I was wrong, it returns the channel that was just subscribed

10:10 sdegutis_: Hallo.

10:18 hiron: I'm having issues using with clojure.tools.namespace.repl/refresh. If I add a defn to my core.clj file and call refresh in my cider-repl, the new function is not available at the previously required namespace. Any thoughts?

10:21 sdegutis_: justin_smith: how heavily are you using component?

10:23 favetelinguis: i have Java 8, latest stable clojure and leningen installed on my arch linux system but when im trying to use incanter charts only empty windows open up, what library do i need to install to get the plots working with incanter?

10:24 ridcully_: that _could_ be a problem with your window manager

10:26 favetelinguis: i use xmonad

10:27 ridcully_: have a websearch about "non reparenting wm java swing" - if this brings nothing up, i can put my script up on refheap

10:27 sdegutis_: Lately I want to use i3, but that's probably because I'm just so dang tired of the plain-jane OS X UI...

10:28 ridcully_: it basically to lie about the familiy of window manager you are using to make java render anything

10:29 Bronsa: ridcully_: FYI refheap is shutting down

10:29 might be read-only already

10:29 ridcully_: yeah, heard about it here. thanks for the info

10:29 sdegutis_: Bronsa: why?

10:29 Bronsa: I thought it was really cool

10:31 Bronsa: sdegutis_: people started uploading stolen credit card infos or something like that and Raynes doesn't have the time to deal with that IIRC

10:31 sdegutis_: ahh yeah that'll do it

10:48 favetelinguis: ridcully_: seems to be a known issue with xmonad, thanks for the pointer

10:51 ridcully_: favetelinguis: no only with xmonad. you found the workarounds?

10:53 favetelinguis: might, http://stackoverflow.com/questions/30742662/java-swing-gui-not-displaying-in-xmonad

10:53 engblom: ridcully_: Try 'export SAL_USE_VCLPLUGIN=gen' before using your JVM apps

10:54 ridcully_: Since adding that to my configuration I have never had any problem with xmonad

10:55 ridcully_: engblom: i dont run xmonad - i use some script where the source is maybe burried in my git log. most likely wmname

11:28 TimMc: Bronsa: I talked with him and he said that it's not being taken down, just made read-only, which is great.

11:28 jsabeaudry: So if I understand correctly I can never put nil on a channel because consumer will think the channel is closed?

11:29 Bronsa: TimMc: ah, good

11:35 ridcully_: jsabeaudry: yes. documented e.g. here https://clojure.github.io/core.async/#clojure.core.async/put!

11:39 jsabeaudry: ridcully_, ah, yes indeed! thanks!

11:53 domgetter: what's the reverse of mapcat? What will take a sequence and turn it into a sequence of subsequences?

11:53 justin_smith: domgetter: partition? partition-all? split-with?

11:53 domgetter: I'm trying to take a list of words and shove them into subsequences that represent rows of words when displayed

11:54 I'll look into those three, thank you :)

11:55 are any of those stateful with respect to the currect accumulating subsequence?

11:55 justin_smith: no

11:56 you can use reduce or loop for that though

11:56 domgetter: okay I'll just build my own then, thank you

12:10 justin_smith: thanks for the advice. I got it up and running: https://gist.github.com/domgetter/2939fd3f5c45fd082a25

12:11 justin_smith: domgetter: cool - it might be easier / more efficient if instead of repeatedly pop/conj acc if it's not full, you have a two collection accumulator

12:11 (defn rows [[full pending] word] ...)

12:12 so instead of of pop at each step, you can just conj to pending / or conj to full and pass [] as pending

12:12 domgetter: okay I think I understand. I'll go ruminate on it and see if I can come up with a result

12:13 justin_smith: domgetter: also, you use (last acc) and (pop acc) - if it's a vector always use pop, last is O(n), peek is much faster

12:13 err, always use peek too, that is

12:13 ,(peek [1 2 3])

12:13 clojurebot: 3

12:14 domgetter: ah okay. got it. obligatory "why don't they just make last efficient for vectors?" :P

12:15 justin_smith: domgetter: yeah, last uses the seq interface rather than having it's own interface

12:15 it would need its own interface for that to work

12:17 domgetter: Hmm, for the destructuring to work, "full" would have to be all the rows up to the last one, and pending would always be the last one. Is there a way to do a rest parameter that would work like butlast ?

12:17 justin_smith: domgetter: nope, that's why I suggested splitting it in two parts like that

12:17 domgetter: oh you mean maintaining it in that structure til the end manually?

12:18 or did you mean have "pending" be its own vector just chilling until I shove it into full?

12:18 that makes a lot more sense

12:20 justin_smith: (defn rows [[full pending] word] (if (> (apply + (count word) (map count pending)) 35) [(conj full pending) [word]] [full (conj pending word)]))

12:21 domgetter: right, maintaining that structure for every step - which means you need to do a conj at the end after reduce is done, or (apply conj (reduce ...))

12:21 domgetter: awesome, thanks for the insight :)

12:21 justin_smith: domgetter: also see how I was able to combine your two sums into one apply +

12:21 sdegutis_: What's the benefit of using type hints? What's the downside of not using them? When should they be used?

12:22 domgetter: yea I saw that, that makes more sense. I was being a lot more procedural

12:22 justin_smith: sdegutis_: 100x perf difference when they are needed is not unheard of

12:22 sdegutis_: I've mostly been putting them in places to satisfy `lein check` but it feels a bit random and ad-hoc.

12:22 justin_smith: wow...

12:22 justin_smith: sdegutis_: clojure knows when compiling whether it's outputting expensive runtime reflection ops

12:23 sdegutis_: that's why lein check can warn you - it's a hook that tells you when that happens

12:23 sdegutis_: and the reflection is very expensive

12:24 sdegutis_: I've even seen differences more like 1000x (in cases that involve not only reflection but also numeric boxing...)

12:26 domgetter: justin_smith: the only "downside" is that I have to do a final conjoin after the reduce since I have a trailing pending vector

12:26 justin_smith: domgetter: right, like I said, (apply conj (reduce ...))

12:26 domgetter: oh, you were one step ahead

12:27 justin_smith: domgetter: I've done this before :)

12:30 sdegutis_: justin_smith: oh wow, then I'll definitely look for hot code paths in `lein check` and fix those

12:31 domgetter: justin_smith: much better! https://gist.github.com/domgetter/2939fd3f5c45fd082a25

12:31 justin_smith: sdegutis_: best value is probably a combination of lein check to see where the reflection is happening, and a profiler so you know what the hot path is

12:31 sdegutis_: justin_smith: hmm interesting concept

12:32 Bronsa: setting *unchecked-math* to :warn-on-boxed is also really useful

12:32 justin_smith: definitely

12:33 sdegutis_: Nice, only 33 reflection warnings. And none of them in hot code paths.

12:33 Bronsa: whoa, definitely gonna set that one

12:33 Bronsa: although it doesn't catch all the boxing cases

12:34 justin_smith: Bronsa: is there a good guide to finding numeric boxing that *unchecked-math* :warn-on-boxed would not catch?

12:34 Bronsa: justin_smith: http://dev.clojure.org/jira/browse/CLJ-1585 this is the only case I'm aware of

12:35 I really dislike how clojure does automatic boxing/unboxing, I wish it didn't

12:35 I'd rather use (Integer. x) and (int x)

12:36 also sometimes type hints work for unboxing, sometimes they don't. I think they should never and the only way to unbox should be using the casting functions

12:36 but it's probably way too late to even propose such a change

12:39 sdegutis_: It's never too late!

12:40 justin_smith: sdegutis_: clojure values back-compatibility, having to use (Integer. x) / (int x) explicitly would break so much code...

12:44 Bronsa: yeah like, 80% of code that uses interop

12:45 justin_smith: but oxlang could totally go that route

12:46 sdegutis_: oxlang!?

12:47 arrdem: that looks fricken cool

12:47 arrdem: do you use it in production yet?

13:04 Why does clojure.data.csv take a writer rather than just returning a string? Or at least why doesn't it have a variant that just returns a string?

13:05 justin_smith: sdegutis_: returning a writer rather than a string is one of those marks of distinction that differentiates a gentleman api dev from the hoi paloi

13:06 sdegutis_: j/k I have no idea honestly

13:06 sdegutis_: :D

13:07 justin_smith: sdegutis_: (java.io.StringWriter.) is simple enough to make at least, maybe they don't want to force the intermediate string form for csv's that are bigger than RAM

13:07 sdegutis_: actually, now that I think about it, it must be that case: a writer can handle a csv bigger than RAM, generating a string breaks well before RAM is even full

13:07 there's a max string size

13:08 sdegutis_: Sure, but now I have a 3 line function in my codebase in its own util namespace whereas I could delete it if this lib came with the 3 line function itself.

13:12 justin_smith: sdegutis: something like (let [s (java.io.StringWriter.)] (read-csv file s) (str s)) ?

13:12 sdegutis: yeah that's what I have

13:13 well, close: (defn csv-to-string [csv & opts] (let [out (java.io.StringWriter.)] (apply write-csv out csv opts) (str out)))

13:13 the apply is cuz it takes pseudo-mappified opts

14:22 catern: how would I get an atomic set datastructure?

14:22 just put it in an atom?

14:22 mikerod: catern: (atom #{})

14:22 I guess I don't know what you mean actually

14:23 #{} is thread safe

14:23 every modification just returns a new one, you don't affect the original

14:23 if you want one though that multiple things refer to, then yes (atom {})

14:23 (atom #{})

14:24 with atomic update

14:24 catern: hmm

14:25 what i really want is, I have some threads handling incoming data, and they check if a tag in the data is in a seen-set, and if it isn't in the seen-set they add it and start a new thread to start doing a thing

14:25 is there a better way to do that than an atomic set?

14:26 an (atom #{})

14:28 justin_smith: catern: note that if you want only one thread to take the action, you can't just deref and swap as separate actions

14:29 mikerod: justin_smith: yes, I was thinking of that

14:29 but if you are just conjoining some value to a set

14:29 justin_smith: catern: and swap! retries, which means you probably don't want to put the launch of that action into the swapping function

14:29 mikerod: and you aren't concerned about it being conjoined more than once

14:29 justin_smith: mikerod: sure

14:30 catern: how big a problem is it if accidentally more than one thread gets started?

14:30 mikerod: if you want to be able to see the set and conj to it atomically, you'd use some transaction based construcdt I guess

14:30 justin_smith: mikerod: or use something like an agent that synchronizes on its value (but runs async)

14:30 and thus does not swap

14:30 s/swap/retry

14:31 mikerod: sure, I really don't have a ton of real-world experience with these things - so I'm learning at this point on what is best for these situations

14:32 I think the the (atom #{}) solution is nice if you aren't concerned with retries and don't mind if you are conj'ing a value that was already conj'ed there after you derefed it

14:32 catern: justin_smith: well, what will actually happen if it's not in the seen-set is a websocket will be opened corresponding to that tag, and then the data that comes in on that websocket will be put in a datastructure somewhere

14:32 justin_smith: so I don't want to open that websocket twice or create that datastructure twice

14:33 justin_smith: catern: right

14:33 mikerod: now I think the (atom #{}) way isn't good then

14:33 justin_smith: catern: since agents don't retry, it might make sense to use an agent and send-off, then await the agent and see if you need to start your thread or not

14:34 or spawn the thread from inside the send-off actually (that would be best I think)

14:34 mikerod: it is weird to me you'd need to do something async for this

14:34 not to say I know the best/better way

14:35 neoncontrails: I just realized, I still haven't contributed to an open source project yet. (Other than my own.)

14:35 Is there a bulletin board somewhere of Clojure projects seeking volunteers?

14:35 catern: i have too much incoming data to do it synchronously

14:35 neoncontrails: Or is Git my best bet?

14:35 catern: the "threads handling incoming data and opening websockets" are actually polling an API, and each request is too slow for me to wait for it to complete before sending the next request

14:36 justin_smith: mikerod: it has to do with the semantics for atoms vs. agents - agent operations are async, atom operations are synchronous - I don't have a good summary for the reasons handy atm but there are good reasons

14:36 mikerod: justin_smith: I know that part

14:36 justin_smith: oh, OK

14:37 mikerod: I just thought there was something synchronous that allowed you to view a value + do something based on it + update it in one lock

14:37 if that makes sense

14:37 catern: (oh, when you said do something async you were talking about the agent way rather than the atom way. nvm)

14:37 mikerod: catern: yes, sorry

14:37 justin_smith: mikerod: not without retries

14:38 mikerod: justin_smith: yeah, I meant to mention that one

14:38 "do something side-effecty"

14:38 justin_smith: yeah

14:38 BRODUS: neoncontrails: i normally contribute to stuff organically. I end up using open source libraries or read open-source code while doing my projects and when I find something I can fix I do it.

14:40 neoncontrails: BRODUS: Hmm. There must be some resource besides git though, no? Or a way to browse git for repos actively seeking contributors?

14:41 BRODUS: neoncontrails: there was a link on HN recently you might like, i'll try and find it

14:42 neoncontrails: BRODUS: I do love HN. Thanks

14:42 catern: justin_smith: i'm worried about the send-off being delayed, though

14:42 i want to create the websocket ASAP because data is being dropped on the floor as long as I don't have it open

14:42 justin_smith: neoncontrails: lein has issues that are marked as specifically good for newcomers to work on, and is very open to contributions

14:42 catern: (this is for a programming game)

14:43 BRODUS: neoncontrails: ah it was this http://up-for-grabs.net/#/ , no clojure projects though

14:43 justin_smith: catern: it will be delayed if another send-off is still running

14:43 neoncontrails: justin_smith: oh, wow. lein itself, eh? I'll look into it

14:43 catern: justin_smith: i mean, those are implementation details though

14:43 it's not necessarily that I want to do it synchronously

14:43 i just want to do it fast

14:44 justin_smith: neoncontrails: there's also crossclj.info that lets you see which projects are most visible/used by other projects, which has links to source etc. might be helpful for finding where to jump in

14:44 catern: scheduled immediately

14:44 (in practice I'm sure it's fine for my application to just let it be scheduled "whenever" since "whenever" is probably very soon, but...)

14:44 justin_smith: catern: sure, then if your other send-off actions are things that return quickly it will be fine. All it does is check a key, conditionally conj and start a thread, right?

14:45 neoncontrails: BRODUS: still a nice list, thanks for sharing

14:45 justin_smith: catern: other than indeterminacy that would be the same as that effecting any new thread already, the only issue is other send-off events, and you have 100% control of how quickly those return

14:45 neoncontrails: justin_smith: also a great suggestion. Thanks for the help

14:46 justin_smith: catern: in fact you should only have one kind of send-off event, run as often as needed: check for key, if not present spawn thread and conj

14:46 if that sequence of actions is a bottleneck of any sort, you are writing some amazing high performance code I tell you hwat

14:47 catern: heh

14:47 well, creating/opening the websocket might take a bit of time...

14:47 justin_smith: catern: right, do that in a new thread

14:47 not in the agent

14:48 catern: btw

14:48 what should I use to make async HTTP requests in Clojure? and async websockets?

14:48 justin_smith: catern: I use http-kit, and the sente lib which maps websockets to core.async

14:49 catern: just clientside btw

14:49 justin_smith: I haven't tried http-kit for client-side websockets though

14:49 but iirc that exists, if not aleph can do it

14:52 catern: aleph? why not use sente?

14:52 justin_smith: catern: sente uses aleph or http-kit

14:53 aleph and http-kit do the websocket part, sente hooks it up nicely to core.async

14:54 ztellman has an alternative called manifold that does similar to sente (connecting websockets, vanilla tcp, input-streams, core.async in various configurations to one another)

14:57 catern: hmm, sente appears to assume you control both ends?

14:57 server and client

14:57 justin_smith: catern: yeah, it's kind of frameworky

14:57 manifold is more flexible

14:58 catern: but aleph would be the part actually doing the websocket part

14:58 afaics http-kit doesn't have websocket client support

14:59 justin_smith: 'k

15:00 yeah, looks like it only has server support, and lately I don't think it's as well maintained as aleph either

15:01 catern: aleph has http too

15:01 so I guess I'll just use that for everything

15:01 normal http*

15:05 so, wait, I can't really tell

15:05 http://ideolalia.com/aleph/literate.html#aleph.examples.http

15:05 how do I get callback-style thing?

15:05 get a*

15:07 justin_smith: catern: if you go down to the http/get examples, instead of specifying a callback, you chain operations on the dereferenced result

15:07 hmm... maybe there is a way to do a callback too though

15:07 catern: yeah, I saw that, but that's not what I want, I think

15:08 since, well, right now my architecture is to fire off HTTP a bunch of requests every fraction of a second

15:08 fire off a bunch of HTTP requests

15:09 justin_smith: catern: did you get down to the aleph.examples.websocket stuff at the bottom?

15:09 catern: i don't want to have to wait for any or all of them to complete before firing off the next

15:10 justin_smith: yeah, I can't really grasp what's going on, but I can only assume that I can register some callbacks maybe

15:11 justin_smith: catern: I think bus/subscribe is the thing you want there, from skimming that code

15:11 catern: I'm interested myself as I may want to upgrade from http-kit/sente to aleph/manifold...

15:16 catern: this is quite complex

15:17 justin_smith: catern: might be easier to just use the direct socket with socket i/o, then upgrade if you need the features

15:17 catern: the more I work on my websocket connected app the more sense those features make...

15:20 catern: the direct websocket or TCP socket?

15:20 justin_smith: websocket

15:21 catern: i can't even tell what the features are here

15:22 this doesn't look any better than wrapping synchronous actions in some async thing

15:22 anyway, operating on the direct socket would be synchronous, right?

15:23 lokien: Hey, I'm processing a string with recursion. Each time I process a letter, I have to update a vector, based on that letter and last item on the vector. How do I do that? I'm struggling with immutability here

15:23 justin_smith: catern: depends, you could use nio

15:23 lokien: are you processing a sequence of some sort start to end?

15:24 lokien: justin_smith: yeah

15:24 justin_smith: if so, reduce

15:24 lokien: let me show you what'd be my input and desired output

15:24 justin_smith: ,(reduce (fn [letters letter] (update letters letter (fnil inc 0))) {} "hello")

15:24 clojurebot: {\h 1, \e 1, \l 2, \o 1}

15:24 lokien: "next prev next next" -> [0 1 0 1 2]

15:25 (vector is 0 initially)

15:25 "" -> [0]

15:26 catern: justin_smith: wait so is this websocket support all just borrowed from some java library?

15:26 ridcully_: ,(frequencies "hello")

15:26 clojurebot: {\h 1, \e 1, \l 2, \o 1}

15:27 justin_smith: ridcully_: right :) just showing the general idea of how to do that with reduce

15:27 lokien: ridcully_: I know, but.. how does that help?

15:28 ridcully_: lokien: that was to make justin_smith smile

15:28 lokien: ridcully_: oh, well, you're a nice person

15:29 TimMc: lokien: If I give you an accumulator [0 1] and an operation "next", how would you write (fn [accum operation] ...) to give me back [0 1 2]?

15:29 besides (constantly [0 1 2]) ;-)

15:29 justin_smith: ,,(reduce (fn [moves word] (conj moves (({"next" inc "prev" dec} word) (peek moves)))) [0] (clojure.string/split "next prev next next" #" "))

15:29 clojurebot: [0 1 0 1 2]

15:30 * lokien 's head exploded

15:31 justin_smith: ,(reductions (fn [move word] (({"next" inc "prev" dec} word) move)) 0 (clojure.string/split "next prev next next" #" "))

15:31 clojurebot: (0 1 0 1 2)

15:31 justin_smith: simpler, I think

15:32 lokien: I tried to do it with "loop"

15:32 but it was a nightmare

15:33 justin_smith: lokien: yeah - that's why my first question was "are you visiting items in order from some source" - reduce / reductions handle the defaults for that nicely

15:34 and unlike map / for, they carry state you can use at future steps

15:34 lokien: justin_smith: idiomatic clojure is so good, my clojure is awful tho

15:34 justin_smith: lokien: the solution is to write more clojure - and share your code with other clojure folks

15:35 sdegutis: the level of indirection in duct is really confusing me... https://github.com/weavejester/duct/blob/master/duct/src/duct/component/endpoint.clj

15:35 justin_smith: my clojure was terrible when I started, it's maybe acceptable now

15:35 lokien: justin_smith: primarily with you, I guess

15:35 acceptable?

15:35 writing code for entire irc?

15:35 are you serious? :D

15:35 justin_smith: heh, that's just one-liner examples, building real stuff is different

15:36 lokien: even more demanding? ygh

15:37 sdegutis: lol justin_smith "maybe acceptable"

15:37 justin_smith: lokien: the one liners and examples here are kind of like that forms in a martial art, or scales in music - they can help you understand something, but aren't much on their own, there's the actual craft side of it too, and I have far to go

15:38 lokien: even sdegutis says you're beyond "acceptable"!

15:38 justin_smith: like, I still have yet to hit the "build a useful lib that has nothing in it I am embarrassed of" landmark

15:38 sdegutis: lokien: "even sdegutis" lol

15:38 justin_smith: that goal is literally impossible due to the 6-months rule

15:39 lokien: justin_smith: for how long have you been in clojure family?

15:39 sdegutis: welp, you're good too

15:39 justin_smith: lokien: I've been using clojure for ... about 4 years?

15:39 sdegutis: hey me too!

15:39 justin_smith: sdegutis: OIC http://www.imdb.com/title/tt0865561/

15:39 lokien: sdegutis: I saw you on hacker news, is paladin usable now?

15:39 sdegutis: lokien: wha?

15:40 lokien: i was on HN?

15:40 lokien: sdegutis: you were commenting

15:40 sdegutis: oh

15:41 lokien: justin_smith: that's not 20 years!

15:41 I mean, you don't have to have a killer app/lib yet

15:41 sdegutis: lokien: haha no paladin probably wont be usable until 2017 at this rate.. this is my first attempt at writing a bytecode-based vm and bytecode compiler

15:41 lokien: sdegutis: damn, I wanted to try it

15:42 sdegutis: lokien: haha get in line ;)

15:42 (aka: i wanna try it too!)

15:43 lokien: sdegutis: only if I could help

15:43 justin_smith: where would I use "loop" form then?

15:44 TEttinger: sdegutis: making a language eh? clojuresque?

15:44 justin_smith: lokien: where speed is your top priority, it can be faster

15:45 sdegutis: TEttinger: heh i wouldnt go so far as to say "making".. more like "dreaming of" at this rate lol

15:45 justin_smith: lokien: especially when your source of data is not a sequence, but maybe a channel or a socket etc.

15:45 sdegutis: you should just do a fork of oxcart

15:45 TEttinger: is that arrdem's?

15:45 sdegutis: TEttinger: but yeah im seein if i can make a bytecode based compiler and vm written in pure & portable c that has only immutable clojure-like values and clojure-like sytnax

15:45 justin_smith: yeah

15:46 lokien: justin_smith: thanks

15:46 TEttinger: ha, portable C

15:46 justin_smith: sdegutis: how many years do you have set aside to do hash-maps?

15:46 TEttinger: that one always makes me chuckle

15:46 sdegutis: justin_smith: haha wait i dont get it

15:47 justin_smith: sdegutis: I mean, do you plan to take 2 years implementing hash-maps, maybe 4 or 5?

15:47 TEttinger: "portable if you have a windows, mac, linux 32-bit, and linux 64-bit computer to compile on"

15:47 sdegutis: justin_smith: heh yeah i thought hash maps were simple until i started reading about how clojure implements them

15:47 justin_smith: so i guess 2017 is reasonable to have "efficient" hashmaps by :D

15:47 justin_smith: especially since you are also writing your own gc last I heard

15:47 TEttinger: there are HAMT implementations in C

15:48 CHAMP is optimized for the JVM

15:48 sdegutis: justin_smith: oh yeah the gc is the easy part afaiui

15:48 TEttinger: tell that to google

15:48 sdegutis: i didnt say efficient/fast gc lol

15:48 TEttinger: dalvik's GC is awful compared to hotspt

15:49 sdegutis: im not aiming to compete with the jvm, im just trying to get something that would be cool for command line scripts.. something like lua

15:49 TEttinger: ah cool

15:49 sdegutis: (in terms of performance)

15:49 TEttinger: yeah I had a similar goal with my attempt at a language

15:49 sdegutis: how did it go?

15:49 did you finish it?

15:49 TEttinger: it went pretty well, I did not finish it, luajit is a kickass thing to target

15:50 the bad parts were that I was doing a lot of stuff in a dumb way, so it lost a lot of potential improvement

15:50 lokien: eh, guys here are implementing languages

15:50 and I'm just sitting here, struggling with advent of code

15:51 TEttinger: I was trying to make a clojure-like lisp that, like yours, could start up quickly and run simple things

15:52 if I started over I would use https://github.com/franko/luajit-lang-toolkit , which is a bit heavy-duty but should result in damn good opts

15:52 sdegutis: lokien: youd be surprised how graspable implementing a basic language is, as long as you do it inefficiently :D

15:52 TEttinger: hmm interesting.. yeah for something that would compete with ruby&rails, luajit looks like a good vm to target

15:53 TEttinger: i think ruby rather shines at command line stuff, small programs that arent intended to be long-lived

15:53 lokien: sdegutis: I dream of a project like this :(

15:53 sdegutis: lokien: lol haha

15:54 TEttinger: ok, back to space filling curves...

15:54 lokien: sdegutis: I open up my vim, sit there staring at screen for like 20 minutes, and then go eat something

15:55 sdegutis: well theres your problem

15:55 lokien: sdegutis: and then I forget about clojure for the rest of the day

15:55 sdegutis: you're using vim!

15:55 haha

15:55 lokien: with emacs it was even worse

15:55 * sdegutis kids, /me kids

15:55 lokien: like "shit, how do I close this buffer? *pkill emacs* welp, all is gone, screw this"

15:55 engblom: I also prefer vim. fireplace is really making clojure development under vim pleasant

15:56 lokien: I can't connect to my repl with fireplace

15:56 few days ago, only :Console wasn't working

15:56 now I can't connect at all

15:56 :(

15:57 sdegutis: editor wars are, like, over, maaan.. the /true/ editor is whatever is in your heart

15:58 lokien: what if my heart is a cold place filled with void?

15:59 ridcully_: have you changed anything? any plugins got autoupdated etc?

15:59 sdegutis: then the true editor for you is (void)0;

15:59 lokien: ridcully_: nothing!

16:00 ridcully_: e.g. cider-nrepl was updated recently, or am i just sitting on an old version?

16:00 lokien: sdegutis: let's write it in clojure :^)

16:00 sdegutis: hahahhaa

16:00 (do nil)

16:00 done

16:00 ,(do nil)

16:00 lokien: Next Big Thing

16:00 clojurebot: nil

16:01 ridcully_: lokien: are you using a pinned version for cider/cider-nrepl?

16:01 lokien: ridcully_: I'm using vim, darn

16:01 ridcully_: me too

16:02 lokien: with cider?

16:02 ridcully_: yet i have cider-nrepl for fireplace installed

16:02 lokien: I'm using vanilla fireplace

16:02 and salve

16:02 and things for highlighting

16:13 amandabb: hi

16:14 so hash tables dont have guaranteed order, but assuming they dont change will accessing items by random index at least be consistently random?

16:14 sdegutis: oh right i forgot cider 0.10 was released woo time to upgrade

16:15 sobel: amandabb: i wouldn't count on it

16:15 amandabb: like if i have a hash table of 10 items and access by random index instead of key

16:15 will any item be relatively equal likely to show itself given a large enough amount of attempts

16:16 or will some items be more likely to keep reappearing

16:16 sobel: how do you index a hash table

16:17 amandabb: can you not?

16:17 i just assumed you could

16:17 justin_smith: amandabb: (rand-nth (vals m))

16:17 amandabb: sometimes i want to access by key but other times i just want a random item

16:17 ooo

16:17 thank you

16:17 justin_smith: amandabb: if you want key and value, (rand-nth (seq m))

16:17 that will give you k/v as a two element vector

16:17 amandabb: gotcha thanks this is perfect

16:23 ridcully_: lokien_: fired up a container, empty vim + pathogen + the four deps salve wants + lein. ran in tmux and ran :Console. cpp/Eval works

16:24 lokien_: ridcully_: yeah, I'm hearing it for the second time

16:24 I guess my laptop is.. Special

16:25 sdegutis: do you use emacs? ;-;

16:25 sdegutis: lokien_: yep

16:26 lokien_: sdegutis: with.. Emacs bindings?

16:26 sdegutis: lokien_: yep

16:26 ridcully_: i added cider-nrepl for some reason (maybe mentioned in a ticket). so i wanted to see, if its important - but seems not

16:26 sdegutis: lokien_: well, kinda

16:26 ridcully_: what errors do you get?

16:26 lokien_: sdegutis: I'm telling your mother

16:27 sdegutis: lokien_: hahaha good luck

16:28 StevensMother: Hello sdegutis

16:29 I'm worried about your pinkies going sore from these bindings you're using

16:29 noncom|2: did anyone use lein-externs ( https://github.com/ejlo/lein-externs ) for clojurescript to generate externs ?

16:30 sdegutis: lokien hah

16:30 StevensMother: It's your mom here

16:30 Please, please stop

16:30 sdegutis: op plz

16:30 haha lol

16:30 StevensMother: no this is patrick

16:31 StevensMother: Oh, you're no fun. :^(

16:31 ridcully_: used some online service last time (most likely linked in the cljs wiki) last time i had to do it

16:31 sdegutis: lokien_: YOU MUST CONSTRUCT ADDITIONAL PYLONS

16:31 ridcully_: noncom|2: but the js was very simple

16:31 noncom|2: ridcully_: yeah, i remember you gave link to the service

16:31 sdegutis: lokien_: sorry i never learned how to interact with people on a normal level this is the best i can do

16:31 artosis: sdegutis: no I don't

16:32 sdegutis: hahah apparently neither have you, alright high five!

16:32 artosis: *high five of social awkwardness*

16:32 sdegutis: lokien so you learnin clojure as part of a high school course or just for fun on the side or what?

16:33 lokien_: I'm in high school, it sucks, it's all hardware

16:33 I just want to write programs, they make me happy

16:36 sdegutis: also, I don't want to go to college, it sucks even more

16:36 sdegutis: lokien_: heh dont know what to tell ya bud sorry

16:36 bbl

16:37 lokien_: sdegutis: why sorry?

16:39 sdegutis: going to sleep now, so.. have a nice day and everything :)

16:51 amandabb: hi can someone take a quick look at this go-block (couple lines) and explain why i'm getting the listed error? http://pastebin.com/j3W8xM3j

16:51 tried using do blocks, doall, doseq.. hmm not sure why it's not working

16:54 neoncontrails: Alright I give up. Asking this n00b question. Using this library:

16:54 https://github.com/wiseman/clj-pronouncing

16:54 Very straightforward. Included the library under :dependencies in my project.clj

16:54 Included the require statement.

16:55 Cursive still can't find the library. What else is required?

16:56 I rebooted the project as JDK1.6, juuust in case it was a versioning issue. No dice.

16:56 I'm out of ideas.

16:58 cfleming: neoncontrails: Do you see the lib under External Libraries in the project view?

16:58 ridcully_: mind to share that project.clj? or is this a cursive-only problem?

16:59 neoncontrails: cfleming: good question. I don't see it, no.

16:59 ridculy_: it's dull I promise, but sure. One sec

16:59 cfleming: neoncontrails: Ok, open View->Tool Windows->Leiningen

16:59 And hit the refresh button.

17:00 That'll sync your dependencies from your project.clj to your Cursive project

17:01 neoncontrails: Got it. Trying now

17:01 ridcully_: http://pastebin.com/X1kzkufG

17:02 noncom|2: amandabb: something is undefined

17:02 amandabb: hmmmm

17:02 noncom|2: it's clojurescript, so that means you are doing undefined.someMethod in js

17:02 amandabb: nothing is undefined in there though

17:03 (def game-chan (chan)) is above it

17:03 what other vars are there? when i remove that block of code it runs fine

17:03 noncom|2: amandabb: are you sure? what if you console.log all of them: go, timeout, <!, >!, game-chan

17:03 amandabb: ooooooo

17:03 it's not just vars

17:04 i forgot about require

17:04 thats probably it

17:04 noncom|2: these are functions, right, but they should print out

17:04 amandabb: yeah didnt import timeout

17:04 good call thanks

17:04 noncom|2: ah, ok

17:04 neoncontrails: cfleming: so that worked great for loading the library into the current project. Now It's giving me a different error about unspecified modules when I try to run, but I may be able to tackle that one

17:05 cfleming: appreciate it. I just upgraded from community edition, I don't recall these hoops

17:07 cfleming: neoncontrails: No worries, I have plans to make that easier/more intuitive

17:07 (i.e. starting with actually telling you when you need to do it)

17:08 noncom|2: amandabb: oh and as a second thought: all these: <!, >!, go, and other stuff are actually vars. it's one of the core features of a lisp - homoiconicity :)

17:08 amandabb: o right

17:15 neoncontrails: cfleming: hmm. I know that the 'module not specified' error is related, but I'm having trouble deciphering what the error means. It's not... really a module, is it? A module would be like a .jar?

17:16 cfleming: neoncontrails: Did you just upgrade IntelliJ?

17:16 neoncontrails: I did, yes

17:16 cfleming: Ok, there's a migration to the run configs which doesn't always work, and I haven't figured out why.

17:17 Open your run config using Run->Edit Configurations

17:17 Check that the specified module looks ok - you might need to re-select it and hit apply.

17:18 neoncontrails: Bingo! Man, I am glad you were here.

17:19 I'm not sure I would've stumbled on the solution to that.

17:26 devth: how to get lein to output just the project version?

17:31 looks like i'm gonna have to use lein-exec

17:36 justin_smith: devth_: hack way to do it (nth (read-string (slurp "project.clj")) 2)

17:36 if it's there on disk

17:36 I'm sure there's a right way that isn't that though

17:37 devth_: ah, yeah

17:37 could use that in combination with lein-exec

17:38 justin_smith: devth_: the good way to do it would be to make a simple lein plugin that gets that data from the project

17:38 that would be a very simple plugin

17:38 devth_: true

17:38 wonder if someone already has

17:39 there's one that sets version :)

17:39 justin_smith: devth_: https://github.com/taoeffect/slothcfg

17:39 runtime access to project.clj data?

17:43 devth_: hm, so i don't think lein-exec and another plugin can work together

17:43 plugins run in a separate jvm or smth?

17:43 tried: lein exec -e "(use 'cfg.current) (println (:version project))"

17:44 but it can't find cfg.current

17:45 devth: ah, need -ep to eval in-project

17:46 lein exec -ep "(use 'cfg.current) (println (:version @project))"

17:47 lol. a bit heavy handed

18:04 justin_smith: (defn 😈 [& args] ...) <- what should go in there?

18:08 ystael: justin_smith: i dunno but it should probably consume all available file descriptors

18:08 MJB47: (mapv #(println "i hate bytes") (range))

18:09 justin_smith: MJB47: making them signed is the icing on the cake

18:32 yenda: Hi guys, do you have a better way to refactor cljs code than manual work ?

18:38 neoncontrails: yenda: I've had great results with IntelliJ/Clojure's refactor tool. I think emacs also has a respectable one, but it's a bit tricky to use

18:39 yenda: if you decide to go with intelliJ though, make sure to get IDEA 14 (not 15, the most recent). Cursive, the Clojure plugin, hasn't been updated yet

18:40 BRODUS: neoncontrails: what refactoring tool do you use for emacs?

18:40 cfleming: neoncontrails: Cursive does work with v15

18:40 BRODUS: i didn't know there waso ne

18:40 cfleming: BRODUS: clj-refactor

18:40 (I don't use it, but that's what you want)

18:40 neoncontrails: cfleming: it does? Yess! I might get that right now then

18:41 BRODUS: ooo, thanks

18:41 noncom|2: but it won't refactor clojurescript because it relies on a running jvm, no?

18:41 neoncontrails: BRODUS: uhh... I'll look up the name. It was the scary tool none of us understood at all in SICP

18:41 cfleming: @noncom|2 I believe that's the case, yes

18:42 BRODUS: there was emacs in SICP ?

18:42 cfleming: Cursive's does work with CLJS, but is currently more limited than clj-refactor

18:42 noncom|2: cfleming: that might be interesting for yenda then

18:42 zms: I'm trting to launch a cljs repl with boot using cljs-repl task. I get "Implicit target dir is deprecated, please use the target task instead. Set BOOT_EMIT_TARGET=no to disable implicit target dir.

18:42 neoncontrails: yup. My university really threw us in the deep end of the pool there

18:43 BRODUS: yeah it took me 2-3 attempts over a couple years before I took to emacs, can't imagine having to learn it with an actual workload

18:45 zms: running with "BOOT_EMIT_TARGET=no boot cljs-repl" seems to indicate that an nrepl server was started but there's no repl."

18:45 neoncontrails: It wasn't pretty. I still managed to fall kind of in love with Scheme, but it definitely left a Pavlovian aversion in me to emacs itself

18:47 zms: Emacs CIDER also fails to connect to the reported port of the nrepl server.. :-( Any hints/guidance appreciated.

18:48 justin_smith: zms: is the cljs repl provided via a browser, or node, or?

18:51 turbofail: huh. i learned to love emacs in order to deal with my workload

18:51 zms: justin_smith: hmm, good point. i'm using https://github.com/adzerk-oss/boot-cljs-repl with weasel and piggieback.. so i guess it should be provided by browser. however, i want to use node.

18:53 justin_smith: zms: so you get a clojure repl, then eventually you call (start-repl) ?

18:54 (once the node process is running with that half of the piggieback/weasel stuff?)

18:58 zms: justin_smith: i guess i'm all confused. must have faulty mental model.. :-( what i would like: Emacs CIDER to be connected to a repl provided by node.

18:58 pilne: hrm... clojure + actors for a concurrent game engine....

18:59 yenda: cfleming: clj-refactor doesn't work with cljs

19:00 justin_smith: zms: the way it works is that you have a clojure repl on a jvm, and you have a clojurescript process with a websocket. The websocket connection is used to send your compiled cljs and run it, and the results come back to your repl (which is still on top of the jvm)

19:00 you need the jvm because you are compiling new clojurescript code as you go in order to run the repl

19:00 yenda: neoncontrails: thanks, I prefer emacs though :/

19:00 neoncontrails: turbofail: yeah that's one way of looking at it. I just remember one time being on a tight deadline, and hitting the wrong key combo, and suddenly everything I typed was wingbats

19:01 turbofail: lol

19:01 justin_smith: zms: so you need cljs code that opens up the websocket and is ready to eval your code, and then you bootstrap (piggyback) that on top of a regular clj nrepl process

19:01 neoncontrails: and I distinctly remember figuring out 10 minutes later that I was stuck in something called 'cuneiform mode' and kind of rage sobbing

19:03 yenda: you are a much braver soul than I. :) Glad you found something

19:03 yenda: neoncontrails: for me the hardest par was not getting myself stucked in configuration mode, where I would end up configuring emacs for days

19:03 then I discovered spacemacs and barely felt the need to configure anything

19:05 zms: justin_smith: so i need 1) clojure repl on jvm (using boot repl), 2) clojurescript process with a websocket (using cljs-repl?), 3) CIDER connects to nrepl (which passes the code to cljs). did i get it right?

19:05 neoncontrails: yenda: yeah you make a good point though. I've been rocking Vim a bit lately, when constrained to a headless server, and I think it can be pretty tough to learn the keystrokes if you haven't directly participated in their making

19:06 justin_smith: zms: I'm not sure about "cljs-repl" but the rest sounds exactly right

19:06 the cljs process will be node loading the js that your cljsbuild outputs

19:06 and that js should make it open a websocket that talks to your repl, etc.

19:07 yenda: neoncontrails: that's why spacemacs is so awesome, it has all the nice tools to help you learn the keystrokes as you go

19:07 zms: justin_smith: so the missing piece is something that will start a process that will link node and clj repl over a websocket, right?

19:07 justin_smith: zms: yeah, this is what piggieback and weasel do together

19:07 their readme files should show you what to do

19:08 neoncontrails: yenda: yeah? Hmm. I'll keep that in mind. I will gladly accept offers of handholding when it comes to emacs config

19:08 zms: justin_smith: thank you for the clarity. be back in a few. :)

19:08 justin_smith: zms: I use figwheel via lein, which automates all this (but I still ended up needing to know the details because abstractions leak, of course)

19:09 yenda: neoncontrails: apparently there is no refactoring tool for cljs yet though :(

19:09 neoncontrails: Gotta say. I've never felt more like an old man than I have the past few weeks on Vim

19:10 zms: justin_smith: figwheel with browser or node?

19:10 neoncontrails: At first, I mean, it was understandable. I was just picking it up. I was just getting started.

19:10 justin_smith: zms: with browser, but with node wouldn't be a huge difference - either way they load up the js and try to connect to a websocket

19:10 zms: justin_smith: honestly, lein has me frustarted.. it seems magical. boot seems conceptually something i can understand.

19:11 justin_smith: zms: yeah, the classic declarative vs. procedural split

19:12 neoncontrails: Then a week went by. Then another week. and I'm still terrified to move the cursor, lest I lose my 300th ordinal position in whatever line I'm on

19:12 zms: justin_smith: which is which? :)

19:13 justin_smith: zms: lein is declarative (you use a data structure that describes your outcome and parameters), boot is procedural (code that does the steps you want performed)

19:14 BRODUS: im using cider to dynamically refer a namespaces vars in another if it isn't already. is there a way to check what has been required in the namespace?

19:16 justin_smith: BRODUS: ns-aliases shows you what has been aliased

19:16 amandabb: hmmmm

19:16 justin_smith: ns-refers shows you what has been used / referred

19:16 BRODUS: but really, running require twice is not an error, and without the :reload arg it doesn't do anything the second time

19:17 BRODUS: calling refer again isn't an error either, if you want to do it at that level

19:17 ,(doc refer)

19:17 clojurebot: "([ns-sym & filters]); refers to all public vars of ns, subject to filters. filters can include at most one each of: :exclude list-of-symbols :only list-of-symbols :rename map-of-fromsymbol-tosymbol For each public interned var in the namespace named by the symbol, adds a mapping from the name of the var to the var to the current namespace. Throws an exception if name is already mapped to somethin...

19:17 neoncontrails: three cheers for idempotency! *cheers seven times*

19:17 justin_smith: heh

19:20 ,(refer 'clojure.core) ; no error!

19:20 clojurebot: nil

19:20 justin_smith: it only errors if the new refer conflicts

19:20 BRODUS: justin_smith: thanks, i didn't realize require did nothing second time around

19:20 zms: justin_smith: i read those documents several times (piggieback, weasel, and others) but it began to make sense only once you spelt it out. so thanks for that. i have enough homework for now. :)

19:22 yenda: neoncontrails: you can play vim-adventures to learn faster

19:24 neoncontrails: yenda: ooh! I was seriously thinking, just the other night, I need to either make a game or find one, because I think the only way I'm going to learn that many keybindings is if I'm playing like... Bop It! or something

19:25 But that might be kind of fun, actually. Delete it! Find it! Yank it! Yank it!

19:26 BRODUS: i liked this one: http://www.openvim.com/

19:26 don't know if vim-adventures goes deeper without paying

19:28 neoncontrails: That's pretty cool too. I've talked myself into making Vim It! See ya, evening plans

19:37 BorisKourt: Does anyone use lentic here?

19:38 (Better question might be, how do I search through all package commands in Spacemacs. It looks like the two commands Lentic uses are renamed.)

19:39 amandabb: is there any way to return a value from doseq?

19:40 im trying to iterate through a 2d array and when two if's are true i want to return a value and exit out of the loop

19:40 and then if it gets through both of them then to just return another value

19:40 turbofail: doseq never returns a value, it always returns nil

19:41 amandabb: so what else can i use?

19:41 trying to do something like this: (doseq [x .. y ..] if#1 .. if #2 .. return a value! .. ... . . done looping through both so just return this value instead

19:42 devth: rewrite it using reduce

19:42 turbofail: maybe reduce

19:42 amandabb: nested reduces?

19:43 turbofail: you could do a nested reduce, or you could do (reduce (fn [[x y]] ...) (for [x ... y ...] [x y]))

19:45 amandabb: hmmm

19:45 there's got to be a better way of doing this

19:45 i guess ill just think on it for a while

19:45 turbofail: or actually you could do it without reduce just by using some

19:46 justin_smith: amandabb: you can use reduce with reduced

19:46 ,(doc reduced)

19:46 clojurebot: "([x]); Wraps x in a way such that a reduce will terminate with the value x"

19:47 amandabb: ok

19:47 ill look in to reduced and some

19:47 thanks

19:47 justin_smith: ,(reduce (fn [_ x] (when (even? x) (reduced x))) [1 3 5 8 1])

19:47 clojurebot: 8

19:47 amandabb: yeah it sounds about right

19:47 justin_smith: amandabb: you can use reduce to walk the result of for, and for has the same syntax as doseq

19:48 amandabb: ok

19:49 im just not sure if reduce is right though

19:49 i dont really have an accumulator value per-se..

19:49 justin_smith: if all you are doing is checking for a specific value, use (some pred? (for ...))

19:50 amandabb: yeah that might be it

19:51 turbofail: actually (first (for [x ...y ... :when (pred x y)] (foo x y))) would do it to

19:51 s/to/too/

19:51 justin_smith: oh yeah, :when is cool

19:51 amandabb: ohhh right first would cut it off right? thats a good point

19:51 turbofail: there's so many possibilities

19:51 * turbofail bursts into song

19:51 amandabb: it wouldnt continue doing the calculation becuse it only needs one

19:51 turbofail: right

19:51 amandabb: ill look in to that too

19:51 justin_smith: first is not guaranteed to cut it off

19:52 amandabb: really?

19:52 justin_smith: if f has side effects that are important, don't do it that way

19:52 turbofail: well yeah there's like chunked sequences

19:52 justin_smith: amandabb: chunking

19:52 side effects and laziness are a bad mix

19:52 amandabb: theres no side effects in here

19:52 im just checking for intersections in a grid

19:52 justin_smith: amandabb: I said "if f has side effects that are important"

19:52 amandabb: if it doesn't go right ahead and do it that way

19:53 amandabb: ok cool

19:53 justin_smith: ,(first (map print [1 2 3 4 5 6])) ; amandabb - example of the gotcha

19:53 clojurebot: 123456

19:53 justin_smith: it printed all of them because chunking

19:53 amandabb: i dont quite understand

19:54 justin_smith: amandabb: map is lazy, but it still processed all the items even though we only asked for the first one

19:54 amandabb: yeah im saying why does it process all of them if it knows we just need one

19:54 justin_smith: amandabb: it doesn't

19:54 first knows, map doesn't

19:55 chunking

19:55 amandabb: basically, for efficiency reasons it processes 32 items at a time

19:56 amandabb: so first only stops map from processing more elements when it can guarantee the map function is pure?

19:56 justin_smith: well, if it can guarantee the map function is pure, it doesn't matter whether it stops it or not

19:56 (except for cpu cost of course)

19:57 amandabb: i guess what im failing to understand is that i was under the impression when first is paired with lazy sequences that it doesnt process the entire list

19:57 that it only does as much as it needs to and is thus efficient

19:57 justin_smith: amandabb: yeah, it's not that deterministic - chunking every time is faster than taking only one item at a time because you might not need them all

19:58 amandabb: ohhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh

19:58 i get it now

19:58 justin_smith: amandabb: stupid analogy "I need a soda" - it's faster to get a six pack than tear one can out

19:58 especially when it's "I need n sodas" and you don't know until runtime - default to grabbing some cases

19:58 amandabb: so if a list is less than a certain size (say 100) it just runs through the whole thing because that would be faster than trying to get speed improvements with laziness

19:59 justin_smith: right - it turns out it chunks by groups of 32 iirc

19:59 amandabb: gotcha

19:59 ok thats neato

19:59 i have to go now thanks for the help

19:59 justin_smith: np

20:12 zms: justin_smith: yay! finally everything works (with lein and figwheel). for reference, this is what i followed: https://libraries.io/clojars/nrepl-figwheel-node%2Flein-template

20:13 justin_smith: good night!

20:16 justin_smith: zms: you too, glad you figured it out

22:04 domgetter: If you pass a partialed function to reduce, does it remake it every iteration? ex: https://gist.github.com/domgetter/bb41ebb4056aff7804d7

22:14 justin_smith: domgetter: reduce is not a macro, all its args including the function are evaluated when the form is compiled

22:14 domgetter: easy test...

22:14 domgetter: ah okay, and macros get evaluated at runtime?

22:14 justin_smith: ,(reduce (partial str (println "test")) [1 2 3])

22:14 clojurebot: test\n"123"

22:15 domgetter: right, because that would've printed test three times if it was evaluating the partial every time

22:15 justin_smith: domgetter: macros can change how their args are evaluated - they can cause them to be evaluated at compile time, during some run-times, during every run-time, never....

22:15 right

22:15 domgetter: Okay I'll keep that in mind, thank you

22:20 justin_smith: one more question. are these delays superfluous or will clojure try to evaluate the let bindings? https://gist.github.com/domgetter/02fbe16020dd8b481d83

22:21 oh I guess I could do my own test with println

22:26 justin_smith: domgetter: yes, it will run all the clauses, so you can use delays if you want to only evaluate certain clauses

22:27 domgetter: yea, I just used the side-effect trick to convince myself that that's true :)

22:27 justin_smith: but here I think just the code is clearer than the delay / deref combo

22:29 yeah, println is a good way to test which things actually run

22:30 devth: println-driven-development

22:46 domgetter: println-driven-*understanding*

22:54 sdegutis: welp

22:58 justin_smith: sdegutis: whelps http://leerburg.com/Photos/whelp-1.jpg

22:58 sdegutis: haha lol

22:58 justin_smith: what new adventures in clojureland have you partaken in as of late old chap?

23:26 justin_smith: sdegutis: same old, working for a startup doing graph analysis

23:27 err, doing an app that does graph analysis

23:27 sdegutis: man that sounds so boring

23:27 is it fun?

23:27 justin_smith: it's actually pretty great, I've just been stuck with the generic stuff lately

23:27 the stuff that would just work out of the box with rails - login, settings, etc.

23:28 or at least the things I gather are much more cookie cutter there

23:31 sdegutis: hahaha yeah i know those feels

Logging service provided by n01se.net