#clojure logs

2014-10-11

00:22s1s2s3does clojure already have a macro version of map, that lets you apply arbitrary forms to elements of a list and not just functions?
00:23TEttingerthat sounds pretty useful... would it allow you to omit elements, in theory?
00:24s1s2s3You mean ignore certain elements of the list?
00:24justin_smith,(for [x [nil 1 2 false true]] (or x 42))
00:24clojurebot(42 1 2 42 true)
00:24TEttingerlike map mixed with filter
00:25TEttingerjustin_smith, the point being or is a macro?
00:25TEttingerand for
00:25s1s2s3That's not what I had in mind but I suppose you could in theory make something like that
00:26TEttingeryeah, for sounds like what you're after
00:26justin_smithTEttinger: yes, for is a macro, and you can use :when to exclude items, that was going to be my next demo
00:26s1s2s3yes for is pretty close to what I want come to think of it
00:26s1s2s3good point
00:27justin_smith,(for [x (range 10) :when (not (odd? x))] (inc x))
00:27clojurebot(1 3 5 7 9)
00:27TEttinger,(for [x [nil 1 2 false true] :when (number? x)] (inc x))
00:27clojurebot(2 3)
00:27justin_smithyeah, that too
00:31s1s2s3actually here is one difference between a macro version of map and for:
00:32s1s2s3suppose you were mapping a two-argument form to two lists
00:32s1s2s3like (mapcro .concat ["a" "b"] ["c" "d"])
00:33TEttingerI love the name
00:33justin_smith,(for [[a b] (map list (range 10) (range 10 20))] (* a b))
00:33clojurebot(0 11 24 39 56 ...)
00:34TEttinger,(for [[a b] (map list (range 10) (range 20))] (* a b))
00:34clojurebot(0 1 4 9 16 ...)
00:34TEttingerhuh
00:34s1s2s3the for way is a bit awkward in comparison in my opinion
00:34TEttingeryah
00:34TEttingerbut you could write a wrapper easily enough
00:35s1s2s3yes, just wanted to check if it's redundant with what already exists
00:35TEttingerI think for is pretty heavily optimized internally, I'd just do a wrapper around it
00:35TEttingersimilar to map
00:36s1s2s3yes I think I will do that
00:37s1s2s3thank you for your thoughts TEttinger and justin_smith
00:38clojerAnyone had any luck with Chestnut. David Nolen had much praise for it yesterday on his blog but I can't get my browser to recognise changes. Also lots of flakey core.async WARNINGs during compilation.
00:39justin_smithtrying to help people with chestnut has made me wish that lein templates had explicit versions like deps do
00:39justin_smithit's cool, but has been changing frequently, and sometimes is broken
00:40clojerjustin_smith: Sounds like the old story with the fragile cljs/lein/cider/figwheel/Austin/Piggieback toolchain
00:41clojerThis kind of thing really can turn new users away from Clojure/script
00:41clojerThe tooling is just dire
00:41justin_smithright, and chestnut is mixing in a bunch of those same elements - but once it is stable it should improve that fragile scenario (or at least we can hope)
00:42clojerjustin_smith: So many bits and pieces all breaking after updates is strong argument against the small libraries philosophy.
00:42clojerjustin_smith: Monolithic has its uses :)
00:42TEttingerand a strong reason why lein uses strict version numbers and not ranges
00:44clojerI wish the community would't tout the magic of Emacs/cider when it seems to be impossible to get a decent cljs browser repl with it.
00:44clojerLein + Emacs/cider is serverly broken IMHO
00:44justin_smithand if we could specify a template version, at least we could say "version $foo of chestnut is known good" or whatever
00:45technomancylein is broken?
00:45technomancybug report plz
00:45clojertechnomancy: No, the combination, especially for a cljs browser repl
00:45clojertechnomancy: I never managed to get one working.
00:45technomancyso you mean cider
00:46justin_smithcider is in alpha status - it's good because they are working on awesome features, and they are being ambitious, it's bad for stability and there should be a clear user flow to choose "many features, often broken" vs. "a few features, just works"
00:46clojertechnomancy: Yes, especially with Emacs
00:46TEttingerlein itself isn't broken by any means.
00:46justin_smithsaying the combination of lein and cider is broken is silly because cider is a library for using lein from emacs - cider is the broken part
00:46technomancy"especially" but cider only works with emacs
00:46clojerjustin_smith: I'm just thinking about what first imopression this gives to newcomers, that's all. Very bad.
00:47justin_smithright - we shouldn't tell people who don't know clojure yet "your best bet is to use this thing that breaks every other day"
00:47clojerjustin_smith: I have perservered for many months but had to switch to Lighttable in the end.
00:47technomancythat's like saying "my linux is broken"
00:48justin_smithtechnomancy: have you tried rebooting? that's the best way to fix a linux
00:48justin_smith /s
00:48clojerjustin_smith: True, but in practice we hear Emacs is the Clojure Way.
00:48technomancywho says that ._.
00:48technomancysend em this way and I'll give em what for
00:48TEttingernightcode, tbh, seems to fix a lot of these newbie issues. templates to start that set up everything without hassle, repl built in, paredit optional, integrates lein...
00:49technomancy(I always wanted to say that)
00:49TEttingertechnomancy, would you say leiningen's source is a good example of a well-documented medium-or-larger clojure app's code?
00:49technomancyTEttinger: as long as you stay away from a few places
00:50TEttingerlearn2code_ was asking about it earlier
00:50technomancyTEttinger: I am more comfortable pointing people to Syme, though it's small-to-medium.
00:50TEttingernever heard of Syme
00:50TEttinger~syme
00:50clojurebotIt's greek to me.
00:50TEttinger$google syme clojure
00:50lazybot[technomancy/syme · GitHub] https://github.com/technomancy/syme
00:51technomancy~syme is a web application for setting up disposable EC2 instances on which to pair program https://syme.herokuapp.com
00:51clojurebotYou don't have to tell me twice.
00:51technomancyyou say that, clojurebot, but sometimes I do
00:51justin_smith~syme
00:51clojurebotsyme is a web application for setting up disposable EC2 instances on which to pair program https://syme.herokuapp.com
00:52TEttingertechnomancy, that readme doesn't tell me anything about what it is
00:55technomancyTEttinger: try this instead https://syme.herokuapp.com/faq
00:58TEttingerah, neat. if I had a paired person to program with and could tolerate emacs or vim I would consider it
00:59justin_smithI want to see pair programming in ed
01:03seancorfieldThere's a plugin for LightTable to pair via Firebase now. Works pretty well for an early release.
01:04seancorfieldOr is it Firepad.
01:06seancorfieldFirepad. So you can pair via LT or a web browser.
01:06seancorfieldTEttinger: what are you using as an editor these days?
01:11TEttingerI write so little in the way of large clojure programs... most of what I do is one-liners, and anything with paren matching works. I did a larger thing in NightCode though, Oakes is doing a great job
01:22seancorfieldNightCode is a nice simple editor. We looked at it for ClojureBridge but decided the UX wasn't as nice - for beginners - as LightTable.
01:24seancorfieldAnd at work we're using LT for all our editing now. 23kloc Clojure, and some ClojureScript too now. Plus it's good for JS and css too.
01:24TEttingerI could never get the eval snippet feature to work in LightTable with my play-clj-using game. since it has odd thread reqs.
01:24numbertenis there any difference between
01:24numbertenflatten
01:24numbertenand 'apply concat'
01:24TEttingeryes
01:24seancorfieldnumberten: flatten completely flattens the collection
01:25numbertenah
01:25seancorfieldapply concat only flattens the top level
01:25numberteni see thanks
01:25TEttinger,(apply concat[[[1 2][[3 4 5 6][7 8 9]10 11 12]])(flatten [[1 2][[3 4 5 6][7 8 9]10 11 12]])]
01:25clojurebot#<RuntimeException java.lang.RuntimeException: Unmatched delimiter: )>
01:25numbertenyeah I didn't catch that in the docs
01:25numbertenthank you
01:25TEttinger,[(apply concat[[1 2][[3 4 5 6][7 8 9]10 11 12]])(flatten [[1 2][[3 4 5 6][7 8 9]10 11 12]])]
01:25clojurebot[(1 2 [3 4 5 6] [7 8 9] 10 ...) (1 2 3 4 5 ...)]
01:25TEttinger&[(apply concat[[1 2][[3 4 5 6][7 8 9]10 11 12]])(flatten [[1 2][[3 4 5 6][7 8 9]10 11 12]])]
01:25lazybot⇒ [(1 2 [3 4 5 6] [7 8 9] 10 11 12) (1 2 3 4 5 6 7 8 9 10 11 12)]
01:26Jaoodseancorfield: but LT's future is dubious since the author has move on to other things
01:26seancorfieldTyping Clojure on my phone is too hard TEttinger so thank you for the examples!!
01:26TEttingernp!
01:27seancorfieldJaood: LT is moving to community-supported open source so I'm comfortable with that.
02:53puyoClojure syntax, maps are {a ax, b bx} and vectors are [a b c] - why do you pass a vector to "let", wouldn't a map be more logical? Is it a Lisp hangover?
02:55TEttingerpuyo: I believe there may be options to the arglist for let. like with for, where you also have a vector of pairs, but then you could have :when (blah) or some theoretical no-arg option like :lazy
02:58TEttingerappears that let doesn't take an arglist. HOWEVER, vectors are sorted!
02:58TEttingerand maps are not
02:58TEttingerand you definitely want the arglist to be assigned in order
02:59puyoohh i see.. maybe the order is significant...
03:06puyothanks :)
03:28justin_smithnumberten: regarding flatten / apply concat / mapcat
03:28justin_smith~flatten
03:28clojurebotflatten is rarely the right answer. Suppose you need to use a list as your "base type", for example. Usually you only want to flatten a single level, and in that case you're better off with concat. Or, better still, use mapcat to produce a sequence that's shaped right to begin with.
03:42cflemingclojurebot knows what's up.
03:43numbertenjustin_smith: thank you
04:24kenrestivohuh
04:24kenrestivo,(contains? [1 3 5] (int (byte 1)))
04:24clojurebottrue
04:24kenrestivo,(contains? [1 3 5] (int (byte 5)))
04:24clojurebotfalse
04:24kenrestivo???
04:24lazybotkenrestivo: Yes, 100% for sure.
04:24justin_smithkenrestivo: contains on vectors checks for index
04:24justin_smithnot contents
04:24kenrestivoah, doh, thanks!
04:24kenrestivo,(contains? #{1 3 5} (int (byte 5)))
04:24clojurebottrue
04:25justin_smith,(.contains [1 3 5] 5)
04:25clojurebottrue
04:25justin_smith.contains does what you want
04:25kenrestivoso do sets :-P
04:26kenrestivohell, there's always
04:26kenrestivo,(#{1 3 5} (int (byte 5)))
04:26clojurebot5
04:27kenrestivoi'm generally allergic to using java interop, unless absolutely necessary
04:29justin_smithif you have one set, that will be used to check multiple items for membership, the set approach makes sense. If you are checking multiple collections for containing an item, then .contains may be better.
04:33numbertendoesn't doall realize a seq?
04:33justin_smithyes, but not recursively
04:34numbertenwhy is this a thing then
04:34numberten,(->> (map identity (range 10)) doall type)
04:34clojurebotclojure.lang.LazySeq
04:34numbertenshouldn't it be fully realized
04:34numbertenbefore reaching 'type'
04:34numberten?
04:34justin_smith,(do (doall [(range) (range) (range)]) nil)
04:34clojurebotnil
04:34justin_smith,((juxt identity type) (range 10))
04:34clojurebot[(0 1 2 3 4 ...) clojure.lang.LazySeq]
04:35justin_smitheven when fully realized, it is still a LazySeq
04:35numberteni see
04:35numbertenthanks
04:35justin_smith(type (lazy-seq nil))
04:35justin_smith,(type (lazy-seq nil))
04:35clojurebotclojure.lang.LazySeq
04:36justin_smithempty lazy seq
05:45tomjack(let [c (chan 1 cat)] (>!! c (range 1e6)) (count (repeatedly 1e6 #(<!! c))))
05:46tomjack;; returns 1000000
05:48tomjack(let [c (chan 10 cat)] (>!! c (range 2)) (>!! c (range 2)) (count (repeatedly 4 #(<!! c))))
05:48tomjack;; returns 4
05:48tomjack(let [c (chan 10 cat)] (>!! c (range 20)) (>!! c (range 20)) (count (repeatedly 40 #(<!! c))))
05:48tomjack;; doesn't return
05:48tomjackmaybe that is the only reasonable behavior?
05:56dagda1_what does the carrot and export mean in this function declaration (defn ^:export run [] which I found in some clojurescript code
05:56tomjackdagda1_: the function name will not be munged by google closure during advanced optimizations
05:57dagda1_tomjack: got it, thanks
06:00amalloydagda1_: spelled caret, by the way, even though it's pronounced like carrot
06:01dagda1_amalloy: haha, I know, I did not notice that
06:01dagda1_I must be hungry
06:03mmeixbasic-level follow-up question from yesterday: why are some functions in Clojure implemented as macros instead of "real" functions (for example and, or) - is there an advantage?
06:05tomjack(if (and true (do (Thread/sleep 1000) false)) ...)
06:06tomjacker
06:06tomjack(or true ...) I mean :)
06:09mmeixhm ... ok ...meditating this - thnx
06:20RhainurI've been doing the problems on 4clojure, and instead of having a steady rise in difficulty, everything seemed straightforward and easy right up until http://www.4clojure.com/problem/28
06:20RhainurI'm straight up stuck and have no idea how to proceed :(
06:20Rhainurany hints?
06:30tomjackRhainur: there is always the source of clojure.core/flatten... unless that's cheating? :)
06:32tomjackthat uses clojure.core/tree-seq, which you could avoid
06:32amalloyRhainur: consider how you could write a function that flattens a sequence by one level, and then use recursion to keep going until there are no levels left
06:33amalloymapcat will be the spine of most implementations of such a function
06:33tomjackdo they teach you nonymous fns?
06:34tomjackI guess they don't teach much
06:43Rhainurtomjack, amalloy: this is my first time working in a non imperative language
07:54Rhainurhahahahahaha man, I did http://www.4clojure.com/problem/26
07:54Rhainurand _pcl's solution is making me laugh so hard
07:54Rhainur(fn [i] (take i '(1 1 2 3 5 8 13 21)))
07:54Rhainurfucking brilliant.
07:57mmeixWhich is more idiomatic/recommended to say:
07:58mmeix#(+ % 3)
07:58mmeix#(+ % 3)
07:58mmeix#(+ 3 %)
07:58mmeix(sorry for the doubled line)
07:59mmeix(of course with "/" and "-" it would matter)
08:02Rhainurmmeix: in the clojure style guide, it only comes up once, and they use #(+ 5 %)
08:02Rhainurso I'd guess it doesn't matter that much
08:02mmeixok
08:02mmeixthnx
08:03mmeix[finding the Clojure Style Guide now]
08:04mmeixmaybe as a somewhat parallel case to (partial + 5)
08:09Rhainurmmeix: oh sorry https://github.com/bbatsov/clojure-style-guide
08:10Rhainurmmeix: I always have that and http://grimoire.arrdem.com/ open when working in clojure
08:10mmeixjust found the first one, thanks for the second!
08:10mmeixah, that's a great overview
13:19CodeWarGentlemen Greetings! Parsing Clojure for a hobby project of mine. Does Clojure have a notion of uniquely_owned_ptr. Meaning it could point to a structure which can contain other references to other structures. However the guarantee is that the entire object graph has only one outstanding reference to it. So if I passed the root pointer I can safely operate on it without
13:19CodeWarworrying about other references to some of the inner nodes
13:26dweaveis .emacs ok to use instead of init.el
13:32dweavei’m trying to install flycheck https://github.com/flycheck/flycheck. do i need this cask thing
13:37justin_smith~gentlemen
13:37clojurebotYou can't fight in here. This is the war room.
14:57arrdemjustin_smith: so if you had to write your own transducers explanation... how do? :P
14:57justin_smithheh
14:57justin_smithI got tripped up on "simple"
14:58justin_smithplease do give a better explanation if you have it :)
14:59arrdemlol. I think the trick is the composable partial builder stuff that Rich was talking about in the strangeloop talk.
15:00Jaoodjava's type system has so many rules
15:00arrdemif you think about transducers as just a way to generalize a state machine implemented as impure fns I think it's not too hard.
15:01Jaoodspambot alert
15:01justin_smithJaood: I blame inheritance
15:20cshellIs there a trick to getting Lighttable to be able to open source files from libraries you import?
15:27arrdem&(* 15 7.25)
15:27lazybot⇒ 108.75
15:52pgmcgeei'm having trouble with *print-length* in nrepl. i'm running user> (binding [*print-length* 2] (range 10)) but i always get (0 1 2 3 4 5 6 7 8 9) in response rather than (0 1 ...) that i expect
15:53schmirpgmcgee: it's being printed after the binding has gone out of scope
15:54pgmcgeeschmir: ah, how can i fix that?
15:54schmirpgmcgee: i.e. you're printing the result of the binding expression
15:54schmirdo (println (range 10)) inside the binding
15:55ben_vulpesso i'm starting in on a little clojure app that runs from the command line. due to startup time constraints, i want this thing to daemonize itself and to be callable later - are there any examples of clojure projects structured like this that anyone could point me at?
15:55pgmcgeeah, is there any way to have the binding apply to the echo nrepl does? that's really what i want to limit automatically
15:56pgmcgeeben_vulpes: how do you intend to call it?
15:58schmirpgmcgee: (set! *print-length* 2)
15:59ben_vulpespgmcgee: $ nifty_app start
15:59ben_vulpespgmcgee: $ nifty_app operation
15:59ben_vulpesat least that's what i'm thinking at this precise moment
16:00ben_vulpesif there's a more idiomatic approach i'd love to hear it. i've only really been building webapps with clojure for the past year, and now want to build a cli tool.
16:01pgmcgeeben_vulpes: i'm not a clojure expert, but i'm thinking that you'll probably need some sort of client/server setup where nifty_app is essentially a client and `nifty_app start` starts the server
16:01schmirben_vulpes: do you know nailgun? http://www.martiansoftware.com/nailgun/
16:02schmirben_vulpes: https://github.com/technomancy/grenchman may also be interesting
16:04pgmcgeeschmir: thanks, that worked!
16:04ben_vulpesschmir: nailgun's interesting, for sure.
16:05schmirpgmcgee: I set *print-length* in my ~/.lein/profiles.clj file
16:09pgmcgeeschmir: just did that and it's awesome. thanks for the help!
16:12schmirpgmcgee: fine. you may also like to set *print-level*
16:13justin_smithben_vulpes: seconding grenchman
16:17dnolen_grenchman hasn't been updated in a year and I never could get it to work even when it was originally released
16:22dnolen_ben_vulpes: if you want some deliverable that has decent startup time for other users then just AOT - people keep complaining about startup time but raw Clojure REPL starts in like 1s on a modern desktop/laptop - because AOT
16:23dnolen_other option if you can take Node.js as a dep is CLJS
16:30donbonif_hello
16:52DomKMIs there an easy way to convert a lazy seq of strings into an InputStream without first eagerly consuming the seq?
16:59arohnerDomKM: not easily, no
17:06DomKMarohner: feasibly? Would I be better off writing the lazy seq to a file and creating an InputStream from that?
17:06arohnerI'm pretty sure it's possible, but it'd be a little complex
17:07arohnereasiest way is probably to write to a byte array, and then IS from that
17:07arohnereasiest way that doesn't involve file I/O, that is
17:07justin_smitharohner: but how would you lazily fill the byte array?
17:07DomKMarohner: unfortunately, the seq it's larger than memory
17:07arohneraha
17:08arohnerjustin_smith: I was assuming "easy" wasn't lazy
17:08justin_smithhe mentioned not eagerly consuming the seq
17:16amalloyDomKM: do you really mean an inputstream, not a reader? strings are made of characters, not bytes, so you want to avoid converting for no reason
17:18amalloybut there are a few helpful functions for this in https://github.com/ninjudd/io/blob/develop/src/flatland/io/core.clj
17:19amalloynotably concat-input-streams takes a seq of input streams and returns an input stream which is their concatenation, and bytebuffer->inputstream turns a byte buffer into an input stream
17:36DomKMamalloy: I do mean an input stream...I think. I'm taking an input stream, converting it to a lazy seq so that I can filter it, and then I want to convert it back to an input stream. A way to map/filter/etc an input stream without making it a seq would also solve my problem.
17:50seangroveWhat's the shorthand for setting nested fields? e.g. (set! (.. dry .-gain .-value) 1)
17:54seangroveNevermind, doesn't really look like there is one
17:59nkozocore.async question: how you can make a go loop that takes items from a from-chan and put them on a to-chan? the tricky part is to park on from-chan awaiting items but also unpark when to-chan is closed by a remote party. I think I need something like alts! were you can wait items on from-chan but also unpark if to-chan is closed (but *without* reading items from to-chan)
19:10ben_vulpesi'm running with cider, and for some reason cider-jump-to-var isn't doing code navigation for me any more. any notion on how to debug this?
19:26axel_does anybody know a good way of debugging code inside a domonad macro call?
19:27justin_smithben_vulpes: you could potentially target cider-jump-to-var for debugging and step through it, if you know enough elisp so you would know which part is broken
19:28justin_smithM-x debug-on-entry <return> cider-jump-to-var
19:28chimpboyhi everyone i am a chimp
19:34ben_vulpesjustin_smith: i think that i'm going to rip cider out
19:35chimpboyben_vulpes yes but i am a chimp
20:45squeedeei wish i could use clojure for my arduino code
23:43squeedeeAnyone mind reviewing my code? https://github.com/squeedee/lsystem/blob/master/src/lsystem/core.clj#L11 - just wondering if i've taken a idiomattic approach to recursion
23:44justin_smithsqueedee: you may want to try making a lazy version - so that instead of providing a count as an argument, you can take as many of the results as you like
23:46squeedeei do want to do that.
23:46squeedeei was looking at transducers today
23:46squeedeetrying to understand how I write lazy versions of everything
23:47squeedeejustin_smith: how would i do it?
23:47justin_smithyou can basically replace the recur with (cons this-result (lazy-seq (iterate ...)))
23:47justin_smithahh - wait
23:48squeedeethey do all need to be evaluated
23:48justin_smithactually, you could use the clojure.core/iterate, and the nth item of the result is the result of n iteration
23:48justin_smithI realized you aren't building a sequence here, so it's not a question of using lazy-seq
23:49squeedeei guess when i went and shadowed iterate i should have at least read what it does :P
23:49justin_smith(core/iterate #(iterate % axiom) rules) - first item in the resulting sequence is your initial state, second item is first iteration, etc.
23:49justin_smithof course it is infinite, so use it with nth / take - don't evaluate directly :)
23:50squeedeesure
23:50squeedeei guess it makes sense to return the iteration results
23:51squeedeewhy hide it and make someone who wants it have to execute each version
23:51squeedeereally enjoying this
23:52justin_smithalso, having two arities at different levels of abstraction (one being repititions of the other) is a little odd
23:52justin_smithnot bad - I am sure I have seen it before, but a little odd
23:53squeedeenot sure i understand
23:55squeedeeSo no point in me providing the 'n' version at all - people should know intuitively (or through docs) to use iterate?
23:55justin_smithno - not what I am saying
23:55squeedeethats seperate
23:55squeedeeI'm asking that by way of looking at iterate
23:56justin_smiththere's no harm in wrapping it in iterate yourself
23:56squeedeei _also_ didnt understand what you were saying about the 2 arities for the abstractions.. Tho i guess if i try to explain it back I do get it.
23:56justin_smithit's as if + and * were one function, with two arities
23:56squeedeeone is 'transform-with-rules' and the other is 'iterate'
23:57squeedeeso they're two abstractions, so why smoosh them together
23:57squeedee?
23:57justin_smithyeah, something like that
23:57squeedeethat the gist
23:57squeedeelemme play with thay
23:57squeedeethat
23:57squeedeethanks
23:57justin_smithnp
23:58justin_smith,(iterate #(+ 5 %) 0)
23:58clojurebot(0 5 10 15 20 ...)
23:59justin_smithillustrating the +/* thing I was saying above