#clojure log - Dec 09 2015

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

0:00 dongcarl: justin_smith: wow... clojure syntax is tricky...

0:00 justin_smith: owlbird: eval is like riding a sherman tank down the block to get a soda from the convenience store two buildings away

0:00 owlbird: The fun will be given to :row-fn while querying data from db.

0:00 justin_smith: owlbird: maybe you just want identity

0:00 ,(identity 42)

0:01 clojurebot: 42

0:02 owlbird: no, it's just a sample code, there may be many styles, each one will has its row-fn to format the result-set

0:02 justin_smith: owlbird: why would you call eval?

0:03 owlbird: if no style fun was found, just return the original value

0:03 justin_smith: owlbird: eval is like the worst possible way to return the original value, replace it with identity

0:03 that's what I was saying

0:03 also if you give eval a list with symbols you probably wouldn't like the result

0:04 owlbird: oh... I got you

0:04 many thx

0:06 justin_smith: owlbird: eval is for compiling code, it just happens to act like identity for inputs that are not lists

0:06 or symbols

0:21 dongcarl: justin_smith: question, when it calls one of the defmethods, is the argument the same as the argument for defmulti or is it ch?

0:22 Trioxin: it's too bad this doesn't seem to be actively developed anymore https://github.com/arcadia-unity/Arcadia

0:27 justin_smith: dongcarl: it gets the same argument the dispatch function did

0:31 Trioxin: what would one use in terms of an engine to begin game dev in clojure?

0:33 dongcarl: justin_smith: can you help me understand what's going on here: https://github.com/shaunlebron/parinfer/blob/master/lib/src/parinfer/reader.cljc#L95

0:33 or anyone really

0:33 here's what a "state" usually looks like https://github.com/shaunlebron/parinfer/blob/master/lib/src/parinfer/indent_mode.cljc#L19

0:34 it's calling (select-keys state [:x-pos :ch]), but state doesn't have keys :x-pos or :ch

0:34 stack does

0:34 so is it just zeroing out the values in stack using conj?

0:37 ridcully: Trioxin: libgdx has a wrapper: play-clj

0:39 Trioxin: depending on the kind of game you plan, something like quil could be enough. also consider clojurescript

2:55 visof: hi guys

2:56 what is the best effiecient way to read multiple url in parallel?, what i know is make each one in future then use @ for all is this the right solution?

3:16 Guest53639: %CLEAR

3:16 CLEAR

3:23 riceandbeans: why does hello world take 13.28 seconds to run?

3:24 visof: riceandbeans: that's jvm

3:24 riceandbeans: you run it as jar?

3:25 riceandbeans: use lein uberjar to get the jar

3:25 amalloy: it's not the jvm, it's lein

3:26 visof: amalloy: why lein get all of this time?

3:27 amalloy: because it loads a bunch of crap, does a bunch of scanning the classpath? i don't know exactly

3:29 riceandbeans: good god

3:29 22 seconds to build a hello world jar

3:30 ok, so java jar hello world takes 5.21 seconds

3:30 still less than awesome

3:31 yes, I'm totally judging your language based on hello world

3:37 visof: riceandbeans: https://github.com/technomancy/leiningen/wiki/Faster

4:30 owlbird: why do the clojure.jdbc functions like db-do-prepared, update!, delete! return a seq, while the original jdbc API return int

4:50 Gamer-Pro: Hello Guys

4:50 Download this game from here

4:50 http://www.indiedb.com/games/spaceshooter-x1/downloads/spaceshooter-x1-update-for-windows

4:50 This game is the best game of the world

4:55 BRODUS: anyone know what version of clojure 4clojure uses ?

4:57 powered: 1.6 I think or lower

4:57 because some 1.7 functions don't work

5:06 BRODUS: powered: thanks. I think its at least lower than 1.5 since its not recognizing reduced.

5:36 jonathanj: if anyone has some time to spare on some code golf, it would be appreciated: https://pb.codehash.net/5276b95b8f404573b3ff1db95717e4ca

6:06 parsing_clj: Hi there! I want to write a parser and im using insta parse

6:07 this is my grammar so far ,modified from the README: http://pastebin.com/3wqcZzLc

6:08 I want to parse **THIS IS A HEADLINE**, the same as ** THIS IS A HEADLINE **

6:08 so basically ignore the white spaces, does anyone knoe how to do that?

6:11 ARM9: parsing_clj try '**' for head

6:11 parsing_clj: ARM9: ok

6:15 ridcully: jonathanj: the merge looks fine to me. i'd extract that interop chain into something nicely named

6:22 visof: parsing_clj: you use trim first

6:22 ,(trim "** THIS IS A HEADLINE **") parsing_clj

6:23 clojurebot: #error {\n :cause "Unable to resolve symbol: trim in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: trim in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6704]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve symbol: trim in this co...

6:23 visof: ,(clojure.string/trim "** THIS IS A HEADLINE **") parsing_clj

6:23 clojurebot: "** THIS IS A HEADLINE **"

6:23 visof: oh

6:24 ARM9: what did you have in mind?

6:24 visof: parsing_clj: you can use tokens lib stanfordnlp

6:24 ARM9: it'd be nice if instaparse had some sort of tokenizer

6:25 visof: stanford-talk has very good example process-text

6:25 l1x: hi guys

6:25 i am trying to use this java lib in clojure http://basho.github.io/riak-java-client/2.0.1/com/basho/riak/client/api/RiakClient.html#newClient(java.net.InetSocketAddress...)

6:26 https://gist.github.com/l1x/98a242724dc5762c0677

6:26 owlbird: how to display method name in logs while using tools.logging with log4j

6:26 l1x: i was wondering why i could not pass in an InetSocketAddress

6:27 owlbird: I use the %M pattern, but all methods was shown as "invoke"

6:27 visof: have you (import '[com.basho.riak.client.api RiakClient])

6:27 ?

6:27 l1x: yes

6:28 it says no matching method

6:28 what does ... mean in java? isnt that a linkedlist?

6:28 ARM9: probably varargs

6:29 visof: l1x: RiakClient.newClient("","",""); but you pass b

6:29 is it working with this example?

6:29 l1x: no this is the java way

6:30 (RiakClient/newClient 10017 (java.util.LinkedList. '("" )))

6:30 the clojure version works

6:30 i am wondering what is addresses

6:30 or how could i figure out its type

6:32 schmir: l1x: you need to pass something like (into-array java.net.InetSocketAddress [...])

6:32 (as the only argument)

6:33 l1x: schmir: thanks!

6:35 schmir: how would you do that? (into-array (InetSocketAddress. "" 10017)) Don't know how to create ISeq from

6:36 (RiakClient/newClient (into-array [(InetSocketAddress. "" 10017)]))

6:36 like this :)

6:36 thanks!

6:37 schmir: (into-array java.net.InetSocketAddress [(java.net.InetSocketAddress. "foo" 3123)])

6:44 jonathanj: so ring.util.io/piped-input-stream uses a nested future to do it's thing

6:44 Source: https://github.com/ring-clojure/ring/blob/1.4.0/ring-core/src/ring/util/io.clj#L11

6:45 the problem with that is that anything that goes wrong in `func` goes completely unnoticed and unhandled

6:47 would it make sense to do something like: (let [rethrow #(throw %)] (piped-input-stream (fn [output] (try (... some code ...) (catch Exception e (rethrow e))))))?

6:48 is it possible to attach a listener that is executed when a future is realized?

6:49 deref-ing a future without knowing if it's going to block or not is not ideal

6:52 tdammers: if you don't want it to block, then maybe a future isn't the right primitive to use?

6:55 jonathanj__: tdammers: what are my other options?

6:57 tdammers: well, you could roll your own code using atoms and lambdas

6:58 but (realized? f) would probably fit the bill

6:58 i.e., only deref the future if realized? says it's ready

7:41 jonathanj: tdammers: i guess the question then is what do you do if it's not realized by the time you test it?

7:43 tdammers: jonathanj: well, what *can* you do? fail hard, or mitigate. It depends on what you want it to do in that case

7:43 jonathanj: there's a third choice: wait some more

7:43 tdammers: I'd file that under "mitigate"

7:44 but yeah

7:44 jonathanj: i see manifold can coerce futures to deferreds, which means i can use (chain) add a callback

7:44 tdammers: another option would be to restructure your code such that the part that blocks on the future runs in a separate thread

7:44 jonathanj: it's kind of annoying there isn't anything in the core library that is effectively (wait-for-this-dereffable-then-do derefable f)

7:45 i suppose it's probably a lot of complexity

7:49 l1x: how can i translate the chained java methods to Clojure the easiest? new StoreValue.Builder(riakObject) .withLocation(location)

7:49 .withOption(Option.W, new Quorum(3)).build();

7:49 (.something (.withOption ....) right?

7:50 there is the .. macro

7:54 jonathanj: i think: (.. (StoreValue.Builder. riakObject) (withLocation location) (withOption Option/W (Quorum. 3) build)

7:54 l1x: nice!

7:54 thanks jonathanj

7:54 jonathanj: i missed a ) before the last build

7:55 l1x: isnt StoreValue.Builder supposed to be StoreValue/Builder?

7:55 jonathanj: i don't know, possibly, it kind of depends on what it is

7:56 if it's a static, then yes

7:56 l1x: thank you

7:56 jonathanj: if it's an inner class then it gets a bit hairier

7:57 i think you basically turn the . into $ for inner classes

7:57 http://blog.jayfields.com/2011/01/clojure-using-java-inner-classes.html

7:57 l1x: huh, never done that

7:58 i am trying out

8:00 jonathanj: from the docs, it looks like it is an inner class

8:00 so you need to import StoreValue$Builder and address it like that

8:07 l1x: https://gist.github.com/l1x/f78b129367a1a6ce80b3

8:07 like this?

8:08 jonathanj: yes

8:09 l1x: cool now i need to figure out how to chain them

8:10 store (.build (.withLocation riak-location (StoreValue/Builder. riak-object)))

8:10 something like that

8:10 jonathanj: the name is StoreValue$Builder

8:10 l1x: this works -> (StoreValue$Builder. riak-object)

8:11 jonathanj: you can use .. to pull that structure inside out

8:11 l1x: yes

8:12 (.withLocation (StoreValue$Builder. riak-object) riak-location)

8:12 this also works

8:12 yenda: Does it make sense if I have a clojure app to build a cljs interface for it ?

8:12 l1x: jonathanj: yeah

8:14 jonathanj: i'm assuming withLocation mutates the object and returns `this`, in which case (doto) might also be useful

8:15 gfredericks: doto doesn't need the object to be returned

8:15 methods that return `this` can be used with ->

8:16 jonathanj: what i meant was: since the return value is always the same object you can use doto instead of .. to chain the calls

8:16 l1x: https://basho.github.io/riak-java-client/2.0.0/com/basho/riak/client/api/commands/kv/StoreValue.Option.html

8:16 jonathanj: which gives you a bit more flexibility because if you have something that is not part of a chained call, you can put it in your (doto) form, whereas with (..) you need to start a new form

8:17 l1x: i guess i need to import this

8:17 with the $ way

8:17 jonathanj: gfredericks: my experience with Java interop is that -> is not often useful because the order of the arguments wobbles around a lot

8:18 but i guess those chained calls would work perfectly well

8:22 ridcully: also doto would not return the build-result, but the builder?

8:24 jonathanj: yeah, that's true

8:24 how the heck does (is (thrown? ...)) work?

8:25 luma: it's magic

8:25 jonathanj: i went looking for a function `thrown?` and found nothing, then read the docs for clojure.test

8:26 l1x: jonathanj: thank you very much for your help

8:26 it works! :)

8:26 https://gist.github.com/l1x/f78b129367a1a6ce80b3

8:26 luma: the is-macro checks if the first item of the list is 'thrown?, and acts accordingly if it is

8:26 l1x: do you think I should rewrite it using the .. ?

8:26 jonathanj: how do i use thrown? with ex-info?

8:27 l1x: or -> like gfredericks suggested

8:27 luma: well, the only thing you can check is if an exception of a specific class is thrown

8:27 or specific class and message with thrown-with-msg?

8:27 jonathanj: luma: yeah... (ex-info) kind of hides that from me

8:28 luma: ex-info creates an exception of class ExceptionInfo, you can check for that

8:28 jonathanj: can i test the info on an ex-info?

8:28 luma: no

8:28 jonathanj: so i guess i write my own (try)

8:29 luma: or yes, but then you have to manually catch it with (try ... (catch ExceptionInfo ex ...))

8:30 jonathanj: i think maybe it's time to use midje

8:31 l1x: thanks

8:32 jonathanj: l1x: :)

8:45 BRODUS: any ideas why this simple try catch block isn't working

8:45 (try (keys [1 2 3]) (catch Exception e (println "error")))

8:45 opqdonut: ,(keys [1 2 3])

8:45 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.Long cannot be cast to java.util.Map$Entry>

8:45 BRODUS: right, I expect it to fail

8:46 opqdonut: I just checked what the exception is

8:46 an Error wouldn't get caught, but it's an Exception

8:46 beaky: ,(try (keys [1 2 3]) (catch Exception e (0)))

8:46 clojurebot: beaky: I don't understand.

8:46 beaky: :(

8:47 opqdonut: (0) is wrong anyway

8:47 beaky: ,(try (keys [1 2 3]) (catch Exception e (nil))))

8:47 clojurebot: beaky: Cool story bro.

8:47 BRODUS: Caused by java.lang.IllegalArgumentException

8:47 Can't call nil

8:47 opqdonut: beaky: you have one ) too much

8:48 BRODUS: very interesting

8:48 it indeed doesn't work

8:48 ARM9: contemplate why (nil) is erronous

8:49 opqdonut: BRODUS: ah, I know, keys returns a lazy sequence!

8:50 for some reason (doall (keys [1 2 3])) doesn't help though

8:50 but e.g. (first (keys [1 2 3])) does work

8:50 ,(try (first (keys [1 2 3])) (catch Throwable e :error))

8:50 clojurebot: opqdonut: I don't understand.

8:50 BRODUS: i understand lazy sequences mostly, but its not clear why thats the reason its failing

8:50 opqdonut: clojurebot has probably banned try-catch

8:51 luma: because it's a lazy sequence, the error isn't thrown inside the try

8:51 opqdonut: the error is thrown when somebody tries to use the result

8:51 luma: the lazy sequence is returned out of the try, and the error is thrown when that lazy sequence is later realized

8:51 opqdonut: ,(do (keys [1 2 3]) 1)

8:51 clojurebot: 1

8:51 opqdonut: see, no error

8:52 ,(do (first (keys [1 2 3])) 1)

8:52 clojurebot: #error {\n :cause "java.lang.Long cannot be cast to java.util.Map$Entry"\n :via\n [{:type java.lang.ClassCastException\n :message "java.lang.Long cannot be cast to java.util.Map$Entry"\n :at [clojure.lang.APersistentMap$KeySeq first "APersistentMap.java" 166]}]\n :trace\n [[clojure.lang.APersistentMap$KeySeq first "APersistentMap.java" 166]\n [clojure.lang.RT first "RT.java" 660]\n [clojure....

8:52 opqdonut: ,(do (doall (keys [1 2 3])) 1) -- I have no idea why this doesn't break though

8:52 clojurebot: 1

8:54 MJB47: doall is only used for side effects

8:54 it returns nill iirc

8:54 while first returns the value

8:54 opqdonut: MJB47: doall should still realise the sequence and give me the error

8:55 ,(doall (map #(/ % 0) [1 2 3])) -- e.g.

8:55 clojurebot: #error {\n :cause "Divide by zero"\n :via\n [{:type java.lang.ArithmeticException\n :message "Divide by zero"\n :at [clojure.lang.Numbers divide "Numbers.java" 158]}]\n :trace\n [[clojure.lang.Numbers divide "Numbers.java" 158]\n [clojure.lang.Numbers divide "Numbers.java" 3788]\n [sandbox$eval122$fn__123 invoke "NO_SOURCE_FILE" 0]\n [clojure.core$map$fn__4541 invoke "core.clj" 2625]\n [cl...

8:55 opqdonut: ,(do (map #(/ % 0) [1 2 3]) 1) -- for comparison

8:55 clojurebot: 1

8:56 luma: opqdonut: it's because of how keys works

8:56 dorun/doall just continuously calls next on the sequence

8:57 and KeySeq (which is what implements keys) only actually produces the key when first is called on it

8:57 opqdonut: but clojure sequences are only lazy in the spine, not the values

8:57 luma: not when next is called on it

8:57 opqdonut: oh, KeySeq is special

8:57 bah

8:57 luma: https://github.com/clojure/clojure/blob/clojure-1.7.0/src/jvm/clojure/lang/APersistentMap.java#L165-L171

8:58 opqdonut: thanks

8:58 yenda: Is it possible to have a clojurescript frontend for a clojure program ? is there something simpler than using ring to make them talk to each other ?

8:59 dnolen: yenda: yes. I can't think of anything much simpler than ring etc.

9:01 BRODUS: thanks for the help everyone

9:04 jonathanj: luma: how do actually address ExceptionInfo?

9:05 clojure.lang.ExceptionInfo it seems

9:07 yenda: dnolen: so ring+compojure is the way to go ?

9:07 j-pb: yenda: bidi is nicer when you do cljs as well

9:08 it allows you to share routes between cljs and clj and generate urls from those shared datastructures

9:08 it's much more declarative than compojure

9:08 you can also use a websocket, if you want more real live communication between your ab and it's ui

9:09 but then you are more constrained in terms of browser support

9:09 yenda: j-pb: Browser support is not a problem

9:11 j-pb: setting up a websocket connection is not that hard to do, and it's somewhat nicer than posts

9:11 I'd pick something like sente for that

9:12 dnolen: yenda: there is no "way to go"

9:12 but yes that will work

9:13 powered: you still need ring for Sente

9:14 j-pb: powered: yeah true, but it's a lot less exposed

9:14 powered: true

9:14 yenda: j-pb: I'm not sure I need websockets though

9:15 I just need to call functions that alter structures or have side effects and return results

9:15 powered: if you don't want low latency or server -> client messages then don't use websockets

9:19 yenda: powered: sente could be nice to watch components state I could add it later

9:19 powered: but for now I just want to have a UI to call functions and move stuff in a graph and send it back again to other functions

9:20 powered: right so you need a simple and quick middleware setup?

9:20 sente's good for that too

9:23 yenda: powered: ok, I settled for om frontend-wise so I'm gonna see how it fits with sente

9:24 jonathanj: if the body of a (future) throws, that exception is wrapped in ExecutionException, is it possible to not do that?

9:28 j-pb: jonathanj: you could catch the exception within the future

9:42 QU35t: Fellas

9:42 opqdonut: jonathanj: or you can just unwrap it when forcing the future

9:48 jonathanj: j-pb: i actually want the exception though

9:48 opqdonut: yeah, that's a little bit inconvenient since i'm writing tests for something that returns a future

9:49 on another note, does anyone use cider and midje together? i can't really seem to get the cider test running stuff working with midje

9:58 heero_: Hi, is there a function to reduce over multiple coll ?

9:59 (reduce coll init list1 list2 ...)

10:00 j-pb: heero_: (reduce fn init (map vector col1 col2 col3 ...)) ?

10:00 powered: (remove even? {:a 1 :b 2 :c 3})

10:01 what is the function I'm looking for instead of remove ?

10:02 j-pb: powered: clojure had something like that as a contrib library

10:02 heero_: j-pb: ok thx

10:04 MJB47: wouldnt filter work?

10:05 ,(filter #(even? (second %)) {:a 1 :b 2 :c 3})

10:05 powered: this works: (remove #(even? (second %)) {:a 1 :b 2 :c 3})

10:05 clojurebot: ([:b 2])

10:05 powered: ah yes

10:06 j-pb: ,(remove (comp even? val) {:a 1 :b 2 :c 3})

10:06 clojurebot: ([:a 1] [:c 3])

10:09 j-pb: (apply into ((juxt empty (partial remove (comp even? val))) {:a 1 :b 2 :c 3})

10:09 ,(apply into ((juxt empty (partial remove (comp even? val))) {:a 1 :b 2 :c 3})

10:09 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

10:09 j-pb: ,(apply into ((juxt empty (partial remove (comp even? val))) {:a 1 :b 2 :c 3}))

10:09 clojurebot: {:a 1, :c 3}

10:09 j-pb: srcr

10:10 scnr lol

10:21 kungi: How do I do an &nbsp in hiccup?

10:22 nevermind I found "&nbsp;" :-)

11:03 visof: hi guys

11:15 sdegutis: I don't know why I signed onto IRC and into #clojure. It was just habit I guess.

11:15 So.. um.... hi?

11:20 Shambles_: sdegutis: Hi.

11:20 sdegutis: Hi.

11:20 I take it justin_smith is asleep then?

11:28 Shambles_: sdegutis: I have no idea.

11:28 sdegutis: :)

11:38 WorldsEndless: So, I thought the doseq family of functions ran only as long as the shortest supplied vector, but was proved wrong by(doseq [n (increment 1) v [\a \b \c]] (println n v))

11:38 j-pb: doseeq is like for

11:39 so if you have

11:39 WorldsEndless: So what if I just want to assign a number to each item of another thing (i.e. for file output)

11:39 j-pb: (map vector col (range))

11:39 or (map-indexed vector col)

11:39 I prefer the first, but others would probably disagree

11:40 ,(map vector [:a :b :c] (range))

11:40 clojurebot: ([:a 0] [:b 1] [:c 2])

11:40 j-pb: like this?

11:40 WorldsEndless: I guess with the latter, I'd then be able to extract the index with something like (doseq [[n v] indexed-vector]) ?

11:40 j-pb: why do you want to do that?

11:40 yes, but

11:41 you can force lazy evaluation, with dorun and doall :)

11:41 WorldsEndless: j-pb: Ah, map is the one that truncates on teh shortest, not the comprehensions. Ok

11:41 j-pb: yeah

11:41 the comprehensions will walk sequences later provided for each element before

11:42 ,(for [x (range 3) y (range 3) z (range 3)] [x y z])

11:42 clojurebot: ([0 0 0] [0 0 1] [0 0 2] [0 1 0] [0 1 1] ...)

11:42 j-pb: ,(for [x (range 2) y (range 2) z (range 2)] [x y z])

11:42 clojurebot: ([0 0 0] [0 0 1] [0 1 0] [0 1 1] [1 0 0] ...)

11:44 WorldsEndless: So with the comprehensions, I should avoid infinite sequences, or just position them later?

11:45 rightwards, that is

11:45 j-pb: with doseq don't do infinite sequences

11:45 beause it's eager

11:46 WorldsEndless: I'm guessing that as long as you respect the laziness, (for) should be okay?

11:46 j-pb: with for, you can happily have infinite sequences, but if you have one nothing before it will advance

11:46 yeah

11:46 ,(for [x (range) y (range 2)] [x y])

11:46 clojurebot: ([0 0] [0 1] [1 0] [1 1] [2 0] ...)

11:46 j-pb: however

11:46 ,(for [x (range 2) y (range)] [x y])

11:46 clojurebot: ([0 0] [0 1] [0 2] [0 3] [0 4] ...)

11:47 WorldsEndless: Cool. I'm still not as fluent as I would like to be in laziness

11:47 j-pb: you might as well had written

11:47 ,(for [x [0] y (range)] [x y])

11:47 clojurebot: ([0 0] [0 1] [0 2] [0 3] [0 4] ...)

11:47 j-pb: because it will never get passed the first element

12:22 WorldsEndless: regexp aren't behaving as I expect. Why is #"^" not matching "beginning of line"?

12:23 ridcully: ,(re-seq #"(?m)^\w" "a b c\nd e f")

12:23 clojurebot: ("a" "d")

12:24 WorldsEndless: ooh. ?m is new to me

12:24 is there a doc page for that (googling for regexps is hair-whitening)?

12:25 luma: WorldsEndless, http://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html

12:25 justin_smith: WorldsEndless: all the (?*) flags are documented in the javadocs

12:25 or what luma said

12:27 WorldsEndless: beautiful. That link will come in handy, too. Thanks.

12:42 basic (probably java) question here: I have a dir-path string (not file). If it doesn't exist, I need to create the file. make-parents doesn't seem to do the trick, since it's a dir. What function do I need here?

12:44 Ah. Files.createDirectory

12:45 I learn much more of Java from working in Clojure than I did in years of classes in Java...

13:15 yenda: haha same for me

13:16 and I learned more of Clojure in 3 months than in java in 3 years

13:40 ecmike: Use Clojure to learn Java, use Java to learn Boilerplate

14:15 tolstoy: Learn Clojure to have fun at home, and Java to have someone else decide what and when to do a job-jar task based on a 10-year-old outdated architecture.

14:15 "For 15 years we've known inheritance is a bad way to model your domain." Scribbles: Not a team player. Doesn't get Agile.

14:15 Doesn't understand "the business".

14:15 </rant>

14:16 More positively: I wonder if there's a place for a "lein" like script that uberjars up clojure + that fs library for scripting (if you don't mind slow JVM start up, which I don't).

14:23 justin_smith: tolstoy: it's not the jvm that is slow to start up, it's clojure

14:24 tolstoy: I've got a "clj" script that starts up the repl. Plenty fast for me. I'd love something with some extra file-system utils.

14:25 justin_smith: sure, make a project with the right deps, uberjar, then you can do "java -cp your.jar clojure.main" to get a repl

14:25 you don't even need any main ns or aot for that to work

14:25 tolstoy: Right!

14:25 justin_smith: for bonus points put pomegranate in there too, so that maven deps can be pulled in at runtime

14:26 (if you really need them)

14:26 tolstoy: Exactly. You can have the "mh" of build systems.

14:26 justin_smith: heh

14:26 alive876: hi newbie here, i have a project that "lein run" works "lein test" ok , but when i run "lein repl" i get Var null/null is unbound. the project file and main file are http://pastebin.com/2pWGAP0u and http://pastebin.com/Pn721weh thanks much

14:27 tolstoy: A simple app to build a classpath. Another app to run a repl. Then just compose them. No complicated "boot" thing. ;)

14:28 Really, all you need is something to resolve deps and the rest: bash (or whatever).

14:28 Hm. How do you get the org mode manual inside an emacs buffer? I don't know how to work the help system.

14:28 justin_smith: alive876: I don't know noir but :ns 'jcrit is suspicious - there is no ns called jcrit there

14:29 tolstoy: M-x info

14:29 alive876: ok , ty

14:29 tolstoy: justin_smith Thanks!

14:29 justin_smith: tolstoy: after that you can click the hyperlinks or nav via keyboard

14:30 tolstoy: info is pretty cool - for example incremental search will look into subchapters that aren't visible in the buffer

14:30 and using org, you can create followable links to places in the info system!

14:30 (full circle)

14:31 tolstoy: justin_smith: That's great. I always need to look up in buffer options.

14:31 alive876: (ns jcrit.server

14:33 justin_smith: alive876: right, I was referring to the args to the noir server start. Also, just fyi lib-noir is still maintained, but noir itself is deprecated and they recommend using ring + your routing lib of choice directly

14:34 alive876: ok thanks

14:35 tolstoy: Hm. I always have `:main ^:skip-aot foo.bar`. I wonder if that metadata tag is even needed anymore?

14:35 alive876: but for my edification , this does or doesn't create the jcrit ns?

14:35 i mean (ns jcrit.server

14:35 justin_smith: alive876: no, it creates the jcrit.server ns

14:36 alive876: ok,thanks

14:36 tolstoy: alive876 Try commenting out the (server/load-views ...) form and see if that fixes it.

14:36 rhg135: tolstoy: AFAIK not till lein 3

14:37 For now aot is the default for main

14:37 tolstoy: rhg135: Ah. I've been including that so long, the problem it solved for me has receded into the dim mists of time.

14:37 justin_smith: but if your jar / uberjar isn't meant to be a point click run app, you don't need a :main-ns

14:39 rhg135: Yeah, I guess the maintainers assumed lein 3 would come soon

14:40 The bug report is old

14:41 alive876: <justin_smith> that doesn't seem to work. and at the beginning i keep getting this too:Consider using [enlive "1.0.0" :exclusions [org.clojure/clojure]].

14:46 justin_smith: alive876: that's a separate issue - you are using an old version of enlive which asks for a different version of clojure than your other libs

14:46 noir probably asks for some ancient version of clojure like 1.3 or something

14:47 alive876: it seems a lot of broken tutorials out there

14:47 justin_smith: alive876: yeah, clojure moves a little faster than the google magic that would lead you to the up to date stuff

14:49 but that's just a warning, the real issue is that noir isn't being started up properly. As I mentioned that 'jcrit arg is pointing it to a namespace that doesn't exist, but what does noir actually want that namespace to be, or to have in it?

14:50 alive876: yea, i just looked and the tutorial is 4 years old

14:50 justin_smith: maybe you could find a newer tutorial, maybe one using bidi or compojure instead of noir

14:56 princeso: is there a function to map data like this {:a 1 :b 2} into some complex object like {:c :a :d {:e :a :f :b} } to result in {:c 1 :d {:e 1 :f 2}} ?

14:57 ecmike: tolstoy: just saw your rant, spot on

14:57 clojurebot: Huh?

14:58 justin_smith: princeso: what is the relationship between the inputs and outputs there?

14:58 is it just mapping the vals by your {:a 1 :b 2} ?

14:59 princeso: justin_smith yes

14:59 justin_smith: ,(require 'clojure.walk)

14:59 clojurebot: nil

15:00 justin_smith: ,(clojure.walk/postwalk (fn [o] (if (map? o) (into {} (map (fn [k v] [k ({:a 0 :b 1} v v)]) o)) o)) {:c :a :d {:e :a :f :b} })

15:00 clojurebot: #error {\n :cause "Wrong number of args (1) passed to: sandbox/eval49/fn--50/fn--51"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (1) passed to: sandbox/eval49/fn--50/fn--51"\n :at [clojure.lang.AFn throwArity "AFn.java" 429]}]\n :trace\n [[clojure.lang.AFn throwArity "AFn.java" 429]\n [clojure.lang.AFn invoke "AFn.java" 32]\n [clojure.core$map$fn__4541 invok...

15:00 justin_smith: oops

15:00 ,(clojure.walk/postwalk (fn [o] (if (map? o) (into {} (map (fn [[k v]] [k ({:a 0 :b 1} v v)]) o)) o)) {:c :a :d {:e :a :f :b} })

15:00 clojurebot: {:c 0, :d {:e 0, :f 1}}

15:01 justin_smith: ,(clojure.walk/postwalk (fn [o] (if (map? o) (into {} (map (fn [[k v]] [k ({:a 1 :b 2} v v)]) o)) o)) {:c :a :d {:e :a :f :b} })

15:01 clojurebot: {:c 1, :d {:e 1, :f 2}}

15:01 princeso: omg you rock justin_smith! thanks

15:01 justin_smith: princeso: of course you could name things and make it not a one-liner

15:03 the main tricks there are using postwalk in order to do nested updates, using into {} in order to map over a hash-map and create a new hash-map, and the usage of the hash-map as a lookup function (with the optional not-found value, so that the nested hash-map stil comes through))

15:03 and the key/value destructuring from the map entry tuple

15:04 ecmike: justin_smith: that's really great... do you have any suggestions for learning clojure that well? I find myself doing a lot of thrashing before getting to anything elegant like that

15:04 justin_smith: ecmike: hanging out here and trying to read / recreate /improve the one-liners helps :)

15:05 ecmike: also, there is of course http://conj.io as a reference, and seeing other people's answers on 4clojure

15:05 ecmike: justin_smith: doing that already, wondering if there were any books/sites/etc you recommend

15:05 justin_smith: oh great, I'll check that out

15:05 princeso: justin_smith: thanks for that. am almost new to clojure, so ill figure out how it all works.

15:05 ecmike: bookmark*2

15:06 justin_smith: princeso: as I recommended to ecmike above, conj.io helps - as does the community knowledge here in the channel if you try to follow the discussion

16:07 WorldsEndless: I am segmenting a file into many files based on a regexp; it works if I slurp and use string/split, but this will have problems for large files. How can I make this large-file friendly?

16:09 Is the best way to iterate through the lineseq and check for re-match, and then split and send the splits to the appropriate place?

16:15 jonathanj: i see people talking about using nrepl in production to embed a repl for investigation etc. purposes

16:15 how do you prevent any random person from connecting to your repl?

16:15 justin_smith: WorldsEndless: that seems reasonable, yeah, though you could try variations like reading N bytes followed by cleaning up the odds and ends by combining any left over from the previous (if any) before running the regex

16:16 jonathanj: by default nrepl only allows connections from localhost (which is a good idea), and then you need to use an ssh tunnel to use it from another host

16:16 jonathanj: ah

16:17 any reason not to embed an nrepl in a production server?

16:17 justin_smith: memory overhead I guess - nrepl is pretty easy to launch from an app

16:18 celwell: jonathanj: that's a terrifying sentence. what's the reason, just curious.

16:18 justin_smith: celwell: well we already discussed the fact that it won't be available without a secure connection

16:27 TimMc: celwell: It is both terrifying and incredibly usful.

16:28 jonathanj: We use liverepl instead. The protection is that you have to be the same user who launched the JVM process in order to inject the agent.

16:28 I once tried to add nrepl to an app using drawbridge but I couldn't get password protection working.

16:29 justin_smith: TimMc: my take was that realistically every OS has local holes, and the realistic barrier to enforce is logged in / not logged in, and once logged in you can't prevent escalations

16:30 (though I guess they don't always have to be as easy as they are via nrepl)

16:31 TimMc: Yeah, but there's always a *chance* your kernel is up to date. ;-)

16:31 Heck, if you're inside the datacenter at most shops you're probably as good as in.

16:31 justin_smith: TimMc: kernel, plus userland - there are local exploits via games, random file conversion utilities, libraries...

16:50 TimMc: jonathanj: One downside of liverepl is that it doesn't give you all the nice nrepl features, you just get a raw repl with no line-editing.

16:50 liverepl can load additional jars, so that might be a path through if that's a problem for you

17:06 jonathanj__: TimMc, justin_smith: Thanks for the discussion, I'll do some reading.

17:13 glosoli: Hey what's the name of the some tool that could scan through the project and point out the stuff that is being done unconventionally ?

17:13 celwell: kibit

17:13 justin_smith: eastwood is good for this too

17:15 glosoli: thanks

18:22 irctc: Hi everyone! :)

18:23 WorldsEndless: Hi, irctc

18:23 irctc: I need help with a concept in functional programming paradigm. I have a function that connects to an API and returns an xml file. Then I need to parse that file, extract info from the parsed result, do some calculations etc, etc. Now I want to make my code functionally as pure as possible.

18:24 As things stand now I have a sequential stack of calls that goes all the way back to the connection that relys on each function passing through a user ID with wich to connect to the api in the connection function.

18:24 How do I change this to be more functionally pure?

18:24 Hi WorldsEndless. :)

18:25 I am thinking that a more functionally pure way would be to just call this connection function once and then save the returned xml in a global (def) and then pass that def arround to other pure functions.

18:26 Am I right in approaching this problem that way or is there another way that it should be done?

18:26 WorldsEndless: Interesting. I recently watched Stuart Sierra's talk on functional design patterns that might be of interest to you: https://www.youtube.com/watch?v=etr08mExAI0

18:27 irctc: Using React-based web libraries, the global atom idea is pretty standard

18:28 irctc: What does that mean. Sorry I'm new to functional programming.

18:28 WorldsEndless: irctc: Although I recently had to redo one of my codebases to pass the value around rather than look it up globally, which brought a lot of benefits

18:28 tolstoy: irctc I think the idea is to do all your side-effects at the front (or end), so don't bury the web request in the middle of calculations.

18:29 WorldsEndless: So, Facebook's "React" framework is a popular javascript engine that has proven very powerful in the hands of Clojurians. The clojurescript approaches, like Om or Reagent, rely heavily on that idea of a global Atom

18:29 tolstoy: irctc: Just make the request, then pass the result to pure transforms, then save (or whatever) the result.

18:29 WorldsEndless: Agree with tolstoy

18:29 irctc: tolstoy, my web request goes all the way through my entire algorithm. This makes it very hard to do unit testing as well.

18:30 WorldsEndless: irctc: Just make the request once, as you were thinking, and pass the needed parts around to what needs them

18:30 tolstoy: irctc: Actually making the request is buried in there somewhere?

18:30 justin_smith: if you put it in a def, then you are stuck with only being able to handle one xml file, with pure handlers and no global you can process as many as your computer can handle

18:30 irctc: So, the request should be made up front and then saved in a def?

18:30 WorldsEndless: irctc: you may not need to save it in a def at all

18:30 irctc: Ok, so how do I go about that aproach?

18:31 justin_smith: irctc: how many different xml files would you ever handle? if it's exactly one for the entire lifetime of the app a def may be OK, if you would ever need a second xml file, definitely don't use a def

18:31 tolstoy: irctc: Using a "def" is just an implemenation detail. You could: (let [xml (make-request...)] (save-to-db (transform xml))). No global.

18:31 irctc: >=1

18:31 Nah, I don't use a db here.

18:31 justin_smith: yeah, if 2 would ever happen, a def would just make things more complicated

18:32 irctc: I agree justin_smith. You have a point there.

18:32 tolstoy: irctc: Again, it's just to illustrate that the network retrieval and saving are at the top level, not in the `transform` bit.

18:32 WorldsEndless: So, guys, I'm a bit tangled up on an idea. Spliting one file to many using readers and writers, I open with "with-open [reader ..]" but am not sure how to alternate writing to a current file with writing to a new file when I match my break-regex.

18:33 irctc: So when I do (connection userid) where userid is some number like 123, I get my xml file back. How do I then pass it to pure functions without calling (connection userid) function from other functions?

18:33 justin_smith: The functional concept is that a function given the same args should return the same result. So focus on breaking the task up to stages that are 100% dependent on their arguments.

18:34 irctc: by calling those functions

18:34 tolstoy: irctc: (let [xml (connection userid)] (transform xml))

18:34 justin_smith: WorldsEndless: with loop or reduce you can have a binding that is passed for each item, and when you see that a new output file is needed you pass that along as the new binding

18:35 WorldsEndless: Wait... you can do that with reduce?

18:35 irctc: Ok, the way I have it set up now is I make (top-function-call userid) --calls--> (mid-function-call userid) --calls--> (bottom-function-call userid) --calls--> (connection userid).

18:35 justin_smith: WorldsEndless: something like (reduce (fn [[out-file acc] el] ... [new-out-file new-acc) lines)

18:35 tolstoy: WorldsEndless: Hm. You could use a multimethod? read-line, charaterize it, then pass it to a multimethod, even method of which knows which file to append it to?

18:36 justin_smith: WorldsEndless: the idea being on a given line you know whether to make a new file or not, and that's the file you pass to the processing of the next line

18:36 tolstoy: irctc: Right. I'd reverse that, if you can. Then pass the XML through your other functions as needed.

18:36 irctc: tolstoy, you mean I should do a let [xml (connection userid)] at the top-level-function and then just pass the local xml binding to other calls within the top-level-function?

18:37 tolstoy: irctc: Yes.

18:38 irctc: tolstoy, I think that makes sense. :) Thank you.

18:38 tolstoy: irctc: At least one benefit of that is that when you read each function, the only thing that function can see are the params.

18:38 irctc: Thank you everyone for your help. I'm gona try it this way.

18:38 WorldsEndless: irctc: good luck

18:39 irctc: Well the main benefit for me will be that I'll be able to do unit testing. Right now I would have to rely on an external api call and that's a real mess if you have large xml files.

18:39 Plus debugging is much easier with pure functions.

18:40 tolstoy: irctc: Yes!

18:40 irctc: I think imperative languages have broken me from the start. lol

18:41 justin_smith: irctc: pure functions are just imperative functions that are only allowed to use data that is in the arg list and can only change things that they return

18:41 you end up returning collections more often, for this reason

18:48 irctc: justin_smith: I feel that because of the lessons I learned while using clojure this made me a better imperative programmer. The notion of pure functions is just not enforced that much from the get go in imperative paradigm. I actually wish I was taught a functional language first before imperative languages.

18:49 justin_smith: irctc: only using arg lists and returning data instead of modifying it are good default behaviors for sure

19:45 domgetter: So I'm trying to take advantage of the JVM doing optimizations, and I'm using dotimes to see timing from multiple runs of a function. Within a dotimes call, I can see it taking less and less time, but a second call to dotimes starts everything over. Is there a way to keep what "work" the JVM did? https://gist.github.com/domgetter/8c0f66b58cbeca135731

19:46 As you can see on lines 69, 196, and 1310, the times drop.

19:47 When I call dotimes a second time, is it starting over because I'm in a repl?

19:48 Or (depending on the optimization of course) can I expect an optimization to stick around in production?

20:02 BRODUS: say i have a complicated expression, and I want to check if the result is either nil? or seq?, how I could I write that while only writing the expression once

20:03 rather than writing it twice in the or expression

20:04 lambda-11235: (let [val ...] (or (nil? val) (seq? val))

20:42 codahale: domgetter: If you’re trying to benchmark something, I’d suggest using Criterium. The JVM makes naive benchmarking effectively impossible.

21:36 jghasjhjkasd: hi can someone tell me why this doesn't work? (map #(1) [1, 2, 3])

21:36 just trying to turn the list in to a list of 1's

21:36 justin_smith: ,'#(1)

21:36 clojurebot: (fn* [] (1))

21:37 justin_smith: that tries to call 1 as a function

21:37 jghasjhjkasd: ohh right ok

21:37 justin_smith: ,(map (constantly 1) [1, 2, 3])

21:37 clojurebot: (1 1 1)

21:37 justin_smith: ,(map (fn [_] 1) [1, 2, 3])

21:37 clojurebot: (1 1 1)

21:38 justin_smith: my two minor peeves about clojure is that identity is longer than (fn [x] x) and constantly is longer than (fn [& _] x)

21:41 lambda-11235: justin_smith: Indeed, I find myself defining id and const in the REPL when I need them.

21:42 identity is still two characters shorter than (fn [x] x).

21:44 justin_smith: lambda-11235: oh right, (fn[x]x) isn't nearly as nice

21:47 jghasjhjkasd: hey justin_smith

21:48 justin_smith: yes?

21:48 jghasjhjkasd: is there any way to do that map thing with the shorthand syntax?

21:48 (map (fn [_] 1) [1, 2, 3])

21:48 with #

21:48 justin_smith: the closest you can get is #(do % 1)

21:48 because otherwise it will complain about the arg count

21:48 and #(do % 1) is terrible

21:49 jghasjhjkasd: i dont get it.. why do you have to use all the arguments?

21:49 justin_smith: jghasjhjkasd: because if you don't use any args, the compiler generates a function that takes no args

21:49 and you get an error because you get an arg

21:49 BRODUS: is there a function that returns the maps a predicate to a collection and returns the first value that satisfies the predicate?

21:49 jghasjhjkasd: oh ok

21:49 thx

21:50 BRODUS: *is there a function that maps a predicate to a collection and returns the first value that satisfies the predicate?

21:50 justin_smith: BRODUS: (comp first filter)

21:50 ,((comp first filter) even? [1 3 6 42])

21:50 clojurebot: 6

21:50 BRODUS: that makes sense

21:54 and because filter returns a lazy sequence that means it will not map over the whole collection

21:57 justin_smith: right

21:58 but I still find it surprising there isn't a function for "first item matching the predicate" built in

22:14 amalloy: that obvious missing function is rich's subtle way of encouraging everyone to run their own fork of clojure with noe added function

23:33 tolstoy: BRODUS "some" kinda does that. (some #(when (pred? %) %) coll).

23:33 BRODUS: right but that just returns a boolean

23:34 tolstoy: The way I wrote it there, it returns the value.

23:34 BRODUS: oh i see

23:34 tolstoy: ,(some #(when (even %) %) [1 3 5 6 8 1 2 4])

23:34 clojurebot: #error {\n :cause "Unable to resolve symbol: even in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: even in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6704]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve symbol: even in this co...

23:34 tolstoy: ,(some #(when (even? %) %) [1 3 5 6 8 1 2 4])

23:34 clojurebot: 6

23:37 BRODUS: good to know, i need to use 'when' more

23:37 tolstoy: Part of the when, when-not, when-let family.

23:50 jghasjhjkasd: how do you remember when the list/collection is the first or last parameter of clojure functions? just memorization or is there logic behind it?

23:51 like cons is list last, conj is list first, nth is list first, reduce is list last, etc.

23:52 tolstoy: My guess: if it's operating over a range of values, it's at the end (map, reduce, etc).

23:52 But if you're just changing one thing about the collection, it's first (conj, assoc).

23:54 amalloy: jghasjhjkasd: mostly things that operate on sequences take them last, where things that operate on any kind of collection take it first

23:54 also how do you remember your username

23:54 jghasjhjkasd: i just typed in a bunch of gibberish it's not my username i'm using irc web client

Logging service provided by n01se.net