#clojure log - Feb 10 2016

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

0:24 tolstoy: Interesting. You can't use core.async inside the Electron main thread, it seems. goog.global.setTimeout is not a function.

0:49 yuung: hey all, how can i load code outside of src/ with lein? i have a folder named db/my_proj in the root of my project folder that I'd like to add to the path

0:50 hiredman: tolstoy: that sounds like a compilation issue with clojurescript

0:51 goog.* is the prefix used by the google closure libraries

0:57 tolstoy: hiredman: I agree. When I'm not so crunched, I'll investigate. It doesn't really make sense to me.

1:25 hiredman: I wonder if it's because I used :optimizations :simple for an app that runs on node.

1:29 neoncontrails: binjured: did you figure out an answer to your question earlier about generating a type-hinted function?

1:48 tolstoy: hiredman: If I do this, (set! js/goog.global js/global), things work. ;) http://dev.clojure.org/jira/browse/ASYNC-110

4:19 visof: hi guys

4:19 ,(conj (vec (drop-last [1 2 3 4])) (inc (last [1 2 3 4])))

4:19 clojurebot: [1 2 3 5]

4:19 visof: is this good way to change the last element only in list?

4:20 ,(conj (vec (drop-last [1 2 3 4])) (let [l (last [1 2 3 4])] (* l l l)))

4:20 clojurebot: [1 2 3 64]

4:21 luma: ,(update [1 2 3 4] 3 inc) ; if you have a vector

4:21 clojurebot: [1 2 3 5]

4:21 luma: ,(update [1 2 3 4] 3 #(* % % %))

4:21 clojurebot: [1 2 3 64]

4:22 visof: luma: what if i don't know index?

4:22 .indexOf ?

4:22 what if there are multiple same elements?

4:23 luma: ,(update [12 13 14 15] 3 inc) ; this doesn't care about the values, the "3" is the index

4:23 clojurebot: [12 13 14 16]

4:59 jonathanj: ,(use 'com.rpl.specter)

4:59 clojurebot: #error {\n :cause "Could not locate com/rpl/specter__init.class or com/rpl/specter.clj on classpath."\n :via\n [{:type java.io.FileNotFoundException\n :message "Could not locate com/rpl/specter__init.class or com/rpl/specter.clj on classpath."\n :at [clojure.lang.RT load "RT.java" 456]}]\n :trace\n [[clojure.lang.RT load "RT.java" 456]\n [clojure.lang.RT load "RT.java" 419]\n [clojure.core$l...

4:59 jonathanj: :|

4:59 not sure if (specter/transform [LAST] inc [1 2 3 4]) is overkill or a good idea

5:00 MJB47: if you are already using specter i dont see a problem

5:00 but i wouldnt include it to the ns just for that

5:00 geirby: yep, the snippet is quite readable

5:01 so go for it if you're already using specter

5:16 jonathanj: MJB47: thing is that once you have it included, you find ways to use it

5:16 MJB47: if you have enough cases where it would be useful, then whats wrong with including it?

5:17 jonathanj: i don't know, you were the one suggesting not including it

5:17 MJB47: the only tradeoffs i can think of is anyoen else working on the project will need to learn it, and its an extra dependency (with all that entails)

5:17 jonathanj: all i'm saying is that if you include it for "just that" you will almost certainly find a way to use it for other cases

5:17 MJB47: this is true, but you can always refactor later to do this with the original case

5:18 idk, its up to you

5:18 personally i think the library is awesome and worth including in most projects

5:18 but that varies between people

5:18 jonathanj: my personal preference is to do it the other way, once your code is more mature and you only have a few uses of something then perhaps rewrite your code so you don't need it

5:19 MJB47: that wounds backwards to me

5:19 idk

5:19 sounds*

5:19 jonathanj: but in terms of getting things done, including specter and writing the code would have taken less time than the IRC conversation

6:28 Using ring-jetty-adapter, how does one specify what certificate to use for SSL connections?

6:29 (I have a keystore with several certificates in it.)

6:34 hillbillie: test

7:16 justin_smith: ,(let [v [1 2 3 4]] (conj (pop v) (inc (peek v)))) ; visof

7:16 clojurebot: [1 2 3 5]

7:17 justin_smith: that only works for a vector though

7:17 clojurebot: Cool story bro.

7:17 justin_smith: ,(let [v '(1 2 3 4)] (conj (pop v) (inc (peek v)))) ; visof

7:17 clojurebot: (2 2 3 4)

10:53 fuuduCoder: what would be the best way to get last but one element in a sequence.

10:54 last of butlast?

10:55 MJB47: depends on the type of sequence

10:56 nvm no it doesnt

10:56 probably (last (butlast ...)) yes

10:56 aurelian: ,(map #(nth [1 2 3] %) [0 2])

10:56 clojurebot: (1 3)

10:57 aurelian: is there a nicer way to do that? ^^

10:57 select from a coll a list of indexes

10:57 MJB47: are you trying to retrieve the first and last elements? or the even indexed elements? or remove the second element?

10:58 fuuduCoder: just get the last but one element if it exists

10:58 aurelian: no, sorry, I have a list and I need to select elements at index 0, 2, 5 and anotherone

10:58 I thought there's a built in

10:58 MJB47: select-keys is close

10:58 but

10:59 ,(vals (select-keys [1 2 3] [0 2]))

10:59 clojurebot: (1 3)

10:59 MJB47: you judge if its nicer

10:59 averagehat: ,(map( [1 2 3] ) [0 2])

10:59 clojurebot: #error {\n :cause "Wrong number of args (0) passed to: PersistentVector"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (0) passed to: PersistentVector"\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" 28]\n [sandbox$eval76 invokeStatic "NO_SOURCE_FILE" 0]\n [san...

10:59 averagehat: ,(map( [1 2 3] [0 2])

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

10:59 aurelian: oh, ok, I thought select-keys is for maps only

10:59 averagehat: oops sorry clojurebot

10:59 ,(map( [1 2 3] [0 2])

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

11:00 averagehat: ,(map [1 2 3] [0 2])

11:00 clojurebot: (1 3)

11:00 averagehat: sorry fail

11:01 aurelian: ,(map #(nth (:a :x 3 :q "foo" :tcp) %) [0 2 5])

11:01 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Wrong number of args passed to keyword: :a>

11:01 aurelian: grr

11:02 ,(map #(nth '(:a :x 3 :q "foo" :tcp) %) [0 2 5])

11:02 clojurebot: (:a 3 :tcp)

11:03 jonathanj: (specter/select [[0 2]] [1 2 3])

11:03 sorry, i'm not trying to be that guy who recommends one tool for everything but there seem to be quite a few applicable cases today

12:24 novak`: is there standard way in clojure to print warnings in console applications?

12:26 justin_smith: novak`: you can print to *err*

12:28 novak`: for example this works java -jar ~/bin/clojure.jar -e '(binding [*out* *err*] (println "err"))' > /dev/null

12:28 since only stdout and not stderr was redirected, "err" prints

12:29 bitsynthesis: hello! is it possible to run leiningen tasks and override a given project property without with-profiles? i'd like to pass in an argument dynamically at the time a task is run

12:31 justin_smith: bitsynthesis: if I were doing this I would define multiple profiles and use with-profile on the command line to select one

12:31 I don't know of a way to get freeform config into lein from the cli

12:31 hyPiRion: bitsynthesis: `lein help update-in`

12:35 justin_smith: hyPiRion: oh, that's a cool one

12:36 bitsynthesis: justin_smith: thank you!

12:45 novak`: justin_smith: Yep, I've already seen it before somewhere... :D Thank you!

12:55 I have one more question - Is there any clojure function that returns platform independent line separator or to use (System/lineSeparator)?

12:56 justin_smith: ,(newline)

12:56 clojurebot: \n

12:56 justin_smith: that outputs it...

12:57 ,@#'clojure.core/system-newline ; var deref since it is private

12:57 clojurebot: "\n"

12:57 justin_smith: ,System/lineSeparator ; no need for the parens I think

12:57 clojurebot: #error {\n :cause "Unable to find static field: lineSeparator in class java.lang.System"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to find static field: lineSeparator in class java.lang.System, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6688]}\n {:type java.lang.RuntimeException\n :messag...

12:58 justin_smith: err...

12:58 ,(System/lineSeparator)

12:58 clojurebot: "\n"

12:58 justin_smith: OK then

12:58 odd that wouldn't be a static field

13:03 novak`: justin_smith: lineSeparator is method actually

13:04 justin_smith: (newline) returns nil, it immediately print newline to *out*

13:07 justin_smith: novak`: right, I was surprised lineSeparator was a method not a static field, and as I showed clojure does have a var holding the system-newline, but it's private

13:11 novak`: justin_smith: So OK, (System/lineSeparator) is good enough. :)

13:12 justin_smith: ,[(Math/PI) Math/PI] ; static methods are slightly weird for hysterical raisins

13:12 clojurebot: [3.141592653589793 3.141592653589793]

13:13 justin_smith: it's one of very few places where parens are optional

13:13 along with the threading macros, case... anything else?

13:14 well case in the special circumstance where you match a single value

13:17 novak`: \exit

14:12 WorldsEndless: What's wrong here?

14:12 ,(for [[n x] (interleave [1 2] ["keywords.csv" "topics.csv"])] (println n x))

14:12 clojurebot: #<UnsupportedOperationException java.lang.UnsupportedOperationException: nth not supported on this type: Long>

14:13 WorldsEndless: For some reason for is choking, since the interleave works in isolation

14:13 chouser: Something is trying to call 'nth' on a long. Destructuring uses 'nth', so look for a place where destructuring is being unintentionally applied to a number.

14:14 WorldsEndless: Obviously that would have to be the [[n x]], but I'm not sure why it has a problem here

14:14 chouser: ,(for [[n x] [1 2 3 4]] n)

14:14 clojurebot: #<UnsupportedOperationException java.lang.UnsupportedOperationException: nth not supported on this type: Long>

14:14 chouser: ,(for [[n x] [[1 2] [3 4]]] n)

14:14 clojurebot: (1 3)

14:14 WorldsEndless: Ah. That's it.

14:15 so, since I want each interleaved item to be an isolated vector pair, what function am I looking for? Maybe not interleave?

14:16 A nested for loop?

14:16 chouser: You might like (map list ...) or (map-indexed list ...)

14:16 ,(map-indexed list "abcd")

14:16 clojurebot: ((0 \a) (1 \b) (2 \c) (3 \d))

14:16 WorldsEndless: So I don't actually want numbers in the real use case, so maybe some kind of map

14:17 chouser: ,(map list "abcd" "wxyz")

14:17 clojurebot: ((\a \w) (\b \x) (\c \y) (\d \z))

14:17 WorldsEndless: yuck

14:17 chouser: ?

14:17 WorldsEndless: Sorry. I just mean the character iteration surprised me

14:17 chouser: oh, sorry.

14:17 ,(map list '[a b c] '[d e f])

14:17 clojurebot: ((a d) (b e) (c f))

14:17 chouser: better? :-)

14:18 WorldsEndless: yuep :)

14:18 chouser: You may also consider replacing your 'for' with 'map' and save the building and then destructuring of the list.

14:19 WorldsEndless: Is there any important difference in this case between map list and map vector?

14:19 chouser: ,(map (fn [x y] (println x y)) '[a b c] '[d e f])

14:19 clojurebot: (a d\nb e\nnil c f\nnil nil)

14:19 chouser: bleh. that printed badly.

14:19 WorldsEndless: No important difference in this case.

14:19 WorldsEndless: I think map is the answer. Thanks!

14:20 justin_smith: WorldsEndless: for something that's going to be exactly length of 2, list might be slightly better, but it really depends what you plan on using it for

14:20 kwladyka: WorldsEndless more like you thinking. If you do something for every position in collection use map. With for you can use :let :when etc. and skip some values

14:21 chouser: ha! I snuck an answer in while justin_smith was away! I'll have to go back to lurking now, since I can't actually compete.

14:21 justin_smith: chouser: hahaha

14:21 kwladyka: chouser yes you was faster this time :P

14:22 it is some kind of achievement ;)

14:45 binjured: is there a way to create a var reference that can be used during macro expansion? i keep getting "Can't embed object in code"

14:47 justin_smith: binjured: that sounds like you tried to use the var itself instead of its value

14:47 or the symbol that would look it up

14:49 binjured: justin_smith: yeah, i can't figure out how to give that symbol to the macro in a way that it actually gets used as a var value.

14:49 justin_smith: ,(defmacro silly [] 'foo)

14:49 clojurebot: #'sandbox/silly

14:50 justin_smith: ,(def foo 1)

14:50 clojurebot: #'sandbox/foo

14:50 justin_smith: ,(silly)

14:50 clojurebot: 1

14:50 justin_smith: binjured: it's that simple

14:50 or you want the var...

14:50 ,(defmacro silly [] '(var foo))

14:50 clojurebot: #'sandbox/silly

14:50 binjured: how can i do that without the '? like, programatically. (something-here "foo")

14:50 justin_smith: ,(silly)

14:50 clojurebot: #'sandbox/foo

14:51 binjured: ah

14:51 justin_smith: so you want to take the string, turn it into a symbol, and get the var for that symbol?

14:52 binjured: yeah. reason being is earlier in the macro I'm doing (declare (symbol some-string))

14:52 justin_smith: ,(defmacro silly [x] `(var (symbol ~x)))

14:52 clojurebot: #'sandbox/silly

14:52 justin_smith: ,(silly "foo")

14:52 clojurebot: #error {\n :cause "clojure.lang.Cons cannot be cast to clojure.lang.Symbol"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.ClassCastException: clojure.lang.Cons cannot be cast to clojure.lang.Symbol, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyzeSeq "Compiler.java" 6875]}\n {:type java.lang.ClassCastException\n :message "clojure.lang.Con...

14:52 justin_smith: ergh

14:52 binjured: yeah, that's what i get too

14:52 justin_smith: ,(defmacro silly [x] `(var ~(symbol x)))

14:52 clojurebot: #'sandbox/silly

14:52 justin_smith: ,(silly "foo")

14:52 clojurebot: #'sandbox/foo

14:52 justin_smith: ~quoting

14:52 clojurebot: quoting is quote

14:53 justin_smith: ~quote

14:53 clojurebot: http://en.wikipedia.org/wiki/Lisp_%28programming_language%29#Self-evaluating_forms_and_quoting

14:53 justin_smith: I wanted clojurebot to have something clever to say about how stupid quoting always is

14:53 binjured: haha

15:38 adis: svasta..nidje zive duse

16:01 kwladyka: what convention for naming do you have in situation like that: (:require [foo.uuid :as uuid]) (let [bar uuid/create!] ...) <- how you will call bar in this case?

16:02 the best would be uuid but, uuid is reserved in that situation

16:09 as i discover i need use uuid in more then one place as name of parameter... maybe in convention better is do require [foo.uuid :as ns-uuid] or something like that?

16:27 octe: i get this "CIDER's version (0.11.0-snapshot) does not match cider-nrepl's version (0.10.0-snapshot). Things will break!" even though i specified "0.11.0-SNAPSHOT" for cider/cider-nrepl plugin in the repl profile in my project.clj

16:27 what could i be doing wrong?

16:28 nevermind, i had it my user profile in profiles.clj

16:44 kwladyka: i have strange situation and not sure what is happening, all the time i get expection IllegalArgumentException No matching field found: getSQLState for class java.lang.ClassCastException clojure.lang.Reflector.getInstanceField (Reflector.java:271) <- i am using data from clojure jdbc query and whenever i pass them i have problem like that

16:45 for example if i pass this data to postal/send-message i get this error, but if i pprint them it is ok.

16:45 this error totally say mi nothing and is very confuse

16:46 what getSQLState have to do with pass data to another function like postal?

16:47 hmm i see whatever i pass to postal it gives me this error.... mmm

16:48 but i also get this error in not postal, in selmer

16:48 that is so strange

16:51 ok that was error from postal (as i guess)

16:59 patham9: hi! why cant clojure automatically detect if a recursion happens at tail position and use recur?

17:00 justin_smith: patham9: it totally could and does not. What this avoids is a common bug in other lisps where people do a self call that they assume is optimized but isn't actually tail recursive.

17:01 patham9: by requiring you to explicitly say "this must tail recur" you get a compilation error that it is not tail, instead of a sneaky stack overflow later

17:02 patham9: which is nice yes

17:02 then the IDE could be smarter, and insert recur where the recursive call happens in case that it succeeds there ^^

17:03 justin_smith: patham9: this would be an awesome editor feature, yes!

17:05 patham9: another question: it wasn't until Clojure where I really realized the importance of tail recursion

17:06 Are there no mechanisms, which can transform a non-tail-recursive formulation into tail recursive ones?

17:06 Often not-tail-recursive formulations are a lot more elegant

17:06 amalloy: not all functions are amenable to such a transformation

17:07 eg, consider doing a depth-first walk of a tree

17:07 patham9: i see hm

17:07 but many could be

17:08 kwladyka: How to with-redefs correctly here https://www.refheap.com/114683 ?

17:09 amalloy: put the with-redefs inside the deftest

17:09 kwladyka: it still call original

17:09 hmm why it doesn't work outside testing?

17:09 justin_smith: kwladyka: the with-redefs needs to surround your code, right now it only surrounds the def

17:10 when your code runs, it is outside that block

17:10 the with-redefs has already exited

17:10 so you need with-redefs to be inside the deftest

17:10 amalloy: (with-redefs [...] (deftest ...)) redefines this function, defines a test, and then puts the original function back

17:10 kwladyka: ok i think i undrestand

17:11 justin_smith: kwladyka: with-redefs is not a lexical binding like let, it is a dynamic one like binding

17:11 patham9: think about this one: (defn factorial [n] (if (= n 1) 1 (* n (factorial (- n 1) ))))

17:11 kwladyka: ok thank you for explanation

17:11 patham9: its nearly the most intiutive way how to see it

17:11 how to define it

17:12 justin_smith: patham9: that one can be tail recursive if you add an arg

17:12 but as amalloy mentions some algos can't be recursive that way

17:12 patham9: if I add an arg?

17:12 factorial only has 1 arg ^^

17:12 justin_smith: right, an accumulator representing an accumulated state

17:12 patham9: you mean a nested function (loop usually in clojure)

17:13 justin_smith: patham9: * has two args, if you want to tail recur both need to be passed to the next call

17:13 patham9: no

17:13 patham9: which has an additional accumulator

17:13 justin_smith: patham9: ok sure, an extra arity, a loop, whatever, but hte point is the algo can be tail recursive if you add an argument

17:14 that's the general thing - many primitive recursions become tail recursions by adding arguments, but only if you can commute on the accumulator

17:14 patham9: by using a loop which is quite unelegant, thats what i want to avoid

17:14 justin_smith: you can commut * but you cannot commute a tree walk

17:14 patham9: then don't use a loop, define a second arity to the same function

17:14 kwladyka: how do you make function to do nothing with with-redefs: [advertisements.email.handler/send-email! (fn [& _] nil)] <- something like that or can i do it simpler?

17:14 patham9: can you give an example?

17:15 justin_smith: (defn factorial ([n] (factorial n 1)) ([n acc] ...))

17:15 that way you can update the accumlator on each call, instead of leaving a multiply hanging for later

17:16 ,(defn factorial ([n] (factorial n 1)) ([n acc] (if (= n 1) acc (factorial (dec n) (* acc n)))))

17:16 clojurebot: #'sandbox/factorial

17:17 justin_smith: ,(factorial 6)

17:17 clojurebot: 720

17:17 patham9: this works? nice :D

17:18 justin_smith: only if your state is commutative, but yes

17:18 or am I wrong about that? puzzling it out now...

17:18 patham9: what does it mean to the state to be commutative?

17:19 kwladyka: anyway for better performance you should use recur

17:19 justin_smith: patham9: multiplication commutes, so you don't need to save up all the multiplications for later, you can do them as you go

17:19 ptisnovs: ,(defn factorial ([n] (factorial n 1M)) ([n acc] (if (= n 1) acc (factorial (dec n) (* acc n)))))

17:19 clojurebot: #'sandbox/factorial

17:19 ptisnovs: its better, not overflow ;)

17:19 ,(factorial 100)

17:19 clojurebot: 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000M

17:19 justin_smith: ptisnovs: you want *'

17:19 patham9: this multi arg is extremely nice in that language!!

17:19 justin_smith: or maybe not?

17:19 patham9: yeah, it works nicely in clojure

17:19 ptisnovs: justin_smith: yeah, it's even better

17:19 patham9: haskell doesnt have sth like this?

17:19 kwladyka: patham9 http://clojuredocs.org/clojure.core/recur

17:20 justin_smith: ptisnovs: instead of 1M you can use *' which means it auto-promotes but only as needed

17:20 kwladyka: there is even example with factorial ;)

17:20 justin_smith: patham9: haskell only allows functions of a single argument, of course

17:20 kwladyka: it is the classic, after all

17:20 patham9: @kwladyka: loop is not that beautiful ^^

17:22 kwladyka: patham9 you don't have to use loop

17:22 patham9: in java i would also use the loop ^^

17:22 kwladyka: ,(defn foo [n] (if (zero? n) "end" (recur (dec n))))

17:22 clojurebot: #'sandbox/foo

17:22 kwladyka: ,(foo 3)

17:22 clojurebot: "end"

17:23 kwladyka: patham9 recur matter for performance

17:24 patham9: i know

17:24 recur is fine

17:24 having to create virtual accumulator variables to make sth tail recursive, not so

17:24 justin_smith: patham9: it's just moving data from the stack into the heap

17:25 patham9: the beauty of the representation is the key difference for me

17:25 sth beautiful turning ugly to be efficient

17:25 ptisnovs: patham9: IMHO only primitive recursive functions could be written by using recur + accumulator. for not primitive recursive functions, stack or other data structure would be needed

17:26 patham9: hm

17:26 ptisnovs: patham9: https://en.wikipedia.org/wiki/Primitive_recursive_function if you are interested

17:26 rcassidy: accumulators aren't ugly :)

17:29 patham9: interesting

17:29 they should be inferred by the compiler not complicating my recursive formulations ^^

17:30 justin_smith: patham9: as the page above mentions, it's impossible to solve the general "is this primitively recursive?" quesiton. But it is straightforward to build a function that is guaranteed to be primitive-recursive

17:31 patham9: maybe in general its hard, for most practical cases though it might be possible

17:32 maybe in general its impossible i meant

17:32 but this doesnt say that much

17:33 as with the halting problem: sure its impossible to decide whether a TM halts. but still its impossible to identify a lot of very interesting infinite classes of TM's where it can indeed be decided

17:33 (whether a TM halts in general I meant)

17:33 but still its possible to identify... argh ^^

17:34 too long day already ^^

17:36 but i see I want too much :D

17:37 ptisnovs: patham9: ackermann's function is pretty good to study: http://rosettacode.org/wiki/Ackermann_function#Clojure

17:37 patham9: impossible to avoid the recursion AND not using stack (or vector or so as accumulator)

17:38 patham9: i know that such functions exist, but most practical recursions are primitive recursive

17:38 as occurring in practical programs

17:38 but still the compiler wont identify this property and leaves it to the programmer

17:38 ptisnovs: patham9: yeah (with the exception of traversing trees)

17:40 patham9: or IDE feature: Primitive recursive function detected, click to rewrite to tail recursive version ^^

17:41 this is what i want ^^

17:42 ptisnovs: lisp and scheme could detect some (almost all?) such cases, so it might be possible to implement it

17:44 justin_smith: well that's just detecting tail position, not something like "this thing could become an accumulator..."

17:45 patham9: indeed, it should do the hard work: creating the tail recursive formulation by its own after finding out that the function is primitive recursive ^^

17:48 amalloy: there are tools that will do that

17:49 patham9: there are?

17:49 amalloy: well, i'm thinking of CPS transformers

17:49 which i think is similar/related

17:52 kwladyka: Why in many modules like for example https://github.com/juxt/bidi i see people use vectors instead of map. Like here (def my-routes ["/" {"index.html" :index "article.html" :article}]) <- why not {"/" {...}} ?

17:54 justin_smith: kwladyka: because the order decides which wildcards could shadow other routes

17:54 and maps are not ordered

17:55 kwladyka: justin_smith thx!

17:55 justin_smith: kwladyka: I figured this out when I helped write a routing lib...

17:58 kwladyka: it was mysterious for me, i saw that many times for different code and always asked myself... but why?

18:06 arkh: any thoughts on why this doesn't work?: (apply assoc {:a 1} (interpose 0 [:b :c :d]))

18:07 justin_smith: arkh: interpose only puts items in between

18:07 ,(interpose 0 [:b :c :d])

18:07 clojurebot: (:b 0 :c 0 :d)

18:07 arkh: ohh ... thank you

18:07 justin_smith: ,(interleave (repeat 0) [:b :c :d])

18:07 clojurebot: (0 :b 0 :c 0 ...)

18:08 justin_smith: err

18:08 ,(interleave [:b :c] (repeat 0))

18:08 clojurebot: (:b 0 :c 0)

18:08 justin_smith: that's the one you want

18:08 arkh: boom - thank you

18:12 amalloy: (into {:a 1} (zipmap [:b :c :d] (repeat 0)))

18:13 (into {:a 1} (for [k [:b :c :d]] [k 0]))

18:16 arkh: now see, that's where my lengthy but insular clojure experience needs more flavor. I always reach for e.g. apply instead of into and there's probably a bunch of other habits I have like that

18:17 it's good to see the different ways

18:21 code-ape: Quick question, I have a lazy-seq of numbers that does terminate. I want to count how many are even. What's the best way to do this? Thank you!

18:24 arkh: code-ape: assuming you don't have memory concerns, (count (filter even? lazyseq)) will do it

18:24 ,(count (filter even? (range 10)))

18:24 clojurebot: 5

18:25 code-ape: arkh: Cool! ... but I do have memory concerns sadly :/

18:25 Sorry, should have specified.

18:30 arkh: unfortunately I have to take off but in general I would recommend using (loop ...) and iterate through the lazy seq while keeping a tally of even numbers

18:30 code-ape: Thought as much! Thank you.

18:30 arkh: you wouldn't need to hold on to the head of the seq or generate an intermediate seq to count over that way

18:31 justin_smith: arkh: you can use reduce instead of loop for less boilerplate

18:31 arkh: this holds true with any loop that has exactly one sequence as input and always walks the sequence end to end

18:32 nb. I am differentiating input from accumulator here

18:33 ,(reduce (fn [n e] (if (even? e) (inc n) n)) 0 [0 1 2 3 4])

18:33 clojurebot: 3

18:34 code-ape: Perfect! Thank you justin_smith :)

18:34 amalloy: (count (filter even? (range 5)))

18:34 oh i see that's there already, except for some reason you said that memory is a problem?

18:35 it's obviously not

18:35 justin_smith: amalloy: that doesn't actually do the head holding arkh was talking about does it? right.

18:35 code-ape: yeah, the count/filter version is actually fine

18:36 code-ape: Oh, alright, good to know!

18:36 justin_smith: ,(transduce (filter even?) + 0 [0 1 2 3 4 5]) ; fancy-ass transducer version

18:37 clojurebot: 6

18:37 justin_smith: wait, that adds the items not counting them

18:46 amalloy: justin_smith: you need to map constantly 1

18:46 justin_smith: ahh, right

18:46 ,(transduce (comp (filter even?) (map (constantly 1))) + 0 [0 1 2 3 4 5])

18:46 amalloy: ,(transduce (comp (filter even?) (map (constantly 1)) + 0 (range 6)))

18:46 clojurebot: 3

18:46 #error {\n :cause "Wrong number of args (1) passed to: core/transduce"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (1) passed to: core/transduce"\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 [sandbox$eval73 invokeStatic "NO_SOURCE_FILE" 0]\n [sandbox...

18:46 amalloy: whoops

18:48 justin_smith: parens are so sneaky

18:48 amalloy: my success rate of typing stuff into #clojure without paredit is high enough i'm willing to accept the occasional disaster

19:46 hey, speaking of counting the number of items in a collection that satisfy a predicate, i just found this (anonymized) in a codebase at work: (reduce (fn [agg x] (if (pred x) (+ agg 1) agg)) 0 xs)

19:47 justin_smith: amalloy: it's more general because you could swap out 1 for another number

19:47 amalloy: nice

19:47 multiplication is too expensive for sure

19:53 TEttinger: amalloy: ... is that a count on a filter, obfuscated?

19:53 amalloy: naturally

19:54 TEttinger: it makes me sad

19:54 amalloy: we were talking about that in here earlier, and someone proposed exactly the same bad solution

20:09 TEttinger: only reason I can think of that being useful, amalloy , is if (pred x) could return non-boolean results, so it might add different numbers based on x's value

20:13 amalloy: sure, and then you'd use (apply + (keep #(...) xs))

20:13 you still wouldn't write it yourself as a reduce

20:35 rhg135: doesn't apply fail with really long seqs?

20:37 amalloy: no

20:37 ,(apply +' (range 100000))

20:37 clojurebot: 4999950000

20:37 rhg135: ,(apply +' (range 1e100))

20:38 clojurebot: eval service is offline

20:38 amalloy: 1e100? you know how big that is?

20:38 rhg135: hmm, maybe I had forgotten the +'

20:38 very big

20:39 I doubt I'll ever get a seq over 1e100 long, so all is good

20:42 ,(do (def count-with-pred (comp count filter)) (count-with-pred even? (range 1e10)))

20:42 clojurebot: eval service is offline

20:42 amalloy: 1e10 is also really big

20:43 that's why i picked 1e5

20:43 rhg135: ,(do (def count-with-pred (comp count filter)) (count-with-pred even? (range 1e4)))

20:43 clojurebot: 5000

20:43 rhg135: I need to pick smaller numbers...

20:45 the factorial function is ridiculously easy in clojure

20:45 amalloy: yeah, the first one you picked is only like...many quintillions of times too big

20:46 lambda-11235: amalloy, rhg135: (range 1e100) would easily take up all the memory on a supercomputer.

20:47 rhg135: 1e10 isn't even that big though

20:47 amalloy: no, 1e10 is fine

20:47 but clojurebot doesn't give you that much time

20:47 adding up all the numbers between 1 and 10 billion

20:47 takes more than a couple seconds

20:48 rhg135: ,(iterate (partial * 2) (iterate inc 1))

20:48 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.lang.Iterate cannot be cast to java.lang.Number>

20:48 rhg135: oh' duh

20:49 yeah, I see how that could take a long time

20:52 I actually calculate the powers of 2 as a inefficient space-heater

22:20 binjured: gah, no matter what i try i can't manage to write a macro that generates this: https://gist.github.com/tdavis/d21ac8579e59d9f5049e except where "thing"/"Thing" is dynamic. i can't get a working IDeref to pass to the `recursive` function. it either ends up as a Var object (can't embed object) or a useless Symbol.

22:22 amalloy: okay, so what are you trying?

22:23 binjured: amalloy: i've tried a bunch of stuff. latest attempt is `(intern *ns* ~(symbol name))`, tried that with deref too

22:25 amalloy: ,((fn [vname] `#'~vname) 'thing)

22:25 clojurebot: (var thing)

22:27 binjured: the problem is building up the contents of that vector requires evaluation (or whatever ~ is called), so i end up with something like [other :- ... #<Var@...> ...]

22:28 TEttinger: `#'~ of course! how beautifully clear!

22:28 I'm glad amalloy understands this stuff!

22:28 amalloy: i mean, you can write (list `var thing) if you prefer

22:29 it's really the same as any other syntax-quoted thing. you start with `, and then write the stuff you want to appear verbatim (here, #'), and then you put a ~ and the stuff you want to be variable

22:31 binjured: tried that, it ends up being a PersistentList

22:33 amalloy: binjured: just like with your question earlier this week, it will be easy to answer once you show me code you are actually running. if you take the things i say, interpret them, apply them, and report results, i have no idea how to help you, because i have no idea how you've interpreted my suggestions, or what context you've put them into

22:33 binjured: amalloy: yeah, i'll try to reproduce with a simple example.

22:33 amalloy: even a complicated example. if you pasted your entire macro i could fix it in thirty seconds

22:33 i just can't debug guesses

22:52 binjured: amalloy: here we go. https://gist.github.com/tdavis/9d8b0f704f1a05f22d0b

22:56 amalloy: https://gist.github.com/amalloy/e2a4edeb7c22b33a9ed5

23:01 binjured: any good?

23:01 binjured: amalloy: testing!

23:04 amalloy: goddamn you, i think it worked...

23:04 amalloy: well i did tell you i knew the answer :P

23:04 binjured: <3 <3 <3

Logging service provided by n01se.net