#clojure log - Jun 04 2015

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

0:23 Seylerius: There a good clojurish way to spawn virtual machines to accomplish a specific task?

0:26 TEttinger: hey Seylerius, did you get the sudoku solver GUI working?

0:26 Seylerius: TEttinger: Been busy with errands all damn day, so no, unfortunately.

0:26 Planning on taking another whack at it tomorrow.

0:26 TEttinger: cool

0:27 Seylerius: Oh, btw, why is your clone always hanging in here?

0:27 TEttinger: It kinda throws off tab-completion on your nick.

0:28 TEttinger: TEttinger2? logger bot, I run an irc bot on an old laptop and I keep an irc client open as well so I can check if it's working

0:28 err

0:28 TEttinger2 is not actually a bot, it's the client

0:28 * Seylerius nods.

0:28 heurist: Seylerius: just set your irc client to complete based on last spoken instead of alpha.

0:29 TEttinger: or shortest first

0:29 but TEttinger leaves, TEttinger2 does not

0:29 ok, time to get this cluajure obscene hybrid working

0:29 Seylerius: TEttinger, heurist: The problem isn't that, the problem is that it just provides the common prefix, which leaves me retyping the ": " every time.

0:30 TEttinger: ahhhhh

0:30 Seylerius: TEttinger: Cluajure? Sounds like an abomination.

0:30 (In other words, I'm being lazy)

0:31 I'm heading out to town. See y'all later, maybe tomorrow.

0:31 * heurist is trying to not tell Seylerius to get a better client.

0:31 Seylerius: heurist: It's ERC, so I just have to configure it a little differently.

0:31 Again, I've been lazy.

0:32 * heurist feels its sympathy evaporate in a lazy-seq

2:44 dfletcher: added my first code sample to clojuredocs.org today :) http://clojuredocs.org/clojure.core/condp#example-556fc440e4b03e2132e7d185

2:47 also heh I never really noticed by my github qrcode thingy looks like a space invader.

2:47 *but my

2:49 condp makes all the other solutions to fizzbuzz look like a big joke heh.

2:50 amalloy: dfletcher: not really. it's much nicer with a loop over the divisor list

2:50 dfletcher: example?

2:52 amalloy: ,(let [divisors [[15 "fizzbuzz"] [3 "fizz"] [5 "buzz"]]] (defn fizzbuzz [n] (-> (first (for [[r s] divisors :when (zero? (mod n r))] s)) (or (str n)))))

2:52 clojurebot: #'sandbox/fizzbuzz

2:52 amalloy: ,(dorun (map (comp prn fizzbuzz) (range 1 30)))

2:52 clojurebot: "1"\n"2"\n"fizz"\n"4"\n"buzz"\n"fizz"\n"7"\n"8"\n"fizz"\n"buzz"\n"11"\n"fizz"\n"13"\n"14"\n"fizzbuzz"\n"16"\n"17"\n"fizz"\n"19"\n"buzz"\n"fizz"\n"22"\n"23"\n"fizz"\n"buzz"\n"26"\n"fizz"\n"28"\n"29"\n

2:53 amalloy: ,(clojure.string/join " " (map fizzbuzz (range 1 31)))

2:53 clojurebot: "1 2 fizz 4 buzz fizz 7 8 fizz buzz 11 fizz 13 14 fizzbuzz 16 17 fizz 19 buzz fizz 22 23 fizz buzz 26 fizz 28 29 fizzbuzz"

2:54 * dfletcher trying to unpack it

2:55 J_A_Work: personally, my favorite FB is with javascript, because switch case can fall through, so you can write it with only the conditionals on mod 3 and 5

2:56 amalloy: the nice thing is that now the divisors are just data, a list you could replace without having to re-define fizzbuzz if you wanted different numbers, and the various bookkeeping is separate from the specific rules

2:57 dfletcher: yeah I like it. also heh thanks for zero? updated my sample

2:59 lumafi: how about fizzbuzz without any conditionals?

2:59 ,(def fizzbuzz (letfn [(fb [s k coll] (mapcat (fn [x] (cons s (rest x))) (partition k coll)))] (->> (range) (fb "fizz" 3) (fb "buzz" 5) (fb "fizzbuzz" 15))))

2:59 clojurebot: #'sandbox/fizzbuzz

3:00 lumafi: ,(clojure.string/join " " (take 30 fizzbuzz))

3:00 clojurebot: "fizzbuzz 1 2 fizz 4 buzz fizz 7 8 fizz buzz 11 fizz 13 14 fizzbuzz 16 17 fizz 19 buzz fizz 22 23 fizz buzz 26 fizz 28 29"

3:00 dfletcher: actually I retract my earlier statment and ammend it. *clojure* makes other solutions to fizzbuzz look like a joke hehe

3:01 amalloy: that's a cute one, lumafi

3:02 dfletcher: zero is a weird case it matches all

3:04 when i tried it as an infinite seq ended up using (rest range) to start with since 0 doesn't make tons of sense

3:04 *to start with 1

3:07 man. i understood amalloy's one pretty quick. this one is making me look up thinigs and I still have no idea whats going on heh.

3:08 amalloy: dfletcher: do you want a hint or to figure it out yourself?

3:08 dfletcher: i like a puzzle i'll ask if I want help hehe

3:10 thanks for asking though rather than just answering it. just feeling chatty this eve :)

3:12 mmeix: Beginner's question: I have [ {:a 1} {:a 2} {:a 3} {:b 5} {:b 6} {:c 99} ] and I want to get [ {:a [1 2 3] {:b [5 6]} {:c [99]} ] - what would be the fn to use with merge-with in this case?

3:12 (obviously conj and concat etc wouldn't work)

3:13 TEttinger: (doc merge-with) ; let's see...

3:13 clojurebot: "([f & maps]); Returns a map that consists of the rest of the maps conj-ed onto the first. If a key occurs in more than one map, the mapping(s) from the latter (left-to-right) will be combined with the mapping in the result by calling (f val-in-result val-in-latter)."

3:13 amalloy: mmeix: in fact concat does work (though i recommend into instead), as long as you pre-process the sequence ahead of time

3:14 mmeix: ah, ok

3:14 amalloy: try something like this: (apply merge-with into (for [m [{:a 1} ...]] ...))

3:15 mmeix: ok, wrapping my brain around this - thanks!

3:29 benhuda: hello

3:30 do you think it is wise to name an open source library "kevlar" given that Kevlar is registered trademark?

3:31 amalloy: well on the one hand you would be safeish on trademark infringement, since there is no danger of someone confusing your clojure library for actual physical kevlar. on the other hand there's nothing stopping them from suing you anyway

3:31 benhuda: yes i just bumped into some lawsuit for kevlarftp (OSS) which was named to kftp after lawsuit threats

3:33 i'll just call it 'armor' then :)

3:35 dfletcher: oh oh I get it! partition is breaking it into sets of 3,5,15. then replace the first element of each partitioned bit with the string. then cons to stitch it all back together. genius! thanks for that lumafi

3:36 TEttinger: kavler

3:36 cavalier

3:39 dfletcher: err, mapcat to stitch it back together, cons is doing the string replacement thingy. ok after midnight i'm a pumpkin now. night peeps.

3:44 TEttinger: &(let [r (range 100) matching (fn [n s] (map #(if (zero? (mod % n)) s "") r) fizz (matching 3 "fizz") buzz (matching 5 "buzz") fizzbuzz (map str fizz buzz)] (map #(if (empty? %1) %2 %1) fizzbuzz r))

3:44 lazybot: java.lang.RuntimeException: Unmatched delimiter: ]

3:44 TEttinger: aww

3:45 &(let [r (range 100) matching (fn [n s] (map #(if (zero? (mod % n)) s "") r)) fizz (matching 3 "fizz") buzz (matching 5 "buzz") fizzbuzz (map str fizz buzz)] (map #(if (empty? %1) %2 %1) fizzbuzz r))

3:45 lazybot: ⇒ ("fizzbuzz" 1 2 "fizz" 4 "buzz" "fizz" 7 8 "fizz" "buzz" 11 "fizz" 13 14 "fizzbuzz" 16 17 "fizz" 19 "buzz" "fizz" 22 23 "fizz" "buzz" 26 "fizz" 28 29 "fizzbuzz" 31 32 "fizz" 34 "buzz" "fizz" 37 38 "fizz" "buzz" 41 "fizz" 43 44 "fizzbuzz" 46 47 "fizz" 49 "buzz" "fizz... https://www.refheap.com/102078

3:45 TEttinger: it's always nice to write fizzbuzz

3:46 different ways every time

3:51 H4ns: how can i, in cider, achieve that a macro expansion (C-c C-m) is not elided using #?

3:51 C-c M-m that is

5:28 kungi: I updated compojure from 1.2.0 to 1.3.4 and the order of the keys/vals in (:roles (friend/current-authentication)) reversed?

5:29 O.o

5:30 Empperi: kungi: you cannot rely on map value ordering

5:30 not unless you are using a sorted map

5:30 https://clojuredocs.org/clojure.core/sorted-map

5:31 TEttinger: or an ordered map, which doesn't come with clojure and is in flatland

5:31 kungi: Empperi: not the ordering of the map. The keys and values reversed

5:31 Keys are now values and the other way around

5:31 TEttinger: hm

5:31 Empperi: well that sounds strange

5:32 TEttinger: that would break all sorts of things if there were duplicate values before: ##(hash-map :a 1 :b 1)

5:32 lazybot: ⇒ {:b 1, :a 1}

5:32 TEttinger: totally fine, but

5:32 ##(hash-map 1 :a 1 :b)

5:32 lazybot: ⇒ {1 :b}

5:32 TEttinger: ,{1 :a 1 :b}

5:32 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Duplicate key: 1>

5:33 TEttinger: the function hash-map is more lenient than the literal

5:38 kungi: ... I think it's my fault because of my get-roles-for-user function ...

5:40 ionthas_: What is the neatest way to define default values for a function? Right now I'm using arity and I call the function with the default parameter value.

5:41 Empperi: that is pretty much the neatest way except if you pass in a map and want to provide default values for keys

5:41 ,((fn [{:keys [foo bar] :or {foo 1 bar 2}}] [foo bar]) {:foo 15})

5:41 clojurebot: [15 2]

5:42 Empperi: in that case it's better to use that part of destructuring syntax

5:42 as one might expect, works everywhere where destructuring works

5:43 ionthas_: Thanks Empperi :)

5:43 Empperi: np

5:45 danielcompton: @cfleming: you around?

5:48 kungi: Found it!

5:52 mmeix: amalloy recommended "into" instead of "concat" for use in merge-with - what are the advantages of into vs. concat?

5:52 (besides looking neat)

5:52 justin_smith: mmeix: hash-maps are strict, concat is lazy

5:53 it's usually a bad idea to mix strict and lazy unless you have a specific reason to

5:53 mmeix: I see

5:53 justin_smith: see also stuartsierra's blog post on concat

5:54 http://stuartsierra.com/2015/04/26/clojure-donts-concat

5:54 mmeix: If I'm foreseeing, that I will consume the whole data, lazyness buys me nothing inthis case - right?

5:54 justin_smith: right

5:54 mmeix: ah - thanks for the article!

5:54 justin_smith: unless the data is too large to be in memory all at once

5:55 mmeix: it's a good blog to follow for clojure

5:55 mmeix: my data is mostly around 5-20 elements

5:55 justin_smith: yeah, staying strict will keep it simpler than

5:55 *then

5:55 mmeix: great advice, as ever :-)

6:00 kungi: Empperi: you where right. I depended on the order of entries in a map. It was a bit hidden in the code

6:01 cfleming: danielcompton: Yep, what's up?

6:02 kungi: Is there a standardlibrary function to (select-vals {:a 1 :b 2 :c 3} [:a :c]) -> [1 3]

6:07 mmeix: I have a second question, loosely related: for my current project (music typesetting with svg in clojurescript) I built a couple of basic functions, and a bigger one, which uses them to build a combined graphical group (a chord, consisting of several noteheads, accidentals, stem flags/beam, dots etc.) with many calculations in it, depending on each other; this makes sense as a semantic unit and building block for the next higher

6:07 level. Now for spacing several of these units in a row (staff) I need to ask the group about its dimensions, which would have to be calculated out of the elements in it - this begins to sound like an object with a function "return-size" or something like that in it. What would be a proper Clojure solution to expose this to the next higher function?

6:12 , (map {:a 1 :b 2 :c 3} [:a :c])

6:12 clojurebot: (1 3)

6:12 mmeix: (for kungi)

6:12 justin_smith: alternately ##((juxt :a :c) {:a 1 :b 2 :c 3})

6:12 lazybot: ⇒ [1 3]

6:13 TEttinger: juxt!

6:13 juxtin_smith

6:13 kungi: mmeix: justin_smith thank you :-)

6:13 TEttinger: (inc mmeix)

6:13 lazybot: ⇒ 1

6:13 TEttinger: (inc justin_smith)

6:13 lazybot: ⇒ 258

6:13 mmeix: my first inc :-)

6:13 justin_smith: TEttinger: eventually I will have to implement juxt-in

6:13 TEttinger: this-juxt-in

6:14 justin_smith: that's the version for protocols, of course

6:14 ddellacosta: omg

6:14 you guys are such dorks

6:14 * ddellacosta ducks

6:15 justin_smith: mmeix: are the graphical elements nested like a tree? if so you may want to do a tree walk and either a thing knows its width, or can find out the width from its children, recursively

6:16 mmeix: they are not nested, but dependent on each other via some rules for placement

6:16 justin_smith: mmeix: oh, then that sounds like a reduce

6:17 each one figures out what its right edge in, based on the prior state, and passes that forward

6:17 s/in/is

6:17 mmeix: aha ... have to ponder this for a while ...

6:19 that means, my group has to collect these measurements inside in a neatly accessible way, and expose it as an additional return value, in a map or something like this)

6:21 and since I'll need the dimensions anyway, the "object" should calculate it alongside all the placement and return it with them - is this right thinking?

6:21 justin_smith: I think so

6:21 mmeix: ok - thanks!

6:24 does anyone have a good source for algorithms for overlap detection of shapes (consisting of horizontal/vertical straight lines only)?

6:25 (expressed in x/y coords, of course)

6:26 TEttinger: if the line is vertical, check if its x is between the end and start of any horizontal lines, and if its x is identical with any other vertical lines

6:26 if the line is horizontal, check if its y is between the end and start of any vertical lines, and if its y is identical with any other horizontal lines

6:27 mmeix: and do this for any combination ...?

6:27 I see

6:27 TEttinger: I mean that's super naive, but each check should be very fast

6:27 you can end early if you're doing a reduce, see ##(doc reduced)

6:27 lazybot: ⇒ "([x]); Wraps x in a way such that a reduce will terminate with the value x"

6:28 TEttinger: so if you know you overlap, you don't need to keep checking

6:28 mmeix: I didn't know about early ending in reduce

6:28 more to learn

6:28 thanks again

6:30 justin_smith: yeah, it's easy to get it mixed up, because we have something called "for", but reduce really ends up being the idiomatic replacement of for in other languages in most cases

6:31 mmeix: I get the notion, that for is seldomly the best solution in Clojure

6:31 using map and reduce instead

6:31 justin_smith: it's useful, but I think people get misled by the name about what it would be good for

6:32 TEttinger: for is often a good solution, but it's "for" generating sequences that you usually want to end up changing with map, reduce, filter, etc.

6:33 mmeix: I see - "reduced" is my finding of the day ...

6:33 (inc TEttinger)

6:33 lazybot: ⇒ 57

6:34 mmeix: (inc justin_smith)

6:34 lazybot: ⇒ 259

6:35 TEttinger: gotta inc justin

6:36 mmeix: which I did :-)

6:36 TEttinger: yeah, but it's basically becoming a rule now that technomancy isn't showing up here

6:36 (identity technomancy)

6:36 lazybot: technomancy has karma 163.

6:36 TEttinger: wow

6:36 he used to be King Karma

6:37 justin_smith: (identity amalloy)

6:37 lazybot: amalloy has karma 276.

6:37 TEttinger: I guess he's still garnering good karma, just uh not bot karma

6:38 mmeix: last question:

6:39 ,(let [m [1 4 2 7 8 5] ] ((juxt min max) m)

6:39 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

6:39 mmeix: umpf

6:39 ;(let [m [1 4 2 7 8 5] ] ((juxt min max) m))

6:39 justin_smith: so close!

6:40 mmeix: ,(let [m [1 4 2 7 8 5] ] (apply (juxt min max) m))

6:40 clojurebot: [1 8]

6:40 mmeix: vs.

6:43 ,(let [m [1 4 2 7 8 5]] ((juxt first last) (sort m)))

6:43 clojurebot: [1 8]

6:43 mmeix: has one of these an advantage?

6:44 TEttinger: yeah

6:44 mmeix: (if this would be needed a lot of times)

6:44 TEttinger: ,(let [m ["the" "quick" "brown" "fox"]] ((juxt first last) (sort m)))

6:44 clojurebot: ["brown" "the"]

6:44 TEttinger: min and max are number only

6:44 mmeix: ah!

6:45 didn't think of that

6:45 TEttinger: so sort will have better behavior if you need to change it to another comparable type

6:45 mmeix: in my case I have only numbers

6:45 justin_smith: we have max-key and min-key

6:45 (doc max-key)

6:45 clojurebot: "([k x] [k x y] [k x y & more]); Returns the x for which (k x), a number, is greatest."

6:46 tvanhens: I'm having some difficulty wrapping my head around how protocols work in the repl. I have a dsl ns that has various records that implement the same protocol in a protocols ns. Then I have another ns called api that checks to see if the records passed into a function satisfy the protocol in the protocols ns but all the inputs are returning false even though when I call type on the inputs they are returning the proper record type which does implement the

6:46 protocol I am checking for. If I manually evaluate the nses in a different order (dsl first then protocols then api) it works as expected.

6:46 justin_smith: ,(let [m ["the" "quick" "brown" "fox"]] ((juxt (partial apply max-key count) (partial min-key count)) m))

6:46 clojurebot: ["brown" ["the" "quick" "brown" "fox"]]

6:46 justin_smith: oops

6:47 ,(let [m ["the" "quick" "brown" "fox"]] ((juxt (partial apply max-key count) (partial apply min-key count)) m))

6:47 clojurebot: ["brown" "fox"]

6:47 mmeix: great stuff!

6:51 j-pb: ,(let [m ["the" "quick" "brown" "fox"]] (apply (juxt (partial max-key count) (partial min-key count)) m))

6:51 clojurebot: ["brown" "fox"]

6:52 mmeix: juxt as the ultimative extractor

6:53 (learning Clojure is really fun)

6:53 tvanhens: it appears that for some reason the namespaces are loading in a weird order and the only way I can get around the behavior is to manually evaluate my namespaces in the right order. Whats weirder is that the problem does not occur when I run my program with lein run or run the tests with lein tests

6:54 it appears that the strange protocol behavior only occurs when I am in the repl

6:54 TEttinger: what's amazing is that the code in there is practically all function calls with names, and almost all of those are defined in clojure. nothing like in java or C or C++ with for(int i = 0; i < 10; i++)

6:54 justin_smith: tvanhens: sounds like you are not requiring something you should be?

6:54 j-pb: ,(let [m ["the" "quick" "brown" "fox"]] (apply (partial (juxt max-key min-key) count) m))

6:54 clojurebot: ["brown" "fox"]

6:55 j-pb: this also works, but at this point my brain stops properly comprehending whu

6:55 justin_smith: j-pb: ahh, much better

6:55 heh

6:55 tvanhens: I think that might be the case justin_smith hard to track it down when the tests are passing

6:55 justin_smith: tvanhens: it's true I am hard to track down when the tests are passing

6:56 (I know that's not what you meant)

6:56 tvanhens: haha :)

6:56 TEttinger: (inc j-pb)

6:56 lazybot: ⇒ 1

6:56 TEttinger: that's a nice golf solution, j-pb

6:57 j-pb: TEttinger: got to think about it some more to make sure it's correct though ;)

6:57 tvanhens: yeah its funky cause the system will start with lein run with no problems. What might cause there to be a discrepency between the two? Its almost as if the repl is using a different protocol even though its the same definition

6:57 j-pb: because right now, the transformation seems correct, but not really intuitive :D

6:57 justin_smith: tvanhens: with the repl are you using the same top level namespace that lein run is?

6:57 mmeix: a bit of brain twister, yes

6:57 hyPiRion: psst

6:57 ,(let [m ["the" "quick" "brown" "fox"]] (apply (juxt max-key min-key) count m))

6:57 clojurebot: ["brown" "fox"]

6:58 hyPiRion: no need for partial there

6:58 mmeix: wow

6:58 tvanhens: no. I will try doing that with repl options

6:59 actually scratch that... it is loading into the same top level namespace

6:59 justin_smith: another possibility is any classpath differences between your profiles

7:03 tvanhens: interesting ok so if I restart my repl and then try to eval the user ns or the core test ns I get an error that the records do not satisfy the protocol. However, if I reset my system with stuart sierra (wich uses refresh for ns-es) I can eval either of those two ns-es fine

7:04 TEttinger: I have a feeling you mean one of stuart sierra's libraries, not the person who often is in here

7:04 justin_smith: tvanhens: are things being required in the wrong order?

7:05 TEttinger: he has stuartsierra in another room, when he gets the signal he reloads all the namespaces

7:05 j-pb: hyPiRion: haha very nice, actually using the apply that way make it quite abit more intuitive :D

7:05 (inc hyPiRion)

7:05 lazybot: ⇒ 75

7:05 tvanhens: haha if only

7:06 mmeix: [light bulb] re: juxt "The returned fn takes a variable number of args" - that made my day

7:06 justin_smith: TEttinger: tvanhens also this reminds me I need to make the tests pass on my port of component to cljc so I can share it (it totally works in my dev code so far, using it for a while now)

7:06 mmeix: thanks guys!

7:06 tvanhens: yeah it looks like they are getting required in the wrong order but only in development. The only difference in the classpath is adding a user and a utils ns when in dev... must be related to those

7:06 j-pb: mmeix: yeah, but actually this is what makes them a tad slower :D compared to #(foo %)

7:07 not significantly though

7:07 speaking of which, am I the only one really missing a #` reader macro? that would combine #() and `[] ?

7:07 tvanhens: justin_smith: that would be great

7:07 mmeix: so readabilty/understandability wins in this case :D

7:09 TEttinger: j-pb, so it is anonymous fn syntax that produces a quoted list?

7:09 err, syntax-quoted

7:10 j-pb: TEttinger: yeah exactly, the ` syntax quote already produces a set of function call to build the described structures, but you can't use it in a #() form because of the immediate function call

7:10 TEttinger: ,`'#(+ % %)

7:10 clojurebot: (quote (fn* [p1__25__26__auto__] (clojure.core/+ p1__25__26__auto__ p1__25__26__auto__)))

7:11 TEttinger: ,`~'#(+ % %)

7:11 clojurebot: (fn* [p1__51#] (+ p1__51# p1__51#))

7:11 TEttinger: wheeeeeee

7:11 ,(`~'#(+ % %) 2)

7:11 clojurebot: #error {\n :cause "clojure.lang.PersistentList cannot be cast to clojure.lang.IFn"\n :via\n [{:type java.lang.ClassCastException\n :message "clojure.lang.PersistentList cannot be cast to clojure.lang.IFn"\n :at [sandbox$eval77 invoke "NO_SOURCE_FILE" 0]}]\n :trace\n [[sandbox$eval77 invoke "NO_SOURCE_FILE" 0]\n [clojure.lang.Compiler eval "Compiler.java" 6792]\n [clojure.lang.Compiler eval "...

7:11 TEttinger: wowza

7:11 justin_smith: ,`~`~`~`~'#(constantly nil)

7:11 clojurebot: (fn* [] (constantly nil))

7:12 justin_smith: ,`~`~`~`~`~`~`~`~`~`~`~`~`~'#(constantly nil)

7:12 clojurebot: (fn* [] (constantly nil))

7:13 tvanhens: oy this is annoying. Ok so test-refresh works (which is using the dev profile) lein run works (which is using prod). Starting the repl goes ok. But if I try and run the tests in the test ns without restarting the system... it won't work. Or if I try evaling the user ns. Any other ideas? I guess its pretty simple to workaround but not understanding whats going on is eating at me

7:13 TEttinger: ,(defmacro whee [anon] `~anon)

7:13 clojurebot: #'sandbox/whee

7:13 TEttinger: ,(whee #(+ % %))

7:13 clojurebot: #object[sandbox$eval177$fn__178 0x4ae63a85 "sandbox$eval177$fn__178@4ae63a85"]

7:14 TEttinger: ,((whee #(+ % %)) 2)

7:14 clojurebot: 4

7:14 TEttinger: woo

7:14 j-pb: hrhr

7:16 but yeah, I find myself quite often in a situation where I would like to map over some data and transform each element to some datasructure, a #` would tremendously help with that

7:17 justin_smith: j-pb: I still don't see where syntax quote helps build data structures

7:18 j-pb: justin_smith: when you deal with xml/html trees, variants or maps representing some kind of record it's really usefull

7:19 justin_smith: mostly because of its splicing capabilities

7:19 justin_smith: ~@x is the inverse operation for & x

7:21 gfredericks: I always thought list* was

7:21 j-pb: TEttinger: ah sorry I think I missunderstood you, it would be a syntax for producing a function that takes args and returns a datastructure with the arguments embedded at some places

7:22 crocket: (slurp cat)

7:22 j-pb: ,(macroexpand '`[:foo %1 %2])

7:22 clojurebot: (clojure.core/apply clojure.core/vector (clojure.core/seq (clojure.core/concat (clojure.core/list :foo) (clojure.core/list (quote sandbox/%1)) (clojure.core/list (quote sandbox/%2)))))

7:22 j-pb: ,(macroexpand '#(`[:foo %1 %2]))

7:22 clojurebot: (fn* [p1__49# p2__50#] ((clojure.core/apply clojure.core/vector (clojure.core/seq (clojure.core/concat (clojure.core/list :foo) (clojure.core/list (quote p1__49__51__auto__)) (clojure.core/list (quote p2__50__52__auto__)))))))

7:23 j-pb: while #`[:foo %1 %2] would return basicall y #(clojure.core/apply clojure.core/vector (clojure.core/seq ...

7:24 mmeix: ( followup question: would something like "(apply (juxt max-key min-key) count ...)" a use case for a transducer? )

7:25 (potentially a silly question, I fear ...)

7:25 j-pb: gfredericks: yeah kinda, but that is what syntax quote will just generate, right? manually building the function calls to generate the datastructures is a lot less obvious than syntax quote

7:26 mmeix: could you explain further?

7:26 gfredericks: j-pb: yeah if it does what you need I guess you may as well use it

7:26 mmeix: I'm not sure .... sorry .... does (apply (juxt max-key min-key) count m) generate intermediate lists, internally?

7:27 j-pb: mmeix: no

7:27 mmeix: ah, ok, then the question was silly :D

7:29 (partial (apply (juxt max-key min-key) count)) could make sense, OTH, maybe ...

7:29 j-pb: mmeix: well the strings will be cast to a sequence, for count probably, and the apply might turn the input vector to a seq as well

7:29 would have to be (partial apply (juxt max-key min-key) count)

7:29 mmeix: ok

7:29 ja

7:31 (inc j-pb)

7:31 lazybot: ⇒ 2

7:53 zamaterian: ikitommi_, should I try to implement a pull request for isssue #121 - that moves the validation into a couple of middleware, as described in my comments ?

8:17 crocket: Ruby map's rehash method terrifies me.

8:17 It leads to all sorts of bugs.

8:17 Mutation is bad.

8:19 TEttinger: crocket, if rehash terrifies you, you should see another ruby method, vomit-spiders

8:19 tdammers: is that like Haskell's hypothetical unsafeLaunchMissiles?

8:19 TEttinger: hehe

8:21 vomit-spiders is an interesting function in ruby's standard lib. they don't know when the commit was, but it was before 1970 so the exact time is hard to guess. the comments are in aramaic though.

8:23 the author's name also appears to be permanently lost, since anyone who claims to have decrypted the thousands-of-characters-sequence speaks in tongues for a while then never speaks again.

8:23 which is something of a liability to a large software team

8:25 but it hasn't been removed from the standard lib because Matz has implied that to do so would be very bad if "the stars are not yet right, and the sleeping multitudes have not yet awoken from their dreaming complacency and seen the fire and heard The Screams."

8:25 crocket: What is vomit-spiders?

8:26 TEttinger: $google creepypasta

8:26 lazybot: [Creepypasta] http://www.creepypasta.com/

8:26 tbaldridge: ~guards

8:26 clojurebot: SEIZE HIM!

8:26 tbaldridge: crocket: do no speak of this again

8:26 crocket: tbaldridge, this?

8:27 I need a clarification of what 'this' refers to.

8:28 TEttinger: humor

8:30 crocket: Clojure's data abstractions are as soothing as my aftershave.

8:37 Heisenbugs...

8:46 In the land of ruby and java, you'll see heisenbugs...

8:54 ,(map inc [1 2 3])

8:54 clojurebot: (2 3 4)

8:54 crocket: ,(doc join)

8:54 clojurebot: Gabh mo leithscéal?

8:56 crocket: (clojure.string/join ["s" "e" "x"])

8:56 ,(clojure.string/join ["s" "e" "x"])

8:56 clojurebot: "sex"

9:19 crocket: How would you allocate memory on JVM?

9:19 Without aggressive GC, I'm not comfortable.

9:28 profil: why is there no multiple bind version of if-let? sorta like how some-> works

9:31 crocket: profil, Did you ever need a multiple bind version of if-let?

9:36 profil: yes, I find it ugly to nest multiple if-lets

9:36 H4ns: i've also wanted that in the past.

9:36 hyPiRion: Nesting if-lets won't give the same functionality as having a multiple-bind if-let

9:36 crocket: profil, Why don't you make one?

9:36 profil: hyPiRion: what do you mean? some-> threads sequentially when the result is not nil

9:36 H4ns: just because you can add general language-level to clojure does not necessarily mean that it is a good idea to do so.

9:36 Empperi: hmm, that sounds more like what "some-let" should be, not multiple binding version of if-let

9:36 profil: I think scheme has what I want, called and-let

9:36 Empperi: "bind these expressions into let constants as long as the previous binding ended up into something else than nil, then execute the body with those constants available"

9:36 if I got it right

9:36 crocket: You should be able to write cond-let.

9:36 cond is what you want.

9:36 profil: Empperi: yes, by using something like (and ~@binds)

9:36 Empperi: pretty easy to do with some macro magic

9:37 hyPiRion: profil: (if-let [a b] (if-let [b c] foo bar) baz) is different from (if-let [a b c d] foo baz)

9:37 profil: crocket: no, I dont care about which one failed

9:37 hyPiRion: there is no (if-let [a b c d] foo baz) ...

9:37 chouser: actually, that's interesting. cond-let and and-let both sound plausible but would have different semantics.

9:38 crocket: profil, What do you want to do?

9:38 chouser: s/actually,//

9:38 hyPiRion: profil: the point is, even if there were, multiple-binding if-let wouldn't be the same as nested if-lets

9:38 Empperi: definitely, but I can see the use case for what I just described above

9:39 hyPiRion: yeah, sure thing

9:42 crocket: profil, Can you give us a paste of a minimal nested if-let form?

9:42 I may be able to simplify your code.

9:57 If you don't care about which one failed, you should nest an if form inside a let form.

9:57 This is simpler.

9:58 H4ns: crocket: it is also not the same thing

9:59 crocket: because when if-let allowed multiple bindings, i would expect it to not evaluate bindings further down as soon as an initialization form returned a false value

9:59 hyPiRion: (let [a b c (and a d) e (and c f)] (if f foo bar))

10:00 crocket: We need to see an actual problem case.

10:00 H4ns: beautiful

10:00 chouser: sounds like nested when-let to me

10:00 hyPiRion: if is probably better to use than and actually.

10:00 gives same result, but might be easier to read? idk

10:01 chouser: ah, you want one else for any falsey. hm.

10:02 profil: I was thinking of something like "(defmacro and-let [bindings then else] (let [tests (take-nth 2 (rest bindings))] `(if (and ~@tests) (let ~bindings ~then) ~else)))"

10:02 chouser: yeah, and you want 'if' instead of 'and'

10:02 Bronsa: if-lets

10:02 H4ns: profil: nice

10:03 crocket: https://gist.github.com/pingles/5150585

10:03 chouser: profil: good sketch, clarifies things. But runs expressions twice.

10:03 profil: yeah, I havent tested it

10:04 crocket: profil, ^^

10:06 chouser: very interesting attempts. Even the last one in the comments there copies the else clause multiple times in the expansion, though only runs it once.

10:06 crocket: Why doesn't clojure already provide a proper let binding for if-let?

10:08 I mean multiple local bindings should be available in if-let.

10:09 hyPiRion: crocket: I believe it's because it's not evident what the evaluation rules would be. Given (if-let [a b c d] foo bar), should c be evaluated if a is falsey? If so, then it's "inconsistent" with all the other binding forms out there.

10:09 Er, I meant the opposite

10:10 crocket: "consistent"

10:10 hyPiRion: I meant: If c is not evaluated if a is falsey, then it would be inconsistent with the other binding forms

10:11 chouser: (if (when-let [a b] (when-let [c d] (when-let [e f] ~then))) ~else)

10:11 is that it?

10:12 crocket: That is ugly

10:12 difficult to read

10:13 chouser: Well, I appreciate the input. I was asking if the semantics match what is desired.

10:13 crocket: chouser, That's what I had in mind.

10:14 H4ns: chouser: if then returned falsey, else would be evaluated and returned. that's not right.

10:14 chouser: H4ns: ah, great catch.

10:17 ok, so hyPiRion's solution, but with 'if' instead of 'and' looks best so far

10:19 crocket: nested if-let sounds nasty.

10:19 H4ns: crocket: if it is only in macroexpansion, what would be wrong with it?

10:19 crocket: Is this a deal breaker?

10:20 H4ns, Can you show me the macro?

10:21 hyPiRion: crocket: https://gist.github.com/pingles/5150585#comment-981238, was it not?

10:21 H4ns: crocket: i have not written it because in my opinion, it is not right to add semantics to the language at that level. i do think, though, that it would be the easiest path towards a correct solution. i understand the argument that it would be inconsistent with other clojure binding forms if if-let did not always bind all variables, so i'm okay with not having it.

10:22 tbaldridge: you aren't really adding semantics, it's adding syntactic sugar.

10:22 H4ns: tbaldridge: same thing to me.

10:23 tbaldridge: I'm just saying, don't be afraid to use the features of LISP. They're there for a reason, and used correctly they can offer great power.

10:23 H4ns: tbaldridge: that kind of stuff always reminds me of "#define BEGIN {" back in the day

10:24 crocket: That duplicates else multiple times.

10:24 H4ns: tbaldridge: well yeah right. and in the end, i always prefer conventional code to sugar-coated

10:24 tbaldridge: suit yourself, but remember, when is a macro implemented in user code (not in the compiler), same with if-let, if-some, and, or, etc.

10:25 The compiler only implements about 12 special forms, everything else is syntactic sugar.

10:26 H4ns: tbaldridge: that is just implementation detail. i don't care about the implementation. all i want is that if i see a common control flow or branching form, i can look into the language manual to see how it works.

10:27 crocket: I think I'll get back to it later when it becomes a problem.

10:27 tbaldridge: but that's what (doc 'foo) and (source 'foo) are for.

10:28 I mean, if you don't want to use macros, that's fine, but just realize you'll be coding lisp with one hand tied behind your back.

10:28 H4ns: tbaldridge: i'm using macros all day long, just not to add syntactic sugar for basic language features that i thing should be "better".

10:29 tbaldridge: i think you can stop trying to evangelize me. :)

10:29 chouser: this channel has a bad influence on my responsible use of time :-P

10:31 destructuring forms cause a bit of a problem with hyPiRion's formulation

10:33 hyPiRion: Oh, I've never thought about destructuring binds in if-lets :o

10:34 ,[(if-let [[a b] [nil nil]] 10) (if-let [[a b] nil] 20)]

10:34 clojurebot: [10 nil]

10:34 hyPiRion: Hrm, I'm not sure what I expected for the first one.

10:35 chouser: well, that's how it's always been. I take advantage of that at times

10:35 else is only for the *expr* being falsey. Nothing to do with the bound locals.

10:35 hyPiRion: right

10:36 chouser: but for multiple-binding-if-let, you can't feed nil to users destructuring forms without risking an exception

10:36 ...an exception that they may have been trying to guard against by using if-let :-P

10:37 But you can't wait and do the destructuring just before the ~then because of course they may be using the bound locals along the way

10:38 hyPiRion: I guess (let [g1# b, a g1#, g2# (if g1# d), c g2#] (if g2# then else)) would work

10:38 but that looks convoluted

10:38 chouser: no, that's what I'm saying won't work

10:39 if b is nil, c will be fed a nil.

10:39 If c is a destructuring form that blows up on nil, you'll get an exception instead of the else

10:40 hyPiRion: ooh

10:40 chouser: er, there are destructuring forms that blow up on nil, right?

10:40 * chouser is having trouble thinking of one

10:41 chouser: maybe not. There are destructing forms that blow up, but maybe none with nil.

10:41 hyPiRion: I think you can if you expect the form to be of some shape

10:42 ,(let [{foo :foo bar :bar :or {bar (+ foo 10)}} nil] bar)

10:42 clojurebot: #error {\n :cause nil\n :via\n [{:type java.lang.NullPointerException\n :message nil\n :at [clojure.lang.Numbers ops "Numbers.java" 1013]}]\n :trace\n [[clojure.lang.Numbers ops "Numbers.java" 1013]\n [clojure.lang.Numbers add "Numbers.java" 128]\n [clojure.lang.Numbers add "Numbers.java" 3644]\n [sandbox$eval54 invoke "NO_SOURCE_FILE" 0]\n [clojure.lang.Compiler eval "Compiler.java" 6792]...

10:42 hyPiRion: ,(let [{foo :foo bar :bar :or {bar (+ foo 10)}} {:foo 10}] bar)

10:42 clojurebot: 20

10:42 chouser: ah, :or ... excellent

10:43 hyPiRion: Heh, macros are hard to get right.

10:43 chouser: trying to expand the else clause exactly once makes this quite tricky

10:44 you could wrap it in a function, I suppose. But that loses its tail position in the containing form. sheesh

10:46 Maybe mutating a local flag is the best way. Huh.

10:57 phillord: I'm just trying nightcode out and it seems to be sending my system load through the roof...anyone else had the same experience

11:01 gfredericks: I wrote a basic test.check property testing carmine message queues and immediately ran into a connection pooling quasi-bug https://github.com/ptaoussanis/carmine/issues/135

11:01 (inc test.check)

11:01 lazybot: ⇒ 1

12:07 mikerod: I'm struggling to remember what puredanger blog is now

12:07 something like "inside a clj developer" - my google searching is failing

12:10 http://insideclojure.org/

12:10 got it

12:15 CookedGryphon: Hey, I want to download zip files in my application from multiple end points, with associated names and version numbers... this sounds a lot like artifact dependency management. Does anyone know if there's a light weight artifact download/cache management client library that I could bundle with my app?

12:18 dfletcher: https://github.com/cemerick/pomegranate CookedGryphon maybe?

12:18 morning all

12:19 alexyakushev: Does anyone have suggestions how to use gen-class in tests?

12:20 tbaldridge: I don't know that you can, gen-class requires AOT compilation, don't think that works with most test suites

12:23 alexyakushev: tbaldridge: That's what I thought. I'm trying to run compile step before testing now, let's see if it works

12:24 mikerod: Does anyone know of a good post anywhere that compares operations on Clojure transients to some mutable Java types - like Arraylist and then even primitive arrays?

12:24 I was doing some microbenches locally with criterium and not getting the expected results (transients were faster)

12:24 just doing something basic like, conj'ing up a vector

12:25 with longs

12:25 tbaldridge: what java collection were you using/

12:25 ?

12:25 nvm, just read what you said

12:25 mikerod: I tried PersistentVector vs transient PersistentVector vs ArrayList vs Primitive array

12:25 I'm thinking I'm just writing something stupid, but I was hoping to find some solid resource online

12:25 where someone already gives a good rundown

12:25 tbaldridge: some code would be good

12:26 mikerod: I'll get some up shortly to demo

12:26 tbaldridge: It could just come down to default sizes of things in Java. transient vectors allocate data in chunks of 32. So it might be possible that ArrayList is using something different

12:28 Also, array lists must copy all contents every time they resize, while vectors allocate in chunks and don't copy old chunks when creating new. ]

12:28 So there's a lot of things here that could cause what you're seeing

12:48 franklnrs: when using reagent, is it idiomatic to keep the complete app state in a single atom and have event handlers do deeply nested update-ins?

12:50 dnolen: franklnrs: you should probably direct your question to #clojurescript

12:51 franklnrs: ah yes, will do

12:51 dnolen: franklnrs: Reagent supports both dividing up your state into multiple ratoms and an Om style single atom + cursors.

12:51 justin_smith: franklnrs: I don't think you would need "nested update-ins" - one update-in with a deep nesting of keys maybe...

12:52 unless I misunderstand you here

12:52 franklnrs: and things won't be rerendered multiple times when they depend on multiple ratoms?

12:53 justin_smith, you're right, update-in with deep nesting of keys

13:10 mikerod: tbaldridge: thanks for the input

13:10 sorry, I had to step away a few. I have https://www.refheap.com/102091

13:10 there is a good chance I just did something wrong in the loop-recur examples, but I don't see where the issue would be

13:11 I was also surprised peek-pop traversal of the vector wasn't as fast as first-next - but not completely relevant

13:12 tbaldridge: mikerod: they're slow because you're using first/next to access the vector

13:13 your first two examples are using the .reduce method on the input vector, this will always be much faster, as it doesn't allocate lazy-seq cells.

13:14 mikerod: your first two examples eventually call this method: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/PersistentVector.java#L328

13:14 that'll be much faster than first & next

13:15 So I'd recommend refactoring the ArrayList example to use reduce. Keep the array list in the accumulator, and call .add on it with each item given to you.

13:19 dysfun: when i deploy an uberjar to my server and java -jar, i get an error saying my core class cannot be found. i've just looked inside the jar and there are AOT versions and the clojure source as well. the named main class is correct. any ideas?

13:20 it's built with leiningen

13:21 hiredman: dysfun: is the main class specified in the manifest?

13:21 * dysfun checks

13:23 dysfun: yes, Main-Class is correct in the manifest

13:24 hiredman: and what happens if you run java -cp your.jar your.main.Class

13:25 dysfun: "Could not find the main class: my.app. Program will exit"

13:25 hiredman: how sure are you that the class exists in the jar?

13:26 dysfun: zip -Tv | grep -v warning | less

13:26 er + the jar filename

13:26 hiredman: (zgrep)

13:26 dysfun: ooh, handy

13:26 hiredman: first thing to do is to blow away target or classes for lein to make sure nothing stale is in there

13:27 dysfun: there isn't anything stale because i don't have leiningen on the target machine

13:27 hiredman: dysfun: on the build machine

13:28 dysfun: okay, it'll take a minute to build and push

13:28 hiredman: the class reported in the "could not find the main class" error exactly matches your main class?

13:28 dysfun: okay, now i get "Warning: The Main-Class specified does not exist within the jar. It may not be executable as expected. A gen-class directive may be missing in the namespace which contains the main method.

13:29 hiredman: there you go

13:30 dysfun: right, so i've got :main ^:skip-aot my.app and :profiles {:uberjar {:aot []}}

13:31 if i don't disable aot, i get build errors

13:31 i think it's to do with running clojure-1.7.0-beta3

13:31 justin_smith: dysfun: my usual approach is to either use clojure.core as my main (supplying my ns as an arg) or make a very tiny namespace that implements the right magic for jsvc, and use require at runtime, plus resolve, to invoke my stuff dynamically after loading

13:31 hiredman: well, like, fix your build

13:32 dysfun: hrm, i could require at runtime, that could work

13:32 justin_smith: that avoids the issues that come with aot

13:32 hiredman: your build just sounds broken, I would wipe as much as possible from your project.clj and get it working from a clean slate

13:32 dysfun: while fixing it all would be lovely, i've already spent ages fiddling with toolchain

13:33 i suppose i probably don't need clojure 1.7 any more now i stopped using the latest clojurescript

13:37 mikerod: tbaldridge: I thought so, but I'm not exaclty sure what my alternatives are

13:38 tbaldridge: oh ok

13:38 I didn't see your second post

13:38 I was skeptical of the first/next stuff

13:41 tbaldridge: I also tried iterating over an ArrayList.get() instead of a PersistentVector

13:41 It still looked like transients win

13:42 tbaldridge: mikerod: the accessing is muddling your results I think. Perhaps just rewrite them all to use a loop with a counter instead of (vec (range ...))

13:42 mikerod: https://www.refheap.com/102093

13:43 tbaldridge: good point

13:43 tbaldridge: Then you're not "complecting" the testing of access with creation.

13:43 mikerod: I figured thesse were just sloppy comparisons

13:43 threw it together quick to try to gauge when it really matters if you are using a mutable Java collection vs transient vs persistent immutable

13:44 Then I started searching around online and didn't find anything too illuminating out there

13:44 dysfun: justin_smith: brilliant, i used a dynamic require and it works great. thanks!

13:44 mikerod: beyond transients outperforming their persistent counterparts - but I wanted to also try again Java mutation

13:44 Java-style*

13:47 tbaldridge: mikerod: dnolen has done some tests showing that transients outperform arrays on JS platforms, but no I haven't seen similar benchmarks on the JVM

13:48 perhaps that's just because collections are much more tunable on the JVM.

13:48 dnolen: tbaldridge: well JS arrays are really analagous ArrayList not fixed dimension arrays

13:49 so it's not surprising that transients wins, they don't have to resize as much

13:50 mikerod: dnolen: I have some experiments against Java primitive arrays too

13:50 tbaldridge: right, but on the JVM "faster" would probably depend on your needs and what JVM collections you used

13:50 mikerod: I still keep "winning" with transients

13:50 seems a bit impossible to me

13:50 so I figure I have something wrong still

13:51 I've also tried starting the ArrayList at the correct, final size. speeds it up slightly, but transient still wins

13:51 tbaldridge: https://www.refheap.com/102094

13:51 I think I'm keeping the pattern of access consistent here

13:55 tbaldridge: some things are different however. The latter one is doing boxed math on the i value

14:28 Bruce_Wayne: I am having trouble implementing re-com in one of my re-frame projects. Does anyone have re-com working?

14:34 looking to integrate this library:

14:34 https://github.com/Day8/re-com

14:35 dnolen: Bruce_Wayne: question more likely to be answered in #clojurescript

14:35 Bruce_Wayne: thank you!

15:06 whodidthis: emacs prelude seems cool but does anyone know where to start if im still not getting pairing ) added when typing (, my modes are(?) Clojure Projectile Pre

15:07 justin_smith: whodidthis: paredit is the mode that does that, also things like prelude are best to ditch as early as you can

15:08 because emacs has standard ways to manage libraries and installation, and using some hacked-up preset setup makes actually managing your own install harder, not easier, in the long run

15:10 pbx: justin_smith, i'm glad to hear you say that because i've had a hard time reconciling such setups with my regular but non-leet use of emacs.

15:11 luxbock: I started out using emacs-starter-kit, then I moved only the things I was actually using to my own setup, but now I eventually switched over to using Spacemacs, which is even more monolithic than Prelude is

15:11 stuartsierra: Most pre-built Emacs set-ups I've seen give you too many new things to learn at once.

15:11 luxbock: and I'm a pretty big fan of it

15:11 brainproxy: justin_smith: I have had nothing but success with prelude over several years and zero friction working with the standard mechanisms for libs and installations

15:11 luxbock: stuff breaks sometimes when I upgrade to the newest develop branch, but overall I really like having actively thought out and developed power user UI

15:11 tbaldridge: emacs-starter-kit was rather recently removed. It's now just a list of packages with instructions on how to do it yourself. Big fan of that now

15:11 brainproxy: prelude, ultra highly recommended in my book, but i realize opinions vary on this subject

15:12 stuartsierra: tbaldridge: glad to hear it

15:12 tbaldridge: They did a good job of walking through what each package does, and why you may or may not need it.

15:13 brainproxy: btw, I merge my fork with prelude's master branch almost every day (i.e. if there are changes) and in the several years I've been using it, only twice has that resulted in a problem requiring me to git reset

15:13 which is a testament to bbatsov's care in making sure that prelude is rock-solid

15:13 luxbock: the difference between now and when I was using the starter-kit before is that now that I've mostly wrapped my head around Emacs and can code in elisp then I can usually figure out pretty fast what broke and how when I upgrade

15:15 brainproxy: also, check out smartparens, an alternative to paredit, actively maintained

15:15 whodidthis: maybe ill do starter-kit instead, seems like a good idea

15:16 brainproxy: whodidthis: going back to your original question, it may be that smartparents isn't enabled

15:16 which is what prelude favors over paredit

15:17 did you copy the prelude-modules.el file from prelude/sample into ~/.emacs.d and uncomment the line for 'prelude-clojure?

15:25 whodidthis: sounds pretty crucial actually heh, thanks

15:25 brainproxy: sure thing

15:25 whodidthis: ill try prelude again after testing this starter-kit

15:25 brainproxy: sure

15:35 justin_smith: one of the complexities introduced by prelude is instead of emacs help, you now need prelude help

15:37 brainproxy: could be; I first started with it and Emacs in late 2011, when prelude was just getting its start as well; the newbie experience w/ prelude in 2015 may be different than mine, i will admit that :-)

15:37 I mainly remember spending time with plain old emacs help and fumbling around looking at prelude source ot understand what was giong on

15:37 *to

15:45 sdegutis: i too do not use prelude

15:46 i tried to make that rhyme but i didnt have the time

15:51 brainproxy: i guess my "bigger picture" view would be that a framework or starter kit that tends to hinder one's understanding and personal development of the Emacs environment is ultimately unhelpful; that hasn't been my experience with prelude, but it could affect others that way, i guess; i haven't worked with other kits, so can't really comment on them

15:52 sdegutis: bbl deadline

15:54 brainproxy: a general recommendation would be to study the source of one's kit of choice and understand what it's doing for you; then, move away from it or morph it into an environment that truly serves your needs

16:30 mikerod: is there any sane way to search through google groups along with sort topics by time etc? I search for these topics online and don't get much help. I feel I'm always struggling to try and use google groups to look through the clj stuff and find what I want.

16:30 am I just crazy?

16:31 hiredman: nope, google groups kind of suck

16:43 aaelony: hiredman: agree

16:47 mikerod: hiredman: good to know

16:59 http://dev.clojure.org/jira/browse/CLJ-1224 was bumped from major to critical recently

16:59 I was hoping that also meant, bumped to 1.7 release instead :P

16:59 but I think I'm too hopefully

17:00 however, critical does sound like a "big deal"

17:03 xemdetia: does jira have blocker like bugzilla

17:03 or does critical already mean escalated to the mooooon

17:12 fredfe: Will slamhound remove unused (:require)'d items?

17:15 mikerod: fredfe: I doubt it

17:15 that's a hard problem too

17:15 unused requires sounds very difficult to determine to me

17:15 which does bother me about Clojure semantics with loading

17:15 fredfe: Funny, I'd think discovering missing items would be a bigger accomplishment lol

17:15 mikerod: :require can cause a namespace to be loaded and compiled for the first time. This processing can have arbitrary environmental side-effects

17:16 1) define global vars 2) define protocols 3) extend protocols to types 4) create new Classes dynamically etc

17:17 arohner: mikerod: 5) run arbitrary clojure expressions at top-level

17:17 mikerod: So my point is, how do you know what an "unused" require is? If it was transitively already loaded by another namespace, that may be ok, but then you're relying on implicit dependencies of your own dependencies, which is a bad practice.

17:18 arohner: yeah, I was enumerating common ones. yes, it can certainly just do anything in the world of side effects.

17:18 this makes :require management tough from my experience

17:18 fredfe: Makes sense

17:18 mikerod: in larger libraries

17:18 I often review people's code and see that they do not specify :require's that they should

17:19 because it just happens to transitively be compiled for them

17:19 hiredman: :(

17:19 people are terrible

17:19 mikerod: Which is unreliable because it can change out from underneath and break your stuff. Typical transitive dependency issues like from Maven.

17:19 arohner: mikerod: I have a habit of only using aliased namespaces, to prevent that

17:20 mikerod: arohner: yes, I like aliasing a LOT

17:20 arohner: (:require [foo.bar :as bar]), then only ever use bar/

17:20 mikerod: I get scared when people use fully-qualified symbols - which obviously should be rare

17:20 but also, if you depend on some protocol extensions from another namespace. that can get messy.

17:21 I'm not saying all of this is "best practice" or anything though. I just see it come up often enough.

17:21 or you make some defrecords somewhere else

17:21 then people do an :import [my.other.ns RecType]

17:21 but they don't do a :require on [my.other.ns]

17:21 jarjar_prime: hello :)

17:22 mikerod: hello world!

17:22 jarjar_prime: is there a way to set lein deploy to use uberjar instead of the smaller one?

17:24 hiredman: you don't want that

17:25 jarjar_prime: hiredman: I'm using that to drop into artifactory (maven) and then pull that into a dockerfile

17:29 fredfe: Has anyone used Jenkins with clojure? Is this how it works: Job #1 Pull project from remote git and run tests (lein test--how to capture test results?) ---> Job #2 Run `lein ring uberjar` and Publish over SSH. But what is used to keep some jar versions in case I need to perform an arbitrary number of rollbacks?

17:31 hiredman: fredfe: jenkins can archive builds

17:31 fredfe: at work we just have jenkins capture the stdout of test runs and of course the pass/fail of the lein test run

17:32 we publish built artifacts to s3

17:32 the path on s3 as the version, so we have builds are archived on jenkins, but also on s3

18:11 andyf: fredfe: mikerod: Eastwood linter can determine when :use or :require'd namespace is not used within a namespace, modulo some bugs where it might not report correctly.

18:11 lein eastwood "{:add-linters [:unused-namespaces]}" https://github.com/jonase/eastwood#unused-namespaces

18:14 mikerod: andyf: how can it know that you aren't relying on the :require for load-compile side-effects?

18:14 I know that eastwood is powerful in terms of detecting symbol references

18:14 given that (I believe) it uses tools.analyzer to get the AST "big picture"

18:16 andyf: mikerod: I'm not sure what kind of examples you have in mind, but it does some magic, and not other magic :)

18:16 basically if you :require or :use a namespace, but do not reference any Vars def'd in that namespace, you get a warning that the namespace is unused.

18:16 It can be fooled, I am sure.

18:18 mikerod: andyf: having a :require to get the side effect of extend-protocol, extend-type, extend, etc

18:18 that's the most obvious one

18:18 I'm guessing that is bad practice, but it has came up quite a bit from what I've seen.

18:19 And as long as it can detect references to deftype'ed classes, that would eliminate my biggest other concern.

18:20 But don't get me wrong, I think eastwood is a great project. I was just more ranting over how :require can be tied to side-effects and makes it tricky.

18:21 I see a lot of people coming from Java that think of it as like :import - but it is a lot different to that. It potentially does a lot of things, import is just sugar

18:24 arohner: crazy idea of the day, I don't suppose it's possible to pass data from one nrepl to another?

18:25 andyf: Clojure is surprisingly mutable in terms of definitions of things and loading code, and I agree that makes some things tricky.

18:25 mikerod: arohner: if it is in a "pure" data form you should be able to copy/paste?

18:25 arohner: mikerod: yeah, but I'm thinking of a lot of data

18:25 mikerod: andyf: yes, that is the part I'm not a huge fan of... Perhaps it is inevitable though.

18:25 arohner: pr it to a file

18:25 read it from the file from the other process

18:26 andyf: If you treat Eastwood as "sometimes finds bugs I didn't find using other methods, but sometimes doesn't, and sometimes gives false warnings", i.e. like every other lint tool I've seen, then it might help you.

18:26 mikerod: edn, if you don't trust it.

18:26 andyf: I think that is a good way to put it. And I think eastwood can reveal a ton of things that are very helpful.

18:27 On the topic of mutable environmental stuff, it looked like https://github.com/mikera/kiss

18:27 Tried to address this with "Immutable environments " I was very interested to see where that was going

18:28 "immutable all the things"

18:31 andyf: mikerod: You can ask mikera to see if anyone has enhanced it since his proposal, but I think the status is something like "you can patch your own local copies of Clojure all you like, subject to the license". Core team probably doesn't consider it anywhere near high priority for including in the standard distribution.

18:35 Drick: http://i.imgur.com/cbOGiI8.jpg

18:39 m1dnight_: Is there any way to make this fail: (if-let [{a :a} {:b 1}] (println "foo") (println "bar"))

18:39 Id hate to write an if test and only destructure in a nested let

18:39 (in the acutal use case {:b 1} would be a call to a function)

18:40 oh no nvm i was confused for a sec, carry on

18:48 mikerod: andyf: yes, I figured. I was just intrigued by the concept.

18:54 reilly3000: anybody know of updates to arcadia since clojure/west?

19:00 Drick: {`}

19:36 jjttjj: i have a list of heavily nested maps containing things of many types. im trying to end up with a human readable list of every type that appears in the thing. I've been trying to use postwalk to just amass keep conjing an atom but think i might be on the wrong track... is there a way to only deal with leaf nodes?

19:39 hiredman: ,(doc tree-seq)

19:40 clojurebot: "([branch? children root]); Returns a lazy sequence of the nodes in a tree, via a depth-first walk. branch? must be a fn of one arg that returns true if passed a node that can have children (but may not). children must be a fn of one arg that returns a sequence of the children. Will only be called on nodes for which branch? returns true. Root is the root node of the tree."

19:40 jjttjj: hiredman: perfect, thanks!

20:10 crocket: http://dpaste.com/3KYMW8W

20:11 How do I consolidate "else2" and "else1" on http://dpaste.com/3KYMW8W ?

20:12 I want "else1" to be evaluated and returned if the innermost if-let form's binding evaluates to false.

20:12 Does anyone have any idea?

20:13 justin_smith: (let [a "3" b "4"] (if (and a b) "then" "else1")

20:13 if "4" should not be evaluated if "3" was nil, then that can be handled also

20:14 (let [a "3" b (when a "4")] (if b "then" "else1")

20:14 if a is nil, b will be nil, guaranteed

20:14 crocket: justin_smith, People are not going to write that by hand.

20:15 justin_smith: I write code like that by hand

20:15 crocket: ouch

20:15 justin_smith: you can use cond

20:15 crocket: There is no cond-let.

20:16 justin_smith: sure, the let thing is a convenience, and it's not available for multiple bindings in any useful way

20:16 crocket: I'm looking for something like (if-let [[result1 result2] (map-all not-nil? ["1" nil])] (+ result1 result2))

20:17 justin_smith: doesn't work though

20:17 it isn't there

20:17 crocket: What isn't?

20:17 justin_smith: that version of if-let does not do what you want

20:17 *that usage

20:17 destructuring + if-let = bugs

20:17 amalloy: welllll

20:17 crocket: That's just a wtf.

20:18 justin_smith: ,(if-let [[a b] [nil nil]] "OK")

20:18 clojurebot: "OK"

20:18 justin_smith: crocket: that's just how it works

20:18 amalloy: it's a bit more nuanced than that, as i'm sure justin_smith knows. you can destructure with if-let as long as you know what is going on

20:18 crocket: ,(if-let [[a b] nil] "ok" "no")

20:18 clojurebot: "no"

20:18 justin_smith: amalloy: right, but what I am saying is that the semantics he wants do not exist in the core language

20:19 amalloy: justin_smith: i'm just taking issue with "destructuring + if-let = bugs"

20:19 crocket: justin_smith, ^^

20:19 justin_smith: sure, yeah, that was overstating it

20:19 amalloy: everything else you're saying i've only glanced at but is probably spot-on

20:19 crocket: ,(if-let [[a b] nil] "ok" "no")

20:19 clojurebot: "no"

20:19 justin_smith: yes, I saw that the first time

20:19 but that doesn't do what you want

20:20 crocket: A hypothetical function map-all should return nil if any element evaluates to nil.

20:20 justin_smith: ,(if-let [[a b] ()] "OK")

20:20 clojurebot: "OK"

20:20 justin_smith: so even if you remove nil, it still doesn't do what you want

20:20 OK

20:22 crocket: (if-let [[a b] (reduce (fn [vec el] blahblah....) (map identity ["1" nil]))] "ok" "no")

20:22 Ok, this is becoming complex...

20:22 I need to write a macro.

20:22 justin_smith: crocket: to me that is much more complex than using when / and

20:24 crocket: Without (when-let), you have to evaluate something again and bind it to a local binding.

20:24 Thus, it leads to double evaluation.

20:24 justin_smith: crocket: not in the version I proposed

20:24 crocket: justin_smith, Show me your code

20:24 justin_smith: (let [a (f) b (and a (g))] (if b (h))

20:24 no double eval

20:25 crocket: justin_smith, What if you have to do that for 7 bindings?

20:25 justin_smith: and (g) is not invoked if (f) was nil

20:25 crocket: What if you have to do that for 7-8 bindings repeatedly?

20:25 justin_smith: crocket: then a macro that checks the prior at each step

20:25 amalloy: crocket: if you need to bind 7 separate things to distinct local variables your function is probably a bit lacking in purpose anyway

20:26 crocket: amalloy, 'probably' is not enough.

20:26 amalloy: crocket: the language provides you with the tools to do whatever wacky things you want. there's no "not enough" you can say about the core language, unless it makes something important impossible

20:27 crocket: I meant 'probably' didn't convince me.

20:27 justin_smith: ,(let [vaues [a b nil]] (if-not (some nil? values) "OK")) ; something like this?

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

20:27 justin_smith: ,(let [vaues [:a :b nil]] (if-not (some nil? values) "OK")) ; something like this, I meant

20:27 clojurebot: #error {\n :cause "Unable to resolve symbol: values in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: values in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6543]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve symbol: values in t...

20:28 justin_smith: ,(let [values [:a :b nil]] (if-not (some nil? values) "OK")) ; should have tested it first

20:28 clojurebot: nil

20:30 crocket: ,(if-let [will-you-dance-with-me nil] "ok" nil)

20:30 clojurebot: nil

20:30 crocket: ,(doc if-not)

20:30 clojurebot: "([test then] [test then else]); Evaluates test. If logical false, evaluates and returns then expr, otherwise else expr, if supplied, else nil."

20:31 crocket: justin_smith, That ends up evaluating every binding.

20:31 I wonder if a lazy sequence could be used for preventing evaluation.

20:32 justin_smith: as long as you watch out for chunking

20:32 crocket: ouch

20:32 chunks of 32 items

20:32 justin_smith: but, eg lists are not chunked

20:32 so you could use a list of functions

20:32 but a reduce might make more sense unless you have another reason to want laziness

20:33 with a reduced case if any return nil

20:34 (reduce (fn [results f] (if-let [r (f)] (conj results r) (reduced nil))) [] [f g h ...])

20:34 crocket: justin_smith, That's very hard to read.

20:34 Can you use dpaste.com ?

20:34 justin_smith: one moment

20:35 https://www.refheap.com/102103

20:37 crocket: I never knew about reduced.

20:37 justin_smith: it makes reduce at least twice as useful I think

20:38 crocket: Does reduced terminate reduce right away?

20:38 justin_smith: yes

20:38 crocket: Or, does reduce consume a sequence until the end?

20:38 justin_smith: ,(reduce (fn [a n] (if (> n 10) a (+ n a)) 0 (range))

20:38 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

20:39 crocket: ,(doc range)

20:39 clojurebot: "([] [end] [start end] [start end step]); Returns a lazy seq of nums from start (inclusive) to end (exclusive), by step, where start defaults to 0, step to 1, and end to infinity. When step is equal to 0, returns an infinite sequence of start. When start is equal to end, returns empty list."

20:40 crocket: ,(take 10 (range))

20:40 clojurebot: (0 1 2 3 4 ...)

20:40 justin_smith: ,(reduce (fn [a n] (if (> n 10) (reduced a) (+ n a))) 0 (range))

20:40 clojurebot: 55

20:40 justin_smith: range returns an indefinite sequence - so (range) won't return for a while if eagerly consumed

20:40 crocket: How does clojure catch that?

20:40 justin_smith: catch which?

20:41 crocket: How does clojure catch an infinite evaluation?

20:41 justin_smith: it generally just lets it happen, but clojurebot has print-level and print-length set up to avoid indefinite printing, which with something lazy, prevents indefinite forcing

20:42 ,(reduce + (range))

20:42 clojurebot: eval service is offline

20:42 justin_smith: that's because it timed out, of course

20:43 crocket: I wish clojure caught infinite loops.

21:06 wei: interesting puzzle for you all: I want to walk a nested vector and build up an array of indices. e.g. (indices [1 [1 [1 1]]]) => [[0] [1 0] [1 1 0] [1 1 1]]

21:07 gfredericks: ,(defn indices [v] (map-indexed (fn [i x] (if (vector? x) (map #(cons i (indices %)) x) (list i))) v))

21:07 clojurebot: #'sandbox/indices

21:07 gfredericks: ,(indices [1 [1 [1 1]]])

21:07 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Long>

21:08 gfredericks: ,(defn indices [v] (map-indexed (fn [i x] (if (vector? x) (map #(cons i %) (indices x)) (list i))) v))

21:08 clojurebot: #'sandbox/indices

21:08 gfredericks: ,(indices [1 [1 [1 1]]])

21:08 clojurebot: ((0) ((1 0) (1 (1 0) (1 1))))

21:08 gfredericks: ,(defn indices [v] (apply concat (map-indexed (fn [i x] (if (vector? x) (map #(cons i %) (indices x)) (list i))) v)))

21:08 clojurebot: #'sandbox/indices

21:08 gfredericks: ,(indices [1 [1 [1 1]]])

21:08 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Long>

21:08 gfredericks: poopsiedoodle

21:09 ,(defn indices [v] (apply concat (map-indexed (fn [i x] (if (vector? x) (map #(cons i %) (indices x)) [[i]])) v)))

21:09 clojurebot: #'sandbox/indices

21:09 gfredericks: poopsiedoodle

21:09 whoops false poopsiedoodle, meant to scrollback farther

21:09 ,(indices [1 [1 [1 1]]])

21:09 clojurebot: ([0] (1 0) (1 1 0) (1 1 1))

21:10 gfredericks: phew okay there we go

21:10 wei: ^

21:12 wei: nice!!

21:13 (inc gfredericks)

21:13 lazybot: ⇒ 139

21:14 gfredericks: hoo ray a prime

21:16 wei: wish there was a mapv-indexed

21:31 crocket: http://dpaste.com/36F19FE generates an error.

21:31 How can I fix it?

21:50 How do I make a macro call itself safely?

21:57 I created the first working prototype of if-let-all. http://dpaste.com/0S2VYM5

21:57 Yay

22:00 Can anyone evaluate if-let-all?

22:02 gfredericks: crocket: I found a bug

22:02 crocket: What is it?

22:02 gfredericks: (if-let-all [x (seq ())] :true-case :false-case)

22:02 crocket: Why is it a bug?

22:02 gfredericks: ,(if-let [x (seq ())] :true-case :false-case)

22:03 clojurebot: :false-case

22:03 crocket: oops

22:03 gfredericks: this is a common macro pitfall

22:03 you're preforming your logic on the forms at compile-time

22:04 (coll-or-nil only runs once when you're compiling the macro call)

22:07 crocket: hmm...

22:07 I think coll-or-nil should evaluate...

22:08 gfredericks, How about http://dpaste.com/3B45AFB ?

22:08 (eval f) fixes the bug.

22:08 gfredericks: and that's the next pitfall :)

22:08 crocket: What is it?

22:08 gfredericks: using eval to fix the first pitfall

22:08 here's the next bug

22:09 (let [a ()] (if-let-all [x (seq a)] :true-case :false-case))

22:09 crocket: ,(let [a ()] (if-let [x (seq a)] :true-case :false-case))

22:09 clojurebot: :false-case

22:10 hasket: What are people's opinion on haskell vs clojure for web dev

22:10 (backend)

22:10 crocket: gfredericks, Do you know a solution?

22:10 hasket, Why don't you try them?

22:11 For web development, both languages are far superior to ruby, java, and python.

22:11 gfredericks: crocket: you need to be doing the logic at runtime, not compile time; to do that you need to emit code that does the logic

22:11 crocket: I'd play with macroexpand-1

22:11 that might give more insight into where things aren't working

22:12 hasket: I know Haskell quite well. I'm just curious as to what clojure has to offer (I know it's an amazing language and I've played around with it a bit, but not extensively).

22:12 crocket: macroexpand-1 doesn't help me with (let [a ()] (if-let-all [x (seq a)] :true-case :false-case))

22:12 hasket, One word, ClojureScript.

22:12 Clojure & ClojureScript

22:12 gfredericks: crocket: you can macroexpand just the if-let-all part

22:13 hasket: crocket, yeah I've tried GHCJS and it's a pain in the butt to install and keep track of dependencies

22:13 lein seems to work much better than cabal

22:14 But I'm in love with Haskell's type system is the issue. Does clojure provide any kind of type safety? Or some assurance of safety?

22:14 crocket: hasket, You can use PureScript.

22:14 hasket, clojure has different ways of ensuring interface integrity than haskell....

22:15 skeuomorf: hasket: https://github.com/clojure/core.typed

22:15 crocket: That being said, haskell is better at checking compile time errors.

22:16 hasket: crocket, yeah that's what it seems like, but I'm fascinated by the language also. I love functional programming. One of my favorite things about haskell is that you can write out the types, then if you don't know the type of something should be in your code, you can leave a hole and haskell will figure out relevant types in scope and tell you what type the hole has. What drew you to clojure? I love the talk "simple made easy" which brought me

22:16 here :)

22:17 crocket: hasket, It's simple.

22:17 It's concise.

22:18 hasket: Cool, I'm gonna learn it. I love learning new languages anyways so it's not even necessarily about trying to do anything with it rather than the beauty of the language itself (at least for me). Clojure looks like an elegant language

22:19 And compiling with ghc and cabal in haskell can be a pain in the butt

22:22 crocket: gfredericks, How do you make if-let-all work?

22:22 It seems I can't evaluate values in if-let-all.

22:23 Because values are defined outside the scope.

22:23 gfredericks: crocket: your macro shouldn't be evaluating them

22:23 macros are about rewriting the code

22:23 crocket: gfredericks, Does it mean I have to duplicate the else clause as many times as bindings?

22:23 gfredericks: no

22:23 crocket: The use of (if-let) leads to multiple instances of the same else clause.

22:24 gfredericks: but you have coll-or-nil

22:24 so you can write this with only one if-let

22:24 crocket: ????

22:25 gfredericks, I thought about nesting if-let.

22:25 If you nest if-let forms, you'll get multiple else clauses.

22:26 gfredericks: (if-let [[a b c] (coll-or-nill [x y z])] true-case false-case)

22:26 ^ you want to write it that way, right?

22:26 crocket: Yes, I did

22:26 gfredericks: so your macro needs to emit code that looks like that

22:26 the macro does *not* need to call coll-or-nil itself

22:26 crocket: ok

22:27 gfredericks: in your original code it does, because of the unquoting

22:27 ~(coll-or-nil values)

22:27 clojurebot: I don't understand.

22:27 crocket: good

22:27 gfredericks, Does it mean I have to expose coll-or-nil?

22:27 gfredericks: you mean make it not-private?

22:27 crocket: Yes

22:28 I wanted to make it private.

22:28 with defn-

22:28 gfredericks: you cannot do that easily

22:28 crocket: I should probably inline coll-or-nil in if-let-all.

22:29 gfredericks: btw if you're going to be using this for serious stuff you might want to think about the fact that your current approach doesn't short-circuit -- it will evaluate all of the "values" no matter which ones are nil

22:29 you also can't use previous values in the later expressions

22:33 crocket: http://www.infoq.com/presentations/macros-clojure-west-2013

22:37 crocket: gfredericks, Does anyone have a better version of if-let-all?

22:39 gfredericks: prismatic/plumbing and flatland/useful are a couple places to check

22:39 I don't often find myself wanting it so I'm not sure

22:42 if I had to write it I'd probably use a function or a sentinel to avoid the repeated else clause problem

22:42 tstout: What are the scope rules of a namespace? For example, can a single file define multiple namespaces? Can multiple files contribute to the same namespace?

22:42 gfredericks: (and so still use nested if-lets)

22:42 tstout: there aren't rules about that, only conventions

22:42 tstout: one-to-one is the convention, and there are probably a lot of tools that assume it

23:03 crocket: By the way, when-let doesn't have else clause problem.

23:07 gfredericks: when-let doesn't have an else at all

23:08 figoe: Something weird

23:08 user=> (into {} (list (vector :a 3))) => {:a 3}

23:08 user=> (into {} (list (list :a 3))) => ClassCastException clojure.lang.Keyword cannot be cast to java.util.Map$Entry clojure.lang.ATransientMap.conj (ATransientMap.java:44)

23:09 Any ideas? :)

23:09 gfredericks: figoe: it's a little weird but that's how it works

23:10 pairs for maps have to be vectors

23:10 figoe: Yes, just got bitten by ... heh

23:10 Guess I gotta do a walk to convert the nested structure to vector or some way

23:11 crocket: gfredericks, When do you use if you want something like if-let-all?

23:14 When -> What

23:16 gfredericks: crocket: I think I rarely need more than two clauses and so I just tolerate a bit of repetition

23:16 mbuf: in the "Language of the System" talk, it was mentioned that Clojure has the notion of system namespace. Are there any examples to illustrate this?

23:17 andyf: tstout: I'm a little late in answering, but Clojure's require and use determine the source file name to read based upon the namespace name, and check that the namespace has been defined after loading the file. You could define additional namespaces in that same file with other namespace names, but you could not require or use those namespaces successfully from that file.

23:17 gfredericks: mbuf: I can't remember him saying that nor can guess what it means; any further context?

23:17 mbuf: gfredericks, like the use of namespaces in datomic with zookeeper and riak

23:18 gfredericks: mbuf: still nothing, sorry :/

23:18 crocket: I guess people haven't needed to use a lot of bindings in if-let.

23:18 gfredericks: crocket: I'll write one up in a minute

23:19 andyf: crocket: A multiple-binding if-let has been asked about multiple times over the last few years on the Clojure Google group. Different people have written different variants of it as macros.

23:22 ToBeReplaced: seems like too much control-flow to put into the language itself... i think i like that you need to define your own so that you have to decide the semantics you want

23:23 and the "if all of these bindings are non-nil then do this else that" version is very easy to write and a good exercise if you haven't written a binding macro before

23:23 mbuf: gfredericks, https://www.youtube.com/watch?v=ROor6_NGIWU 36:00 - 37:30

23:26 gfredericks: mbuf: I'm can't listen to noise atm, sorry

23:27 mbuf: gfredericks, okay

23:27 cfleming: gfredericks: I'm going to tell Rich you said that

23:28 gfredericks: cfleming: no no! don't tell him! oh god

23:28 I didn't mean that kind of noise

23:28 oh no

23:28 * gfredericks looks frantically around the room for some way to get himself out of this mess

23:28 cfleming: That was an even better reaction than I was hoping for

23:29 gfredericks: now he's never going to accept my patch for CLJ-1237

23:30 cfleming: That does look like it would have been difficult to debug

23:30 gfredericks: and then it happened to my teammate a year later!

23:41 crocket: give this a try https://www.refheap.com/102107

23:42 crocket: Jesus

23:45 gfredericks, Is it better to call recur instead of self in self?

23:45 gfredericks: crocket: it's impossible

23:45 it's not a tail call

23:45 crocket: impossible?

23:46 gfredericks: if you try it you'll get a compile error

23:46 crocket: I don't know what self does.

23:46 gfredericks: that's just a name I gave the function

23:47 or you mean what that function does

23:47 it sets up (if-let [a x] (if-let [b y] (if-let [c z] [a b c])))

23:47 which gives you short-circuiting and visibility of previous results

23:48 crocket: What is short-circuiting?

23:49 gfredericks: if x is falsy it won't evaluate y or z

23:53 crocket: gfredericks, (if-let-all [a 2 b 2] "ok" no") is translated to something like (let [temp [a b]] (if temp (let [[a b] temp] "ok") "no"))

23:54 gfredericks: crocket: that approach doesn't give you short-circuiting

23:54 crocket: Whut

23:54 gfredericks, I used https://www.refheap.com/102107

23:58 gfredericks: when I expand it I get (if-let [[a b] (if-let [a 2] (if-let [b 2] [a b]))] "ok" "no")

23:58 which is short-circuiting

23:59 you can try (if-let-all [a (do (println "a") nil) b (do (println "b") 2)] "ok" "no") to test out short-circuiting properties

Logging service provided by n01se.net