#clojure log - Mar 02 2015

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

0:47 Shayanjm: What's the difference between doto & ->?

0:53 puredanger: doto applies each expression separately without threading the result because it expects to be calling side-effecting functions

0:53 _kardan: doto cascaded calls & -> chained calls

0:53 puredanger: which is what you commonly get with Java setters

0:58 TimMc: &(clojure.walk/macroexpand-all '(-> a (b 1) (c 2)))

0:58 lazybot: ⇒ (c (b a 1) 2)

0:58 TimMc: &(clojure.walk/macroexpand-all '(doto a (b 1) (c 2)))

0:58 lazybot: ⇒ (let* [G__13521 a] (b G__13521 1) (c G__13521 2) G__13521)

1:31 jon__: getting started with clojure

2:48 bucketh3ad: Is it a good idea to use pmap to run a get/parse function over a list of uri's, or is there a better tool for such a task?

2:51 TEttinger: bucketh3ad, I think pmap is mostly for cpu-limited computations that need multiple threads, not things that need multiple network connections?

2:51 I haven't done much with remote getting of content

3:38 zot: morning all. i'm having a dumb moment, and hoping that somebody here might have the eyes to combat my blindness. i'm working up a "simple" core.async model for kafka, intended to work with the component library. it's failing miserably, despite having tried to model it off my other working async pub/sub code. i've stripped out the stop code, and made it self standing (instead of component based). the 'send-message' at the end returns, and the '

3:40 TEttinger: message cut off after: end returns, and the '

3:40 ^ zot

3:41 zot: the 'send-message' at the end returns, and the 'recv-message' just sits waiting. any clues?  https://gist.github.com/anonymous/b639bddfe1f7ea646b1f

3:42 (also, i would gladly take ideas and suggestions as to how experienced clojurists debug this sort of thing — i'm a bit clueless when debugging async, etc., code in clojure.)

3:43 sveri: zot: not sure about this, but I think I read somewhere you have to take extra steps to get stacktraces from async code

3:43 zot: i can't even tell if a stacktrace is the problem, or if i'm "doing it wrong" wrt pub/sub in core.async

5:33 ftr, it was something stupid: (async/pub was being called w/ (:publisher this), which is empty at that point in execution.)

6:16 devll: hi,I am using Component for my project.

6:16 and calling (.stop (:server component)) in (stop [this ..])

6:16 wont work.

6:17 full code is here. http://pastebin.com/FLhSw2MY

6:17 why?

6:17 clojurebot: why is the ram gone is <reply>I blame UTF-16. http://www.tumblr.com/tagged/but-why-is-the-ram-gone

6:18 devll: could anyone explain this to me? thanks.

6:20 justin_smith: ?

6:21 TEttinger: hey devll

6:21 I'll take a look

6:21 devll: hi TEttinger ,thanks

6:21 TEttinger: also, define "won't work"

6:21 devll: throws an exception.

6:22 TEttinger: when you (println (:server component)) , can you also print the (class component) and (class (:server component)) ?

6:23 also, which exception

6:23 NPE would be good to know if it's that

6:23 devll: the code I posted works.

6:23 I commented out one line.

6:24 brkpnt: Hi, there is an equivalent way to load a whole project like in Common Lisp asdf:load-system? In other ways to compile my whole project and load it to the repl?

6:24 devll: which throws exception if I use it instead of close-jetty function

6:24 brkpnt: ways->words*

6:25 devll: brkpnt: tools.namespace maybe help.

6:26 TEttinger: brkpnt: setting the :main ns may also help in project.clj

6:26 clojurebot: Excuse me?

6:26 devll: (:server component) is a org.eclipse.jetty.server.Server

6:27 TEttinger: and which exception?

6:27 devll: wait a sec.

6:28 TEttinger: it doesn't have a .stop method

6:28 http://download.eclipse.org/jetty/stable-7/apidocs/org/eclipse/jetty/server/Server.html

6:28 there's doStop

6:28 you could try .doStop instead of .stop

6:29 (I agree with your instincts that it should be called stop)

6:29 devll: it does.

6:29 please look at my close-jetty

6:30 it works

6:30 IllegalArgumentException No implementation of method: :stop of protocol: #'com.stuartsierra.component/Lifecycle found for class: nil clojure.core/-cache-protocol-fn (core_deftype.clj:555)

6:30 jetty 9

6:33 let me try doStop

6:34 TEttinger: ohhh

6:34 it has to do with component/Lifecycle

6:36 I have no idea how stuartsierra's lib works

6:36 devll: OK.

6:36 thanks anyway.

6:36 I will read the code myself.

6:38 TEttinger: I'm not sure how defrecord works, tbh

6:39 ##(doc defrecord)

6:39 lazybot: ⇒ "Macro ([name [& fields] & opts+specs]); (defrecord name [fields*] options* specs*) Currently there are no options. Each spec consists of a protocol or interface name followed by zero or more method bodies: protocol-or-interface-or-Object (methodName [args*] body)* D... https://www.refheap.com/98006

6:42 devll: changing to doStop gives NPE.

6:43 TEttinger: interesting, it is null then somewhere

6:44 oh, and (assoc component :server nil) won't change component

6:44 devll: but close-jetty works perfectly

6:45 TEttinger: ,(def component {:server "something"})

6:45 clojurebot: #'sandbox/component

6:45 TEttinger: ,(assoc component :server nil)

6:45 clojurebot: {:server nil}

6:45 TEttinger: ,component

6:45 clojurebot: {:server "something"}

6:45 devll: I think assoc is different for Component.

6:46 not this immutable way.

6:47 TEttinger: what's the type of component, the arg you get called component?

6:47 (class component)

7:00 zot: it should be an Httpserver record

7:00 and the dissoc/assoc at the ends looks correct to me

7:40 Guest7286: I have question: I removed core_test.clj and now Leiningen fails to run the other tests. I tried to find a solution, but Google doesn't seem to know how to fix it. Does anyone have an idea how to fix this?

7:48 never mind, it was a namespace clash that made it happen. sorry aobut that

7:57 Eremox: Is it possible to create a circular list without creating a new data structure?

8:00 schmir: , (take 10 (cycle [1 2 3]))

8:00 clojurebot: (1 2 3 1 2 ...)

8:01 schmir: Eremox: does cycle help?

8:02 Eremox: Think of a list where the second element is the list itself

8:03 hyPiRion: Eremox: no, cycle is the closest you get

8:03 It's effectively the same thing though

8:03 Eremox: OK thanks anyway.

8:26 ssideris: Eremox: you could make your own lazy seq and return whatever you like as the next element

8:26 doesn't have to be realized

8:26 Eremox: Yeah thanks I will try it.

8:45 sveri: Hi, did someone here do an app where he receives several chunks on the backend from cljs (like with resumable.js)?

8:45 I wonder how to handle the data that comes up

9:40 Hm, ok, in a different way, I get a org.eclipse.jetty.server.HttpInput in the request. How do I access it's contents or store it on disk?

9:41 calling .read on it returns -1 which means that the end is reached

9:43 llasram`: sveri: Two possibilities off the top of my head: (a) the request has no body content (e.g. is a normal GET); (b) something else in your stack is consuming the entire input

9:44 sveri: llasram`: ah, I look the second one up, taking out some middlewares, good idea

9:44 ordnungswidrig: sveri: it's an inputstream, I typically use "slurp" on it. depending on the content-type of course

9:45 svri: you can dump the complete request with `(prn request)` at some point, that might give you some insight

9:46 sveri: llasram: ordnungswidrig hm, it still is empty, even when removing my own questionable middleware, still strange. I am using resumable.js which sends get request with some content. at least get requests are all that get out

9:47 ordnungswidrig: slurp returns an empty string

9:49 mpenet`: body in GET is not always supported, it's not clearly defined by the http spec if I recall

9:50 depending on the server you're using it might just be ignored

9:50 sveri: mpenet`: Yea, I wonder if I am using it the wrong way

9:50 mpenet`: probably

9:51 ordnungswidrig: GET does not support a body in all practical applications

9:51 I think in HTTP/2 they got that clear

9:52 mpenet`: yup

9:52 sveri: kk, the docs also talk about POST requests

9:52 weird

9:58 ok, thank you, I must be using it wrong, will be looking how to fix this :-)

11:31 takosuke: hello peoples, I got a quick question if anybody is up for it -

11:31 Glenjamin: ~ask

11:31 clojurebot: The Ask To Ask protocol wastes more bandwidth than any version of the Ask protocol, so just ask your question.

11:32 takosuke: lol

11:32 understood :)

11:32 i want to have a login-required route in flask proxy to a different app

11:32 wordpress in this case

11:33 the point is to use only one auth system (the one implemented in flask) to give access to the content

11:33 im thinking of doing some proxy magic with nginx but i cant quite fit the pieces together

11:35 something like setting up a virtual host for the wordpress app that can only be accessed internally via localhost:9000

11:35 justin_smith: where does clojure fit into this?

11:35 takosuke: omg

11:35 sorry

11:35 wrong channel!!

11:35 justin_smith: heh

11:35 takosuke: lol

11:35 xemdetia: so as part of the ask to ask protocol

11:35 do we send him a reset?

11:35 takosuke: i badly need a reset

11:36 * xemdetia RST takosuke

12:00 sritchie: has anyone seen this? CompilerException java.lang.RuntimeException: No reader function for tag +clj, compiling:(taoensso/sente:606:89)

12:00 compiling a file at the REPL

12:00 this happens on my latest Sente upgrade - as far as I know, the cider repl’s not supposed to try and compile raw cljx files

12:02 is it possible to exclude files from a jar dependency?

12:02 justin_smith: sritchie: well, an easy thing would be to try a regular (non-cider) repl and see if the error is still there

12:02 sritchie: good call, trying

12:03 the_frey: If I have a massive lazy-seq and I call partition-all on it, then doseq to call some functions on the partitions I run out of memory

12:03 is that because the previous partitions are kept in memory?

12:03 I thought doseq discarded the head

12:03 sritchie: the_frey: did you bind the lazy-seq to something?

12:03 justin_smith: the_frey: do you have a binding somewhere to the beginning of the list directly?

12:03 sritchie: (def my-seq ...)

12:03 the_frey: it's in a let binding yeah

12:04 sritchie: justin_smith: still happens at a normal repl

12:05 the_frey: (let [foo (partition-all 10000 data-seq)] (doseq [data data-seq] load-into-db data))

12:05 justin_smith: sritchie: cool, so it's not a cider problem

12:05 the_frey: justin_smith ^ is a kinda simplified version of what I'm doing here

12:05 justin_smith: the_frey: that should not be holding onto the data - unless foo escaped the let block

12:05 the_frey: is it because it's returning a lazy seq of fully-qualified seqs?

12:05 justin_smith: (or something using foo escaped the let block)

12:05 the_frey: sorry

12:05 justin_smith: doseq returns nil

12:06 the_frey: (let [foo (partition-all 10000 data-seq)] (doseq [data foo] load-into-db data))

12:06 ^ is what I meant

12:06 justin_smith: that let block returns nil, so it will not hold onto foo's head

12:07 and thus that shouldn't leak

12:07 the_frey: hmmm

12:07 the weird thing is if I fully qualify this lazy seq, it takes like twenty mins but will eventually churn through in linear time

12:07 justin_smith: I assume load-into-db isn't holding onto it's args after the db transaction?

12:07 fully qualify?

12:07 the_frey: holding onto its args in what way?

12:08 fully realize?

12:08 justin_smith: OK, that's weird

12:08 the_frey: sorry, long day, a bit flu-ey

12:08 sritchie: justin_smith: brutal. gonna try publishing my own version of sente with cljx files excluded.

12:08 the_frey: yeah this way it stays way lower in CPU usage but still dies after a while, so my guess is a leak

12:09 justin_smith: the_frey: have you tried profiling? jvisualvm is free, it comes with the jdk, point and click

12:09 the_frey: good shout

12:10 I will go and have a nose

12:10 cheers!

12:13 arrdem: Has anyone messed with play-clj? I'm trying to find the path of least resistance to drawing a simple sprite & rotation based GUI

12:14 xemdetia: justin_smith, I must warn that jvisualvm is sun java only :)

12:14 or at least doesn't work with the jvm's I've tried

12:15 justin_smith: xemdetia: jvm or jdk?

12:15 xemdetia: jvm, I think I tried using it against ibm jre and it failed

12:16 godd2: 2acronym4me

12:16 xemdetia: ibm jre has other fun tracy-profile options though

12:16 Shayanjm: Hey guys, I'm trying to write a macro that returns a function for a circle given a radius and x/y offsets

12:16 here's what I've got: https://gist.github.com/shayanjm/8773123440a7c8cc2258

12:17 my issue is that when I macroexpand-all to inspect, that inner 't' (the argument to the anonymous function i'm trying to generate) ends up becoming <NAMESPACE>/t -- which obviously throws an error when used

12:17 arrdem: Shayanjm: the inner t needs to be a gensym. try using the token t#.

12:17 justin_smith: xemdetia: openjdk has a visualvm project, checking whether they include it with their jdk, I thought they did

12:18 xemdetia: oh I forgot about openjdk

12:18 It might indeed work there

12:18 Shayanjm: Excellent thanks a lot arrdem. I've been on python for a while so i've forgotten my clj know-how :(

12:19 you still in ATX btw?

12:19 arrdem: Shayanjm: you remember what -# does in the context of `? yep.

12:19 we never did get coffee :P

12:19 Shayanjm: I'm pinning that on you ;)

12:19 arrdem: I'll take it

12:20 Shayanjm: umm, i can't really articulate what -# does in the context of ` but my best swing is that it generates a symbol to be used within the context of the result of the macro?

12:20 sritchie: ambrosebs: hey hey

12:20 this is easier than twitter

12:20 Shayanjm: instead of evaluating immediately, or evaluating upon generation

12:20 sritchie: ambrosebs: right when I include core.typed I get that error from piggieback (with cljs excluded from core.typed)

12:20 ambrosebs: I’d love to get my team switched from schema to a real type system

12:21 justin_smith: Shayanjm: it escapes the auto-namespacing of `, while using a gensym to prevent accidental capture of symbols from the place the macro is used

12:21 arrdem: Shayanjm: in ` context, -# postfixed symbols are named gensyms. It's equivalent to wrapping your ` form with (let [t (gensym "t")] `...) and using ~t instead of t#

12:21 Shayanjm: ahhh

12:22 arrdem: Shayanjm: if you want an unqualified, named symbol `~'foo is the raw symbol foo. Handy sometimes if you actually do want closures or named parameters.

12:22 Shayanjm: Gotcha

12:22 arrdem: have you graduated?

12:23 arrdem: neg. spring next year.

12:23 * arrdem sad panda

12:23 Shayanjm: sweet, any solid plans after grad?

12:23 or gonna cross that bridge when it comes?

12:24 arrdem: lolno I'm just trying to get graduated first. bomb that bridge when I get to it.

12:24 Shayanjm: lolol can respect

12:24 arrdem: will be at Factual over the summer... so hopefully amalloy et all won't get sick of me :P

12:26 Shayanjm: sounds like fun

12:29 arrdem: I sure hope so

12:39 Kristien: hi

12:41 justin_smith: hello and welcome to the beautiful world of Clojure programming

12:44 Kristien: I love this wonderful world already!

12:44 justin_smith: (inc puredanger)

12:44 lazybot: ⇒ 33

12:44 justin_smith: for that clojure.inspect link on stackoverflow

12:45 I had no idea!

12:45 puredanger: :)

12:45 * justin_smith throws together a ring middleware to make a tree inspector for the request

12:46 justin_smith: it's just too bad there isn't a "mutable" version that has a single display, and lets you push things to it from the repl

12:47 Glenjamin: that exists

12:47 i've seen it

12:47 justin_smith: in some lib?

12:47 Glenjamin: if i could only remember what it was called

12:47 arrdem: There is no new code.

12:47 justin_smith: haha

12:47 because I don't want to pop a new frame for every request

12:47 Glenjamin: it's like a fancy logging/tracing thing that sends the forms to another file

12:48 s/file/process/

12:48 justin_smith: but I could totally use a thing that showed a tree of the most recent request

12:48 Glenjamin: and has a web interface

12:48 justin_smith: right, schmetterling does something like this

12:48 Glenjamin: and let you say "record the next N events and show me"

12:49 that's going to really bug me

12:50 maybe it's https://github.com/relevance/mycroft

12:51 i don't think that's what i was thinking of :s

12:51 godd2: Mycroft Holmes?

12:52 justin_smith: man, those software company names - "relevance" "factual". I guess "voodoo" and "enigma" were already taken.

12:52 Glenjamin: aha

12:52 http://matthiasnehlsen.com/blog/2014/11/14/Inspect/

12:52 that's the one

12:55 justin_smith: cool

12:55 (inc Glenjamin)

12:55 lazybot: ⇒ 15

12:56 justin_smith: Glenjamin: that dude's book looks interesting too, I hope he finishes it

12:57 Glenjamin: there's also a talk https://skillsmatter.com/skillscasts/6031-birdwatch-building-a-system-in-clojure

12:57 justin_smith: I prefer books myself, but good to know

13:27 daniel`: im trying to write a friend workflow with multiple challenges/steps, how could/should I share data between steps that the client should never recieve?

13:30 justin_smith: daniel`: you can use an in-memory ring session

13:30 all the client gets is a key used on the server side to look up the session

13:31 daniel`: mhm, right, a random token or something

13:31 i was wondering what to use to safely identify the user between steps

13:31 justin_smith: daniel`: yeah, it is built into ring's session stuff if you use the in-memory option

13:32 the user gets a cookie with their session id

13:32 daniel`: i already have db sessions setup for another worflow

13:32 workflow

13:32 justin_smith: OK

13:32 so you could probably leverage that. You may need ssl to ensure the cookie is not snooped / stolen though?

13:33 or use ring-anti-forgery

13:33 https://github.com/weavejester/ring-anti-forgery

13:34 daniel`: thanks, will look into it

13:35 its not a huge concern as the data the server returns back should be encrypted

13:35 and won't be usable to anyone anyway

13:38 justin_smith: daniel`: depending what is hapening, you would want to look out for people using the cookie to make changes they should't be authorized to make

13:40 daniel`: yep, definitely justin_smith

14:20 ambrosebs: get got into gsoc!

14:20 *we

14:21 havenwood: \o/

14:21 justin_smith: cool

14:22 ro_st: only good things happen when you get time to work on OSS. well done, ambrosebs!

14:28 ajmagnifico: Anyone have any thoughts on this stack trace? http://cl.ly/image/0p162k160o0S

14:29 agarman: you have recursion that doesn't end

14:29 justin_smith: ajmagnifico: sounds like a recursive concat bomb

14:29 ajmagnifico: It fills up 1024 frames in the stack trace, repeating the same pattern over and over again

14:29 I do use concat

14:29 justin_smith: ajmagnifico: what can happen, is that you can have nested calls to concat, and if they are not forced before a deep nesting, just getting the first item causes too many layers of lazy-seq realization on the stack, and you get a stack overflow

14:30 this can sometimes be fixed by using lazy-cat

14:30 or otherwise refactoring so you don't have a huge number of concat calls being realized all at once

14:30 Scala: [beginner lisp question] I'm trying to convert {:foo "1 1", :bar "2 2"} to [:foo [1 1], [:bar [2 2]], how do I map over a dictionary mapping like this?

14:30 ajmagnifico: thx justin_smith, I'll check it out!

14:31 justin_smith: Scala: seq

14:31 ,(seq {:a 0 :b 1})

14:31 clojurebot: ([:b 1] [:a 0])

14:31 justin_smith: Scala: also, map already calls seq on its arg

14:31 so you can just call map on the hash-map and it works

14:31 agarman: justin_smith: Scala also has a string split happening

14:31 llasram: And a Long/parseLong

14:31 justin_smith: OK

14:31 Scala: I'm not too concerned about that part

14:32 justin_smith: that's just details :)

14:32 agarman: yep

14:32 Scala: so since map will make a 2 element list out of map entries, is there a nice way to have a function expect that but treat it as 2 separate args?

14:32 agarman: you can just use (map (fn ...) {:foo "1 1" ...}) as well

14:32 no need doing seq first

14:33 llasram: ,(map (fn [[k v]] {:key k, :value v}) {:foo "1 1", :bar "2 2"})

14:33 clojurebot: ({:key :bar, :value "2 2"} {:key :foo, :value "1 1"})

14:33 llasram: "destructuring"

14:33 agarman: ,(map (fn [[a b]] [a b]) {:foo "1 1"})

14:33 clojurebot: ([:foo "1 1"])

14:33 justin_smith: ,(map (fn [[k v]] [k (map #(Long/parseLong %) (clojure.string/split #" " v)) {:foo "1 1" :bar "2 2"})

14:33 clojurebot: #<RuntimeException java.lang.RuntimeException: Unmatched delimiter: )>

14:33 llasram: heh

14:33 justin_smith: oops

14:34 agarman: ,(map (vector %1 %2) {:foo "1 1"})

14:34 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: %1 in this context, compiling:(NO_SOURCE_PATH:0:0)>

14:34 agarman: ,(map (vec %1 %2) {:foo "1 1"})

14:34 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: %1 in this context, compiling:(NO_SOURCE_PATH:0:0)>

14:34 agarman: ,(map #(vector %1 %2) {:foo "1 1"})

14:34 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (1) passed to: sandbox/eval176/fn--177>

14:34 Scala: agarman: I think (fn [[a b]]) is what I was looking for

14:34 agarman: ,(map #(vec %1 %2) {:foo "1 1"})

14:34 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (1) passed to: sandbox/eval204/fn--205>

14:34 agarman: dang it

14:34 nvm

14:35 justin_smith: ,(map (fn [[k v]] [k (map #(Long/parseLong %) (clojure.string/split #" " v))]) {:foo "1 1" :bar "2 2"})

14:35 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.String cannot be cast to java.util.regex.Pattern>

14:35 justin_smith: blerg, wrong one ::

14:35 agarman: yeah, there's a #(... %1 %2) syntax as well

14:35 justin_smith: ,(map (fn [[k v]] [k (map #(Long/parseLong %) (clojure.string/split v #" "))]) {:foo "1 1" :bar "2 2"})

14:35 clojurebot: ([:bar (2 2)] [:foo (1 1)])

14:35 justin_smith: there we go!

14:37 engblom: How is clojure storing a list? Is it keeping a count variable updated or will (count my-list) traverse the list in order to tell the length?

14:37 justin_smith: ajmagnifico: ##(nth (iterate #(concat nil % []) [1]) 10000)

14:37 lazybot: java.lang.StackOverflowError

14:38 justin_smith: ajmagnifico: ##(nth (iterate #(concat nil % []) [1]) 10)

14:38 lazybot: ⇒ (1)

14:38 agarman: ,(counted '(1 2 3 4 5))

14:38 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: counted in this context, compiling:(NO_SOURCE_PATH:0:0)>

14:38 rhg135: engblom: for lists it's linear

14:38 justin_smith: notice the only difference is the number of concat calls that got stacked up

14:38 agarman: ,(counted? '(1 2 3 4 5))

14:38 clojurebot: true

14:38 rhg135: for vectors a count is kept

14:38 engblom: rhg135: Thanks!

14:38 rhg135: np

14:39 agarman: ,(counted? {1 2 3 4})

14:39 clojurebot: true

14:39 agarman: ,(counted? (range 1000))

14:39 clojurebot: false

14:39 justin_smith: ,(counted? (cons 1 nil))

14:39 clojurebot: true

14:39 justin_smith: I had no idea///

14:40 engblom: According to what agarman man got the bot to tell, the length of a list seem to be stored

14:40 (doc counted?)

14:40 clojurebot: "([coll]); Returns true if coll implements count in constant time"

14:40 Scala: agarman: I think (fn [[a b]]) is what I was looking for

14:40 whoops

14:40 agarman: ,(counted? (seq 1 2 3))

14:40 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (3) passed to: core/seq--4091>

14:41 agarman: ,(counted? (seq '(1 2 3)))

14:41 clojurebot: true

14:41 justin_smith: ,(counted? (iterate inc 0))

14:41 clojurebot: false

14:41 * agarman needs to read stuff before hitting enter

14:43 justin_smith: agarman: there's an inherent race condition between reading the line, and sending it to irc

14:43 agarman: and we all get to see your retries :)

14:43 agarman: justin_smith: mostly trying to hit enter before you've answered the question

14:43 justin_smith: hehe

14:44 that's another kind of race

14:44 * justin_smith eases off on the throttle.

14:44 agarman: it's a race I'm not likely to win

14:44 (inc justin_smith)

14:44 lazybot: ⇒ 201

14:44 agarman: (dec agarman)

14:44 lazybot: You can't adjust your own karma.

14:45 agarman: justin_smith: keep the throttle to the floor. it appreciated by more than just me.

14:46 arav93: Hi!

14:47 And thank god Clojure got in :)

14:47 agarman: hi arav93

14:47 arav93: Hi agarman

15:29 maddprof: Hello all - I'm hoping I'm in the right channel, but I'm looking for some help writing a batch file that sets a few environment variables then executes a jscript file

15:30 justin_smith: maddprof: I don't think clojure is likely to help you with that

15:30 it's a great language, but not great for batch files

15:30 maddprof: justin_smith: any recommended channels? I've posted a question on superuser, but being a new member there I'm not really expecting any traction

15:31 justin_smith: I don't know, maybe if there is a windows related channel?

15:31 maddprof: okay thanks, back to google I go!

16:22 Scala: what is the idiomatic way to join strings in a list conditionally. ["a", "b"] -> "a, b" but ["a"] -> "a"

16:23 justin_smith: Scala: to me that would usually be a sign of some mistake being made

16:23 amalloy: Scala: that's not really conditional at all, that's just how joining works. see clojure.string/join

16:23 justin_smith: oh, n/m, amalloy is right, I misread :)

16:23 Scala: oh, derp

16:23 justin_smith: ,(clojure.string/join "," ["a"])

16:23 clojurebot: "a"

16:24 justin_smith: ,(clojure.string/join ", " ["a" "b"])

16:24 clojurebot: "a, b"

16:24 justin_smith: (pretend I used ", " the first time too, the result would have been the same)

16:25 godd2: He's lying

16:26 justin_smith: :)

16:26 ~justin_smith

16:26 clojurebot: justin_smith sits on a throne of lies

16:27 SegFaultAX: justin_smith: You smell like beef and cheese, you don't smell like justin_smith!

16:28 justin_smith: SegFaultAX: how did you know I had beef tacquitos for breakfast! what witchcraft is this!

16:30 amalloy: justin_smith: you had me worrying it might actually be spelled tacquito

16:31 justin_smith: oh man...

16:32 amalloy: which just makes no sense at all in spanish, but who knows what kind of tragedies english has wrought

16:32 * justin_smith puts on his dunce cap and sits in the corner reading the dictionary.

16:32 Kristien: tacquito programming is tacit programming in Spanish

16:33 amalloy: Kristien: eh?

16:38 crazydiamond: Hi. What's best practice for doing testing in Clojure? Is it better to keep tests (calls to deftest and run-tests) in the same file where functions are or separate one?

16:38 justin_smith: crazydiamond: run-tests shouldn't be in any of your files - use a tool like "lein test" to find and run all your tests

16:38 and put tests in their own test namespaces

16:39 crazydiamond: justin_smith, ok, so, let's say I want to do TDD in vim?

16:39 justin_smith: you can also call run-tests from the repl if you want to do tdd

16:39 devll: (sh "rmdir" "*" :dir "resources/ghosts/output")

16:39 crazydiamond: aha, ok, thanks

16:39 devll: why "*" does not work?

16:41 ** why does not "*" take effect?

16:42 justin_smith: devll: I'm not sure, maybe you explicitly have to tell the shell it spawns to turn globbing on?

16:42 hiredman: * is a shell glob, it is expand by the shell, sh is, despite its name, not actually executing commands via a shell

16:43 justin_smith: hiredman: oh, that would explain it. I was looking at the source but had not gotten that deep yet.

16:43 (inc hiredman)

16:43 lazybot: ⇒ 73

16:43 devll: OK . (inc hiredman) thanks.

16:44 crazydiamond: is there a vim plugin to auto-pretty-indent Clojure code in current buffer?

16:44 justin_smith: devll: yeah, this works here: (sh "sh" "-c" "echo *")

16:45 crazydiamond: yeah, I think there is a vim integration for clj-fmt

16:45 https://github.com/weavejester/cljfmt

16:47 crazydiamond: btw, as long as this is an utility https://github.com/weavejester/cljfmt

16:47 may I install it globally?

16:47 justin_smith: crazydiamond: you may want it as a :plugins entry in ~/.lein/profiles.clj

16:48 crazydiamond: which is exactly what it recommends doing on the readme

16:48 crazydiamond: yep, and what to run afterwards? lein deps while being in my home dir?

16:48 justin_smith: no, deps is always implicit

16:48 devll: thanks . (inc justin_smith)

16:48 justin_smith: and installs are always per-user

16:49 so you can just add it to your :plugins then run "lein cljfmt check" or use the vim binding for it or whatever

16:49 devll: (inc justin_smith)

16:49 lazybot: ⇒ 202

16:49 crazydiamond: aha

16:49 cool, thanks!

16:55 sritchie: ambrosebs: hey

16:55 ambrosebs: around?

17:04 * akkad hunts for anyone who uses apparmor to lock down clojure servers

17:13 profil: I am having trouble with referring a macro, I am doing "(ns my-namespace (:require [gloss.core :as g :refer-macros [defcodec]]))" and then I try to use defcodec directly but getting "Unable to resolve symbol". If i do g/defcodec I can access it. Whats wrong?

17:14 ztellman: profil: as far as I know, :refer-macros is a cljs thing, and Gloss is JVM-only

17:14 justin_smith: yeah, clj will just ignore the :refer-macros key afaik

17:14 profil: ahh that makes sense :D

17:15 so I can just refer a macro as usual then?

17:15 yes, that worked, thanks guys

17:17 crazydiamond: btw, when doing TDD in Clojure, how to struggle with constant problems like "there was some (def foo ...), and after I removed it it appears again". I'm doing :%Eval (in vim plugin fireplace) to run tests (actually I often ant to see just output of some command, not perform test)

17:17 justin_smith: crazydiamond: reloading a namespace does not eliminate defs that are removed from the ns

17:18 crazydiamond: yep, I realized that. so I probably must remove (ns ) form top of the file

17:18 justin_smith: that won't help

17:18 crazydiamond: that a am evaluating

17:18 so, I wonder what's correct way

17:19 justin_smith: crazydiamond: there is a function to remove a var, I am trying to find it (forgot the name)

17:19 crazydiamond: but, isn't there some more general approach?

17:20 like forgetting about what was there just some time before

17:20 I mean, reloading

17:20 justin_smith: clojure.tools.namespace has some stuff for this

17:20 but no, loading the file does not delete definitions

17:20 crazydiamond: I am using this

17:20 (require 'clojure.tools.namespace.repl)

17:20 (clojure.tools.namespace.repl/refresh)

17:21 in the end it would turn so that I would need re-launch repl every time

17:21 which is incorrect and just ugly

17:22 justin_smith: crazydiamond: ns-unmap will delete a var from a namespace

17:22 crazydiamond: thanks, but provided some name...

17:23 justin_smith: ns-publics will give you all vars in a given namespace

17:23 (well, all that are visible outside that namespace)

17:24 crazydiamond: but... aren't there just some best-practices?

17:25 justin_smith: running lein check or lein eastwood will tell you when you have code that reflects definitions that no longer exist

17:26 eastwood is generally helpful, in other ways as well

17:30 crazydiamond: however, doing :%Eval in vim... that should be equivalent of just throwing that bunch of code into REPL?

17:31 justin_smith: right

17:31 within the apropriate namespace context

17:33 Scala: I'm checking program args when running the program. If they fail my check I want to print a line and exit. An if statement only lets me run one action though, and putting both actions in a function with no args doesn't run. What's the proper way to do this?

17:33 justin_smith: do

17:34 (do (println "message") (System/exit 42))

17:34 also, this may be a good place to use when (which like functions contains an implicit do)

17:35 (when we-outta-here-homies (println "bye") (System/exit 42))

17:36 when is if with a do block and only one branch

17:44 Geeky_Vin: Hello Fellow Clojurers! I have a simple doubt could some help me. I have a string, "{\"result\" : \"some value\"}" now How do I convert it to just {result: some value}

17:45 justin_smith: Geeky_Vin: you can use cheshire or clojure.data.json

17:46 wait, that would give you {:result "some value"}

17:46 {result: some value} is not a valid clojure form

17:49 Geeky_Vin: @justin_smith yeah but not if you set the third value as true ;)

17:50 havenwood: Geeky_Vin: Deserialize the JSON?

17:50 Geeky_Vin: oh wait I see what you mean

17:50 but still thats enough for me!

17:50 havenwood: (json/read-str "{\"result\" : \"some value\"}") #=> {"result" "some value"}

17:50 Geeky_Vin: @havenwood yes Haven

17:51 @havenwood but I need to preserve the map value

17:51 in map: form or :map value

17:51 I mean key sry

17:52 i.e key : value or :key value

17:53 havenwood: (json/read-str "{\"result\" : \"some value\"}" :key-fn keyword) #=> {:result "some value"}

17:53 Geeky_Vin: Like that ^ or am I still not getting it?

17:55 Geeky_Vin: @havenwood oh yeah thats better its equivalent to parse-string in cheshire btw

17:55 havenwood: Geeky_Vin: Like the second example here?: https://github.com/dakrone/cheshire#decoding

17:58 Geeky_Vin: @havenwood yeah.

18:01 nicferrier: ,ping

18:01 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: ping in this context, compiling:(NO_SOURCE_PATH:0:0)>

18:04 justin_smith: $ping nicferrier

18:05 nicferrier: justin_smith: :-) - I thought I was in #emacs.

18:05 justin_smith: hmm, I wonder if that plugin broke

18:05 $ping

18:05 lazybot: justin_smith: Ping completed in 0 seconds.

18:06 justin_smith: $ping example.com

18:06 lazybot: justin_smith: FAILURE!

18:12 amalloy: justin_smith: lazybot's website-pinging feature never made much sense to me

18:15 Glenjamin: $ping isup.me

18:15 lazybot: Glenjamin: Ping completed in 0 seconds.

18:16 crazydiamond: Is there way to create new namespace for which result of ns-refers wouldn't be empty and switch to it?

18:16 justin_smith: crazydiamond: ns

18:16 bucketh3ad: I've got a doseq with two side-effect functions that operate over a sequence. What is the best way to change (doseq [s my-seq] (func1 s) (func2 s)) so that it runs ALL func1's first then ALL func2's, rather than in pairs for each element of the sequence?

18:16 justin_smith: or you can manually call clojure.core/refer-clojure within that ns

18:16 amalloy: justin_smith: you know about lazybot's actual useful pinging feature though, right?

18:16 crazydiamond: justin_smith, ok, but given some name?

18:17 amalloy: where you write "amalloy: ping", and lazybot will PM you when he notices me talking in any channel

18:17 justin_smith: crazydiamond: I guess you could use create-ns and refer-clojure, but why do you need to create namespaces at runtime anyway?

18:17 crazydiamond: justin_smith, I want to create ns with random name each time I'm doing :%Eval. that crazy hack

18:17 amalloy: bucketh3ad: you write it as two doseqs

18:18 you want to walk over the seq twice, not walk over it once doing two things, so that's what you have to write

18:18 crazydiamond: justin_smith, 'cause Clojure isn't about updating and deletion. it's about creating new :D

18:19 bucketh3ad: amalloy: Thanks! That seemed like the right path, but I wasn't sure if there was a more idiomatic method.

18:21 amalloy: i mean, you can do some silly business if you want, but it's silly. like just for fun: ((reduce (fn [f s] (fn [] (do (thing1 s) (f) (thing2 s)))) (fn []) myseq))

18:22 which is not quite right since it does like (f1 c) (f1 b) (f1 a) (f2 a) (f2 b) (f2 c)

18:23 bucketh3ad: Yeah, that is pretty silly

18:32 crazydiamond: (eval `(ns ~(gensym)))

18:33 let the testing begin

18:33 akkad: is there away to avoid duplicate function names? some dev overwrote my function without knowing it.

18:33 no errors popped up anywhere

18:34 Glenjamin: akkad: namespaces?

18:34 akkad: this happens to be the same namespace

18:34 Glenjamin: smaller namespaces? :p

18:34 akkad: just looking for compiler options to assert on this like CL

18:35 Glenjamin: https://github.com/jonase/eastwood might have it

18:35 aha, here we go

18:35 https://github.com/jonase/eastwood#redefd-vars

18:36 akkad: perfect thanks

19:01 Bronsa: ,(. Double -POSITIVE_INFINITY)

19:01 clojurebot: Infinity

19:01 Bronsa: ,(.-POSITIVE_INFINITY Double)

19:01 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: No matching field found: POSITIVE_INFINITY for class java.lang.Class>

19:01 Bronsa: :|

19:02 Glenjamin: doesn't .- only work on instances?

19:02 amalloy: well, evidently that is so

19:02 Glenjamin: weird that (. class -field) works tho

19:03 Bronsa: i'm not sure that the failing case is intentional

19:03 Glenjamin: ,Double/POSITIVE_INFINITY ; is the recommended way though?

19:03 clojurebot: Infinity

19:04 amalloy: yes

19:04 Bronsa: Glenjamin: sure but that should just be sugar over .

19:05 amalloy: Bronsa: it is

19:06 it's sugar over (. Double POSITIVE_INFINITY), with no -

19:09 Bronsa: amalloy: I cannot read anywhere that the .- field access syntax should not work for static fields and should only work for instance fields

19:09 so I think it should be reasonable to expect (.-POSITIVE_INFINTY Double) to work

19:11 wrt (. foo -bar) behaving like (.-bar foo), no idea if that's by design but it's definitely supported by both clj and cljs and cljs explicitely uses it

19:11 so I just always assumed it was intentional

19:12 amalloy: i imagine in cljs both forms work, right?

19:12 Bronsa: yeah, in clj too

19:12 ,(deftype x [y])

19:12 clojurebot: sandbox.x

19:12 Bronsa: ,(.-y (x. 1)

19:12 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

19:12 Bronsa: ,(.-y (x. 1))

19:12 clojurebot: 1

19:13 Bronsa: ,(. (x. 1) -y)

19:13 clojurebot: 1

19:15 blake_: OK, so, I'm catching exception in some code, the idea being to catch all the exceptions and return them as a seq.

19:15 But what happens instead is I'm eating them. Or at least some of them. java.lang.NullPointerException in particular.

19:16 It actually looks like other exceptions are returned. Since I'm not discriminating, I don't see how it can happen.

19:17 I have some code https://www.refheap.com/98037 but I'm not sure how instructive it is.

19:17 zengy: exit

19:18 blake_: Maybe it's eating them all and the code just doesn't build the error list I think it's building. (I make a vector out of the exceptions and return that.)

19:30 Eh. Maybe just rewrite the code so it's easier to debug. =/

19:32 justin_smith: blake_: ##(key nil)

19:32 lazybot: java.lang.NullPointerException

19:32 justin_smith: blake_: via that specific circumstance (which I think could absolutely happen), you get an exception that breaks out of your catch block

19:32 and does not get added to the vector of caught exceptions

19:34 blake_: another factor here is ##(dorun (map inc (range 1000)))

19:34 lazybot: ⇒ nil

19:34 blake_: justin_smith: Interesting. It shouldn't be possible here but that's a good sign that I wouldn't be looking for it.

19:34 justin_smith: because dorun returns nil, you will never see the results of that keep function

19:35 blake_: justin_smith: OK, did the dorun....crap...

19:35 justin_smith: including the vectors created by catch

19:35 blake_: Well, that explains THAT.

19:35 justin_smith: you probably want doall

19:35 blake_: (inc justin_smith)

19:35 lazybot: ⇒ 203

19:35 blake_: Holy crap! I missed your bicentennial!

19:35 justin_smith: haha

19:36 blake_: I had cake planned and firecrackers...

19:36 patchwork: blake_: It was quite an event, we were wondering where you were

19:37 blake_: Debugging!

19:37 patchwork: I tried to save you some cake but... you know these monsters

19:39 blake_: I'll set the building on fire.

19:45 ##(key nil)

19:45 lazybot: java.lang.NullPointerException

21:22 emaczen: What is wrong with this multimethod form?

21:23 (defmulti pushable? :Pile :Pile)

21:23 justin_smith: why do you list the dispatch twice?

21:23 emaczen: I want to dispatch on two "piles"

21:23 justin_smith: that's not how defmulti works

21:24 (doc defmulti)

21:24 clojurebot: "([name docstring? attr-map? dispatch-fn & ...]); Creates a new multimethod with the associated dispatch function. The docstring and attr-map are optional. Options are key-value pairs and may be one of: :default The default dispatch value, defaults to :default :hierarchy The value used for hierarchical dispatch (e.g. ::square is-a ::shape) Hierarchies are type-like relationships that do not depend upon type inheritance. By default Clo

21:24 emaczen: Okay, so I have to make a different dispatch function

21:24 justin_smith: what do you expect to dispatch on?

21:24 two args?

21:25 emaczen: Yes

21:25 justin_smith: (defmulti pushable? (fn [a b] [(:Pile a) (:Pile b)])) maybe

21:25 that would treat each order pair of :Pile as a separate dispatch

21:26 emaczen: justin_smith, thanks that is what I am looking for

21:28 justin_smith: you could also make the dispatch function varargs if you wanted other arities to be acceptable

21:36 emaczen: what is the function for pushing/appending an element to a collection?

21:39 justin_smith: emaczen: push (for vectors)

21:39 TEttinger: (doc conj)

21:39 justin_smith: no such function for lists

21:39 clojurebot: "([coll x] [coll x & xs]); conj[oin]. Returns a new collection with the xs 'added'. (conj nil item) returns (item). The 'addition' may happen at different 'places' depending on the concrete type."

21:39 amalloy: justin_smith: ...

21:39 conj, not push'

21:39 justin_smith: conj

21:39 that was a weird brain fart...

21:39 sorry

21:39 TEttinger: haha

21:40 justin_smith: ~justin_smith

21:40 clojurebot:

21:40 amalloy: *chuckle*

21:40 TEttinger: ,(def ☃ conj)

21:40 clojurebot: #'sandbox/☃

21:40 TEttinger: ,(☃ [1 2 3] 4)

21:40 clojurebot: [1 2 3 4]

21:40 amalloy: ~amalloy

21:40 clojurebot: amalloy is nuts for juxt

21:41 TEttinger: clojurebot: TEttinger |is| putting BOMs in all your strings while you sleep

21:41 clojurebot: Ok.

21:43 emaczen: so conj for vectors but nothing for lists?

21:43 TEttinger: conj for vectors at the end, conj for lists at the start

21:43 amalloy: emacsnw: conj adds to a collection in "the natural place", which is different for each kind of collection

21:43 for vectors, it's at the end

21:43 TEttinger: if you want to attach to the end of a list, that's the worst case for lists, but you can use ##(concat '(1 2 3) [4])

21:43 lazybot: ⇒ (1 2 3 4)

21:44 TEttinger: concat appends sequences

21:44 which includes lists and vectors and even maps

21:44 justin_smith: and you can fake something similar with into for prepending on a vector (once again, worst case)

21:45 ,(concat "hello" "world")

21:45 clojurebot: (\h \e \l \l \o ...)

21:45 justin_smith: :P

21:45 TEttinger: ##(concat '(1 2 3) {:☃ 4})

21:45 lazybot: ⇒ (1 2 3 [:☃ 4])

21:45 TEttinger: ##(concat '(1 2 3) {:☃ 4 :☃☃☃ 10})

21:45 lazybot: ⇒ (1 2 3 [:☃☃☃ 10] [:☃ 4])

21:46 TEttinger: note how maps aren't ordered and get split into key-value pairs when treated as a seq

21:51 emaczen: what is pop!

21:52 justin_smith: it's like pop, but for transients

21:52 or as we like to call it, hobo soda

21:52 emaczen: You beat me to the next question -- what are transients?

21:52 justin_smith: optimized data structures for updating, if you don't need to access the older values

21:53 when you are done punching them you can turn them into normal persistent data structures with persistent!

21:53 emaczen: Is there anything like (push (pop l1) l2)

21:54 justin_smith: well, it would be conj or into

21:54 not push

21:54 TEttinger: so, you wouldn't change the value of l1 there because lists are immutable

21:55 emaczen: What can I do to get this functionality?

21:55 TEttinger: ,(conj '(2 3) (head '(1 2 3)))

21:55 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: head in this context, compiling:(NO_SOURCE_PATH:0:0)>

21:55 TEttinger: ,(conj '(2 3) (first '(1 2 3)))

21:55 clojurebot: (1 2 3)

21:55 justin_smith: TEttinger: peek works on lists

21:55 amalloy: justin_smith: but not seqs in general, sadly

21:55 justin_smith: right

21:56 amalloy: it's one of the few reasons list? isn't totally useless

22:00 justin_smith: ,(map #(instance clojure.lang.IPersitentStack %) [[] () (iterate inc 0) (range) {}])

22:00 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: instance in this context, compiling:(NO_SOURCE_PATH:0:0)>

22:00 justin_smith: oops

22:00 ,(map #(instance? clojure.lang.IPersitentStack %) [[] () (iterate inc 0) (range) {}])

22:00 clojurebot: #<CompilerException java.lang.ClassNotFoundException: clojure.lang.IPersitentStack, compiling:(NO_SOURCE_PATH:0:0)>

22:00 justin_smith: ,(map #(instance? clojure.lang.IPersistentStack %) [[] () (iterate inc 0) (range) {}])

22:00 clojurebot: (true true false false false)

22:18 emaczen: why can't I pop a lazySeq?

22:18 What can I do to a lazySeq?

22:20 TimMc: emaczen: "rest" gives you the lazy seq minus the head, and if that's not pop, I don't know what is

22:21 emaczen: TimMc: THanks

22:21 TEttinger: if you want one element, first or nth, if you want a different lazyseq, rest

22:21 emaczen: (swap! state update-in :deck rest)

22:21 UnsupportedOperationException nth not supported on this type: Keyword clojure.lang.RT.nthFrom (RT.java:857)

22:21 TimMc: There's also "next", but that's only if you want an empty result to be expressed as nil, not ().

22:21 amalloy: [:deck]

22:21 emaczen: Here (:deck @state) is a lazySeq

22:22 I'm not sure why I can't use rest in this context

22:22 amalloy: emaczen: [:deck], not :deck

22:22 it's entirely unrelated to lazy seqs, you are using update-in wrong

22:23 TEttinger: update-in takes a vector of things to go "in" to

22:23 emaczen: why do I have to use the []?

22:23 Okay, I see

22:23 amalloy: &(doc update-in)

22:23 lazybot: ⇒ "([m [k & ks] f & args]); 'Updates' a value in a nested associative structure, where ks is a sequence of keys and f is a function that will take the old value and any supplied args and return the new value, and returns a new nested structure. If any levels do not exist, hash-maps will be created."

22:23 emaczen: Thanks TEttinger

22:23 TEttinger: np!

22:23 emaczen: I'm still getting used to the documentation...

22:24 amalloy: i think clojure 1.7 is going to include an update function, which would behave like you imagined update-in does

22:24 but i haven't been paying attention to that plan for a while

22:28 ob_: learned about the first thread macro (`->) tonight and it made me happy :)

22:28 thread first rather lol

22:30 TEttinger: it's a good one!

22:30 ob_: i can't believe ive been more than one tutorial deep without learning about it

22:31 "Hey world, clojure is like hacking on linux. See, we have pipes in the form of arrows!"

22:32 emaczen: how many functions warrants a thread first ?

22:32 gfredericks: two?

22:32 raspasov: ob_: also take a look at https://clojuredocs.org/clojure.core/some-%3E , it can be useful in some cases

22:32 justin_smith: 3

22:32 gfredericks: I'll sometimes use cond-> and some-> with just one

22:32 emaczen: is there a general consensus?

22:32 amalloy: that's the wrong question to ask

22:33 there's not some "cost" to having nested parentheses that -> alleviates, and above a certain level you need -> to survive. you use -> whenever that lets you rearrange your code into an order that's more readable

22:34 TEttinger: I just use (((((((((((((((((())))))))))))))))))))

22:34 ob_: -> makes reading clojure to a newbie like me totally sane now

22:34 -> is clojure's secret weapon and it doesnt even know it

22:34 TEttinger: heh, it's true

22:36 raspasov: but the BEST jedis, they only code in nested (). why? because they can see the future :)

22:37 amalloy: huh?

22:37 raspasov: lol I'm kidding

22:37 because if you don't use -> the code is backward, i.e. you need to be able to see "forward" in time to understand it lol

22:38 amalloy: i don't get the "code is backward" argument. we talk that way in english all the time. verb the noun. verb and verb the adjective noun

22:39 raspasov: maybe "inside out?

22:39 amalloy: is "drive the car" inside out?

22:39 justin_smith: amalloy: but in reverse application order, where the last verb is the first applied?

22:39 amalloy: i love -> at least as much as the next guy, but so many of the arguments for using it don't make any sense

22:40 justin_smith: I sleep after I walk home after I go out with some friends after I work after I get up and have coffee

22:40 raspasov: haha

22:40 justin_smith: that's how outside in can read

22:41 ob_: (z(y(x))) vs (-> x y z)

22:41 pretty damn easy call

22:41 for the uninitiated at least

22:41 raspasov: http://www.yodaspeak.co.uk/index.php

22:43 ob_: The #1 complaint i see on every thread about clojure ever is "omg parens". Only today did I see a comment about thread first macro halfway down the page.

22:43 raspasov: ob_: the correct macroexpand for this case would be (z (y x)), but I totally agree with you

22:44 (macroexpand-1 '(-> x y z))

22:46 puredanger: I think -> is great when there is some consistency to the results flowing through the forms (sequences, collections, etc)

22:46 I'm less a fan when the kind of thing being threaded changes in every line

22:46 although occasionally I see it used to good effect

22:46 justin_smith: if it has an assembly-line like logic to it

22:47 raspasov: puredanger: totally agree, I can't count how many times I've done this and then you have to "deconstruct" your code to actually debug/undestand what's going on lol

22:47 justin_smith: my two best use cases are successive transformations that keep the same basic structure, or nested lookup (when get-in just doesn't suffice)

22:47 puredanger: yes, exactly

22:47 ob_: I don't know where -> doesn't make sense to use, but as a PR move to get people interested in clojure, it's amazing imo. It copmletely disarms the "omg parens" crowd

22:47 justin_smith: ob_: yeah, less parens than java

22:48 puredanger: objection to parens is, as we know, silly. but it's also real.

22:48 ob_: then again do you want people in the community that will ignore all the goodness bc of parens?

22:48 i think the benefits outweigh tho. if nothing else, you destroy the #1 barrier to entry

22:48 puredanger: I don't want to think that way

22:49 raspasov: we should just fork Clojure and make it like Python, that will solve all of the world's problems

22:49 ob_: yea me either im not into that "pain is good" stuff

22:49 justin_smith: ob_: yeah, actually my first response to "omg parens" is usually "they are a cost of entry, and it's worth it" - if someone still can't handle the parens, that's their loss

22:49 puredanger: I want to find ways to have people put that reactive fear aside long enough to notice everything else

22:49 justin_smith: raspasov: at that point you just have ml without the static typing

22:49 ob_: show them parens and say "if this freaks you out, you can use -> this way:"

22:49 parens first, -> second

22:50 raspasov: justin_smith: and without the JVM?

22:50 locks: can I compile a clojure library into a jar and use it from Java in Android?

22:51 justin_smith: raspasov: well, who says an ml can't compile to the jvm, I'm just saying that's what the language you end up with would effectively be (once you have immutability, and indentation for nesting)

22:51 amalloy: ob_: -> doesn't even reduce the number of parens except in the absolute least interesting case

22:51 justin_smith: amalloy: it reduces the depth of them though

22:51 amalloy: (-> foo (f x) (g y) (h z)) vs (h (g (f foo x) y) z)

22:52 locks: -> is bad? D:

22:52 amalloy: that's clearly better-written with ->, but not because of number of parens or depth of anything

22:52 it's because the extra arguments pertaining to h (here, z) are next to h instead of on the opposite side of the expression

22:52 ob_: the mental strain of going inside out is significant for a newbie

22:52 like myself

22:52 although at day 7 im getting the hang of it

22:52 raspasov: amalloy: in nested maps it's nice like (-> deep-nested-map :lvl-1 :lv-2)

22:52 ob_: but -> as "linux piping" is a freaking revelation

22:53 amalloy: raspasov: that should be get-in anyway

22:53 raspasov: yea that's also possible

22:57 ob_: is there really much interop with java in real world clojure

22:58 it almost always reads as a half-hearted benefit rather than something ppl actually do

22:58 raspasov: ob_: depends on what you're doing, if you need an existing java library that does not have a read clojure wrapper, then yes

22:58 justin_smith: ob_: I use it plenty

22:58 ob_: it comes up more when you need a lib for a specific pragmatic thing

22:58 raspasov: or if you need to use classes like ByteBuffer or other lower-level Java utils

22:58 justin_smith: it's often easier to just use the java lib for it

22:59 ob_: oh ok

22:59 justin_smith: also, IO tends to be very interop-heavy, beyond the super-basics

23:00 ob_: for abstract and algorithmic stuff outside a tight loop, yeah, you won't see interop. But for specific utilities or places where you need performance interop will pay off.

23:01 amalloy: it's also easier to work in a mixed team of clojure programmers and infidels if you can just say "okay, we'll write up an interface, and i'll give you an object that implements that interface"

23:01 ob_: lmao infidels

23:02 im guessing clojure programmers are java experts first

23:02 amalloy: some of them

23:04 justin_smith: ob_: you should see what he does with apostates

23:04 it isn't pretty

23:04 ob_: #isis?

23:04 justin_smith: ob_: I learned java after clojure

23:05 ob_: my dayjob is sql+asp.net mvc

23:05 but i sneak in some clojure reading

23:05 justin_smith: ob_: have you checked out clojure-clr?

23:05 ob_: ive heard about it

23:05 justin_smith: it's not as mature, but it has the advantage of using an ecosystem you know better

23:06 ob_: im not heavily invested in clr personally

23:07 justin_smith, do you use clojure at work?

23:08 justin_smith: ob_: yeah, I do contract work, back end for web sites in clojure

23:09 ob_: cool

23:14 justin_smith: is there a name for that thing Microsoft does where they give a super generic name to software? "windows" "sql server" "mvc"

23:16 ob_: a marketing term?

23:17 justin_smith: it's like, attempting to capture the generic term / concept so people will think it implies their version maybe?

23:19 ob_: sounds like branding

23:19 the windows brand, sql brand, etc

23:19 sql server rather

23:19 justin_smith: right

23:20 it's like the reverse of the kleenex effect - instead of their own brand becoming generic, the generic thing becomes their brand

23:21 ob_: interesting

23:22 but i dont know if ms advertises Windows. Don't they always through version numbers to imply you need to upgrade to the new version?

23:23 *Don't they include version numbers

23:24 justin_smith: yeah

23:25 ob_: funny how apple went with OS X which sounds like some mainframe

23:25 while MS went with something kinda creative with Windows

23:25 as far as names go

Logging service provided by n01se.net