#clojure log - Oct 29 2014

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

0:00 justin_smith: numberten: oh, agent uses nprocessors+2 as well

0:00 numberten: magic number I guess

0:00 bbloom: puredanger: are you saying you can always use two more threads?

0:00 heh

0:00 puredanger: exactly

0:00 justin_smith: numberten: it's core.async that multiplies by two and then adds 42 https://github.com/clojure/core.async/blob/aefbe7ad7e68f89f2ca584cd2fcd1bdf6fe8a601/src/main/clojure/clojure/core/async/impl/exec/threadpool.clj

0:01 I was misremembering

0:01 numberten: that's also weird..

0:01 clojurebot: Titim gan éirí ort.

0:01 justin_smith: ~that

0:01 clojurebot: that is not the forget syntax

0:01 justin_smith: how meta, clojurebot

0:02 numberten: what does ~ do for clojurebot?

0:02 joshhead: *2 then +42? that seems pretty arbitrary

0:02 justin_smith: numberten: it asks him for a factoid

0:02 ~factoid

0:02 clojurebot: Excuse me?

0:02 numberten: ~justin_smith

0:02 justin_smith: ~botsnack

0:02 clojurebot: justin_smith is sits on a throne of lies

0:02 Thanks! Can I have chocolate next time

0:03 numberten: heh

0:03 justin_smith: numberten: a youthful indescretion preserved for all time, or until the sqlite db holding the factoids gets wiped

0:03 TEttinger: ~ask

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

0:04 justin_smith: bodie_: https://github.com/swannodette/om/wiki/Cursors is the doc I found

0:14 bbloom: justin_smith: i think i'm going to abuse Rhino, since it has a js parser and code generator... although it's private impl details i may have to hack around to get at

0:26 justin_smith: bbloom: interesting

0:27 what's the default equality method that #{} uses?

0:27 it seems not to be .equals

0:27 ,(deftype Tuple [a b] Object (equals [this other] (and (= (.a this) (.a other)) (= (.b this) (.b other)))) (toString [this] (str "<" (.a this) "," (.b this) ">")))

0:27 clojurebot: sandbox.Tuple

0:28 justin_smith: ,(into #{} [(Tuple. 0 0) (Tuple. 0 0) (Tuple. 0 0)])

0:28 clojurebot: #{#<Tuple <0,0>> #<Tuple <0,0>> #<Tuple <0,0>>}

0:28 justin_smith: ,(apply = [(Tuple. 0 0) (Tuple. 0 0) (Tuple. 0 0)])

0:28 clojurebot: true

0:28 justin_smith: I implemented equals, = returns true, but a set doesn't consider them unique

0:29 *identical

0:38 amalloy: justin_smith: you didn't implement hashCode

0:38 justin_smith: amalloy: yeah I figured it out http://stackoverflow.com/questions/26622511/clojure-value-equality-and-sets/26622863#26622863

1:48 Balveda: Say I've got a map like so

1:48 {:names [{:surn "A" :givn "B"} ... {:surn "X" :givn "Y"}]}

1:50 justin_smith: OK

1:52 egghead: very nice Balveda

1:52 Balveda-2: huh, I cut out

1:52 egghead: :)

1:52 Balveda: Anyways, yeah

1:53 I've been having some issues with a function because of that for a week or so and through some debugging I found out that what is wrong is that I'm doing (map-indexed list x-map) and that just gives me one item with everything in it

1:54 justin_smith: Balveda: I think I did not see the "because of that" you refer to

1:54 nathan7: 06:47:50 < Balveda> {:names [{:surn "A" :givn "B"} ... {:surn "X" :givn "Y"}]}

1:54 that's all we got

1:54 Balveda: AH

1:54 <Balveda> I want map-indexed to get me 0 {:surn "A" :givn "B"} 1 {:surn "C" :givn "D"} etc

1:54 <Balveda> What fn could I feed it?

1:54 Then everything else

1:55 My connection's being pretty terrible today unfortunately

1:55 egghead: Balveda: i think you're looking for update-in ?

1:55 justin_smith: ,(map-indexed list (:names {:names [{:surn "A" :givn "B"} {:surn "X" :givn "Y"}]}))

1:55 clojurebot: ((0 {:surn "A", :givn "B"}) (1 {:surn "X", :givn "Y"}))

1:55 Balveda: hm..

1:57 Balveda-2: I'm actually doing something like that but it's not quite doing this

2:01 Balveda: jeez

2:01 anyways

2:01 I saw your code, justin_smith, and I am actually doing something like that

2:01 It's all in cljs, Hoplon in particular

2:01 justin_smith: OK

2:02 Balveda: but the functionality should be similar

2:02 justin_smith: right, all of that above should just work in cljs

2:09 vIkSiT: hello all

2:09 I have a fn that takes a few args : (myfn a b c :k v :k2 v2 ... )

2:10 in general, the v can be another complex structure

2:10 eg

2:10 :k {ns2/myfn {:k' :v' ... })

2:10 Id like to create a macro that allows me to return the args portion that are key/vals

2:10 so

2:10 (myfn a b c (mymacro))

2:10 should give me

2:11 (myfn a b c :k v :k1 v1 ...)

2:11 how would I do this?

2:11 As you might imagine, these key values need to be constructed piecemeal based on input and i'd like to abstract it out from myfn

2:11 ideas?

2:12 justin_smith: are all of those instances of myfn the same function?

2:12 vIkSiT: oh sorry no

2:12 that should be (ns2/anotherfn)

2:13 I guess what I can't figure out is - what should be the return type of this macro/function that returns these kv pairs?

2:13 justin_smith: vIkSiT: macros cannot transform an outer form

2:13 they only transform what is inside them

2:13 not what wraps them

2:13 vIkSiT: right

2:14 I guess my question is more on - if I have to call (myfn a b c & args)

2:14 how do I get these args from some function

2:14 justin_smith: apply

2:14 vIkSiT: hmm

2:15 what's a good example?

2:15 (defn myfn [a b c & args]

2:15 (prn a b c args))

2:16 (myfn 1 2 3 :k1 'v1 :k2 'v2) -> 1 2 3 (:k1 v1 :k2 v2)

2:16 justin_smith: ,(apply (fn [& {:keys [a b c]}] [c b a]) (apply concat {:a 0 :b 1 :c 2}))

2:16 clojurebot: [2 1 0]

2:16 justin_smith: the extra apply concat is because & {:keys ...} sucks

2:16 vIkSiT: sorry whats going on here again?

2:17 justin_smith: ,(def args{:a 0 :b 1 :c 2})

2:17 clojurebot: #'sandbox/args

2:17 justin_smith: ,(defn dothing [& {:keys [a b c]}] [c b a])

2:17 clojurebot: #'sandbox/dothing

2:17 justin_smith: ,(apply dothing (apply concat args))

2:17 clojurebot: [2 1 0]

2:17 vIkSiT: ah hmm

2:18 justin_smith: or you could just not use & {:keys ...}, and everything is suddenly much simpler

2:19 vIkSiT: sadly its not my function. library

2:19 justin_smith: vIkSiT: the apply concat is needed to put the map in the shape that & {:keys ...} needs

2:20 vIkSiT: justin_smith, trying to wrap my head

2:21 so what happens when dothing has [a b c & args]

2:21 how would I use it?

2:21 justin_smith: (apply dothing a b c (apply concat args))

2:21 (if args is a map)

2:21 ,(apply + 1 2 3 [4 5 ])

2:21 clojurebot: 15

2:22 justin_smith: only the last arg is unwrapped, the rest are used as normal

2:23 vIkSiT: hmm

2:29 justin_smith - one issue here

2:29 (apply concat mymap)

2:29 gives (:k1 v k2 v...)

2:29 its a list

2:29 whereas what I want is the values themselves

2:29 justin_smith: just the values?

2:30 vIkSiT: ,(defn myfn [a b c & args]

2:30 (prn a b c args))

2:30 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

2:30 justin_smith: use vals then

2:30 vIkSiT: sorry I mean

2:30 (apply myfn 1 2 3 (flatten (apply concat {:k1 1 :k2 3})))

2:30 1 2 3 (:k1 1 :k2 3)

2:30 justin_smith: ,(vals {:a 0 :b 1 :c 2 :d 4})

2:30 clojurebot: (2 1 4 0)

2:30 vIkSiT: but I want

2:30 justin_smith: you don't need flatten

2:30 vIkSiT: 1 2 3 :k1 1 :k2 3

2:31 justin_smith: vIkSiT: that is the point of apply

2:31 vIkSiT: you can't alter the args to myfn inside one of its args, that's just not a thing

2:31 clojurebot: I don't understand.

2:31 justin_smith: so you use apply

2:31 vIkSiT: hmm

2:32 justin_smith: there is no way to wrap your map such that it alters the arg list - but apply will construct a new arg list

2:32 and also, that flatten is not needed, and can break things

2:32 ~flatten

2:32 clojurebot: flatten is rarely the right answer. Suppose you need to use a list as your "base type", for example. Usually you only want to flatten a single level, and in that case you're better off with concat. Or, better still, use mapcat to produce a sequence that's shaped right to begin with.

2:32 justin_smith: I've never actually ever needed flatten

2:35 vIkSiT: is the issue you are describing with myfn that you want myfn to make a single collection of all its args?

2:35 vIkSiT: i'm just wrapping my head around how this apply is working with the concat map

2:35 hmm

2:35 justin_smith: (defn otherfn [a b c & args] (println (conj args c b a)))

2:35 ,(defn otherfn [a b c & args] (println (conj args c b a)))

2:35 clojurebot: #'sandbox/otherfn

2:36 justin_smith: ,(apply otherfn 1 2 3 [4 5 6])

2:36 clojurebot: (1 2 3 4 5 ...)\n

2:36 justin_smith: ,(defn otherfn [a b c & args] (apply println (conj args c b a)))

2:36 clojurebot: #'sandbox/otherfn

2:36 justin_smith: ,(apply otherfn 1 2 3 [4 5 6])

2:36 clojurebot: 1 2 3 4 5 6\n

2:36 vIkSiT: aah

2:36 got it

2:37 thanks justin_smith - that was super helpful :)

2:37 justin_smith: these also work:

2:37 vIkSiT: hmm?

2:37 justin_smith: ,(otherfn 1 2 3 4 5 6)

2:37 clojurebot: 1 2 3 4 5 6\n

2:37 vIkSiT: ah

2:37 yes

2:37 I understand how apply works now

2:38 justin_smith: ,(apply otherfn [1 2 3 4 5 6])

2:38 clojurebot: 1 2 3 4 5 6\n

2:38 justin_smith: ,(apply otherfn 1 [2 3 4 5 6])

2:38 clojurebot: 1 2 3 4 5 6\n

2:38 justin_smith: etc. etc.

2:38 vIkSiT: ah

2:39 makes sense

2:40 zRecursive: ,(doc ->)

2:40 clojurebot: "([x & forms]); Threads the expr through the forms. Inserts x as the second item in the first form, making a list of it if it is not a list already. If there are more forms, inserts the first form as the second item in second form, etc."

2:41 justin_smith: zRecursive: something that really helps with -> is using macroexpand

2:42 zRecursive: ,(macroexpand ->)

2:42 clojurebot: #<CompilerException java.lang.RuntimeException: Can't take value of a macro: #'clojure.core/->, compiling:(NO_SOURCE_PATH:0:0)>

2:42 justin_smith: ,(macroexpand '(-> 1 inc (println "is the number")))

2:42 clojurebot: (println (inc 1) "is the number")

2:42 vIkSiT: oh nice trick

2:42 zRecursive: great!

2:47 justin_smith: anyway, I'm staying logged in but turning in for the night, see you all later

2:48 Balveda-2: (inc justin_smith)

2:48 lazybot: ⇒ 107

2:49 fairuz: (+ 1 2)

2:49 clojurebot: 3

3:16 rurumate: Is defrecord "discouraged"?

3:20 arrdem: rurumate: in what sense?

3:20 rurumate: defrecord and deftype are not tools one typically reaches for right away if that's what you mean

3:20 rurumate: but they are working tools to be used when appropriate

3:25 rurumate: arrdem: The reader can not read records. When performance is not critical, should hash maps always be preferred? Records are also often used with protocols. Is it preferable to use defmulti / defmethod, and a dispatch field in hash maps instead? I'm looking for the best practice way here.

3:28 arrdem: rurumate: maps represent arbitrary mappings... for small symbolic mapings records or types are intended to do better

3:28 rurumate: the "best practice" is to prototype everything with plain maps, get that working and then use records if there is a gain from doing so

3:29 rurumate: Also, what happens when you have a record based protocol, and then use standard functions like assoc on your records. That can have unexpected results, because it converts the record to a map, and then the the correct dispatch of the prototype may not trigger. It seems that this can lead to subtle bugs and brittle code

3:30 arrdem: rurumate: no records are maps and remain records if you assoc or dissoc on them

3:30 rurumate: *dispatch of the protocol may not trigger

3:30 arrdem: if you merge on a record you can discard the record class and get a map back, but that's sketchy anway

3:33 rurumate: I think records are mostly awkward to work with

3:33 more awkward than regular maps, anyway

3:33 arrdem: that's definitely true

3:34 but maps are a less complex tool and are generally preferred so you shouldn't be surprised.

3:35 yekKhaste: Hi

3:35 Is clojure good for rapid web development?

3:36 Clojure can compare to something link rails for rapid web development?

3:39 rurumate: yekKhaste: it's a lisp, so it should be good for pretty much anything

3:39 yekKhaste: rurumate, Has it any full stack web framework that can compare to rails?

3:39 arrdem: yekKhaste: no

3:39 rurumate: there are some web frameworks, but I'm no authority on that. I doubt it has something as mature as rails

3:40 arrdem: rurumate: maturity I would debate, we certainly have no monolitic web platform ala rails

3:40 rurumate: it's what I meant to say

3:41 yekKhaste: And do you recommended clojure for freelancer developers?

3:41 arrdem: I have freelanced with Clojure successfully before...

3:41 many Clojure shops are contractors

3:41 rurumate: if you sell the source code to the client, better ask them if they want to maintain that

3:42 yekKhaste: Actual I am looking for some modern tool for rapid backend development

3:43 I what too know cant I use clojure or not

3:44 arrdem: I don't think there's any way we can reasonably make that assessment for you

3:44 I've used Clojure to build websites and contract as have others...

3:44 it can be done

3:44 whether it's appropriate for you... who knows

3:44 yekKhaste: arrdem, Thanks alot

3:45 arrdem: yekKhaste: sorry, that's the most helpfull answer I can give :/

4:16 sm0ke: ,(def a (atom (proxy [Object] [] (finalize [] (println "OK gcd..")))))

4:16 clojurebot: #'sandbox/a

4:16 sm0ke: ,(reset! a nil)

4:16 clojurebot: nil

4:16 sm0ke: ,(System/gc)

4:16 clojurebot: nil

4:16 sm0ke: can someone tell why it is not gc'd

4:17 hyPiRion: sm0ke: you'd probably need to run the gc 4-5 times

4:18 sm0ke: ran it 40 time

4:18 nothing

4:18 hyPiRion: hm

4:19 sm0ke: ,(repeatedly #(System/gc))

4:19 clojurebot: (nil nil nil nil nil ...)

4:19 sm0ke: no helo

4:19 no help either

4:20 opqdonut: sm0ke: a) there's no guarantee on running finalizers timely b) even if the finalizer was run, clojurebot might not print the line

4:20 sm0ke: opqdonut: i obviously was testing this on my machine!

4:20 opqdonut: that's what I thought :)

4:21 hyPiRion: well. The JVM doesn't guarantee that finalize is called on an object, so.

4:23 yocapybara: guys I'm being a dufus. Say I'm (/ 4 3) dividing 4 by 3, and I want to get 2 so to round up to nearest integer, I can't use quot as that rounds down, anything easy out of the box? or do I have to bring in BigDecimal?

4:23 sm0ke: wow, so i need to create a Java class to prove this now

4:24 pyrtsa: sm0ke: As nice as it would be, finalisers are not the way to deal with automatic cleanup of non-memory resources in Clojure.

4:24 ,(with-open [_ (reify java.lang.AutoCloseable (close [_] (println "closed")))] (println "working on it..."))

4:24 clojurebot: #<CompilerException java.lang.ClassNotFoundException: java.lang.AutoCloseable, compiling:(NO_SOURCE_FILE:0:0)>

4:24 pyrtsa: Doh.

4:24 ,(with-open [_ (reify java.io.Closeable (close [_] (println "closed")))] (println "working on it..."))

4:24 clojurebot: working on it...\nclosed\n

4:25 sm0ke: pyrtsa: i have a kind of situation where i cannot use with-open

4:25 pyrtsa: Macros (e.g. with-open) could be a way around it, though.

4:25 Elaborate?

4:25 opqdonut: ,(let [obj (proxy [Object] [] (finalize [] (println "OK gcd..")))] (.finalize obj))

4:25 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: No matching field found: finalize for class sandbox.proxy$java.lang.Object$ff19274a>

4:25 amalloy: sm0ke: *out* is not bound to anything while you're running a finalizer

4:25 opqdonut: ^ that's fishy

4:25 amalloy: ah of course

4:25 run by the finalizer thread

4:25 pyrtsa: amalloy: Wow, didn't know!

4:26 (inc amalloy)

4:26 lazybot: ⇒ 181

4:26 sm0ke: ok then

4:26 hyPiRion: yocapybara: (defn div-up [a b] (quot (+ a b -1) b))

4:26 sm0ke: ,(def b (atom 1))

4:26 clojurebot: #'sandbox/b

4:26 sm0ke: ,(def a (atom (proxy [Object] [] (finalize [] (swap! b inc)))))

4:26 clojurebot: #'sandbox/a

4:26 hyPiRion: amalloy: I tried setting an atom. No response there either.

4:26 sm0ke: ,(reset! a nil)

4:26 clojurebot: nil

4:27 sm0ke: ,(repeatedly 100 #(System/gc))

4:27 clojurebot: (nil nil nil nil nil ...)

4:27 sm0ke: ,@b

4:27 clojurebot: 1

4:27 amalloy: opqdonut: i doubt if you're allowed to call finalize yourself. it's a protected method

4:27 sm0ke: well

4:27 ,(repeatedly 100 #(System/gc))

4:27 clojurebot: (nil nil nil nil nil ...)

4:27 sm0ke: ,@b

4:27 clojurebot: 1

4:28 yocapybara: hyPiRion: that is intruiging, feel like my mind is turning to mush as I get older! - thanks, going to play in a repl

4:29 man I totally would have never have come up with that, I need to go back to junior high and retake math classes

4:29 sm0ke: ,(repeatedly 100 #(System/gc))

4:29 clojurebot: (nil nil nil nil nil ...)

4:29 sm0ke: ,@b

4:29 clojurebot: 1

4:30 sm0ke: i am going to keep doing this unless java gives up...you stuPUID JAAVvaaaVAa

4:30 amalloy: sm0ke: do it in your own repl. nobody needs to see that pasted here over and over

4:30 sm0ke: :)

4:31 i think its a problem with proxy

4:31 amalloy: also, like...who cares? finalizers are a disastrous antipattern; no correct program can rely on finalizers ever being run: http://blogs.msdn.com/b/oldnewthing/archive/2010/08/09/10047586.aspx

4:31 it's a curiosity, of course, and i'd like to know why this isn't working here

4:32 but cursing java seems like the wrong approach: any resolution you get here isn't really going to help you write a better program, as much as taking some other approach would help

4:33 hyPiRion: yocapybara: np – It's probably because I've tried to do round up integer divisions in the past :)

4:33 yocapybara: hyPiRion: I'm doing it in excel on loads of numbers to try to figure out what sorcery it is, man to think I used to do pages and pages of math in school :)

4:34 hyPiRion: It's not entirely foolproof though. I think I'd only use it for positive numbers.

4:35 yocapybara: hyPiRion: that's the context in which I'm using it so that's great

4:37 ro_st: using logback, i'd like to put everything in our code in one file, except for a couple namespaces, which i'd like to log to a different file. does anyone perhaps have an example logback.xml with this situation?

4:38 hyPiRion: yocapybara: Another way to write it is (+ 1 (quot (- a 1) b)) if that helps your understanding better.

4:38 I think it should be easier to "see" why that one works

4:41 yocapybara: hyPiRion: thanks :) will put that alongside, yes I think I can already see that one more

5:19 justin_smith: rurumate: the reader can read records

5:30 ,(defrecord Foo [x y])

5:30 clojurebot: sandbox.Foo

5:30 justin_smith: ,(Foo. 0 1)

5:30 clojurebot: #sandbox.Foo{:x 0, :y 1}

5:30 justin_smith: ,(= #sandbox.Foo{:x 0 :y 1} (Foo. 0 1))

5:30 clojurebot: #<RuntimeException java.lang.RuntimeException: Record construction syntax can only be used when *read-eval* == true>

5:30 justin_smith: bleh

5:31 anyway, it can be read

5:31 (require '[clojure.edn :as edn])

5:31 ,(require '[clojure.edn :as edn])

5:31 clojurebot: nil

5:32 justin_smith: ,(edn/read-string "#sandbox.Foo{:x 0 :y 1}")

5:32 clojurebot: #<RuntimeException java.lang.RuntimeException: No reader function for tag sandbox.Foo>

5:38 justin_smith: rurumate: this stuff doesn't work with clojurebot, but it all works in a standard clojure process / project, including reader literals in files

5:40 rurumate: justin_smith: thanks

5:41 danners: hey what is the best free tutorial for clojure, assuming no previous functional expericence ?

5:42 scottj: danners: braveclojure.com is the most popular one recently

5:44 danners: scottj: thanks

5:49 dysfun: hi all. i'm building a securitymanager that prevents user-provided code from being naughty. where naughty is largely defined as "can open files, use the network, generally perform I/O". obviously i can only lock on a class level. is there any wider mechanism for banning those operations?

5:49 * dysfun imagines if you look through the standard java library, there are literally hundreds of classes that do naughty things

5:50 sm0ke: dysfun: best would be to sandbox the process imo

5:51 or you can take a look at ##(File. "ssss")

5:51 lazybot: java.lang.IllegalArgumentException: Unable to resolve classname: File

5:51 sm0ke: ,(java.util.File. "aaa")

5:51 clojurebot: #<CompilerException java.lang.ClassNotFoundException: java.util.File, compiling:(NO_SOURCE_PATH:0:0)>

5:52 sm0ke: wowsad

5:52 ,(java.io.File. "aaa")

5:52 clojurebot: #<File aaa>

5:52 sm0ke: hurmm oh

5:53 dysfun: exactly

5:53 and let's not forget java.nio.* either

5:54 sm0ke: well File is just logical unless you do some operations further

5:54 ,(slurp "/etc/hosts")

5:54 clojurebot: #<SecurityException java.lang.SecurityException: denied>

5:54 sm0ke: see

5:55 dysfun: yes, but how much is that restricted? can i for example check the existence of a file or read the contents of a directory?

5:57 and where is the source for the bot's sandbox?

5:59 justin_smith: both clojurebot and lazybot are on github

5:59 dysfun: whose account?

5:59 justin_smith: $google github lazybot clojure

5:59 lazybot: [Raynes/lazybot · GitHub] https://github.com/Raynes/lazybot

5:59 justin_smith: $google github clojurebot

5:59 lazybot: [hiredman/clojurebot · GitHub] https://github.com/hiredman/clojurebot

6:00 dysfun: sweet

6:09 hugod: bbloom: stevedore was originally based on https://github.com/arohner/scriptjure

8:29 jonathanj: is there really no shorter way of writing (assoc xs (dec (count xs)) (str ":" (peek xs)))?

8:29 having to repeat "xs" three times seems crazy

8:30 clgv: jonathanj: time to write a function ^^

8:30 jonathanj: create a my-project.tools namespace and put that helper function there

8:32 jonathanj: e.g. (defn update-last [xs f & args] (apply update-in xs [(dec (count xs))] f args)) usable as (update-last [0 1 2] #(str ":" %))

8:33 ,(defn update-last [xs f & args] (apply update-in xs [(dec (count xs))] f args))

8:33 clojurebot: #'sandbox/update-last

8:33 clgv: ,(update-last [0 1 2] #(str ":" %))

8:33 clojurebot: [0 1 ":2"]

8:41 clgv: what is the recommended setup for tagged literals? such that they are usable in repl as well as in a standalone uberjar?

8:53 dysfun: the clojurebot sandbox. is the reason that it gets the parent of clojure.lang.RT's classloader so that it can load another version of clojure/

8:55 sorry, not the clojurebot sandbox, classlojure

8:56 * dysfun is doing too many things at once

8:57 clgv: dysfun: what is the context question?

8:57 did they fix the memory leaks in classlojure yet?

8:58 dysfun: i have no idea. i haven't used classlojure before

8:58 clgv: humm 1 year no change - so I guess not

8:58 dysfun: the problem i'm trying to solve is loading plugins written in approximately any jvm language

8:58 classlojure's code looks relatively straightforward to sort the classloader/only-load-from-this-jar problem

8:58 the securitymanager, well, that's going to be tedious, i have no doubt

8:59 however, i'm curious why they're doing a .getParent on clojure.lang.RT's classloader. the only reason i can think they would is because they explicitly advertise loading other versions of clojure

8:59 clgv: dysfun: there is clojail for the security stuff. it includes functions to configure jvm security mechanisms as well

9:00 dysfun: yes, i'm aware of clojail, but it seems targeted mostly at securing clojure, so we'll see how that one pans out

9:00 clgv: yeah but that includes the usual jvm stuff, afair

9:00 dysfun: *nod*. as i say, we'll see how it pans out

9:01 if i can reuse it, of course i'm thrilled to not have to do the tedious stuff

9:01 clgv: I think it's mostly specifying white lists of what is allowed

9:03 dysfun: be aware that you can only spin up a small number of classlojure classloaders due to memory leaks, when you use classlojure

9:03 dysfun: I tried that a while back

9:03 dysfun: i am not using classlojure

9:03 clgv: ok ^^

9:04 dysfun: mostly because the actual part that i need is several lines of code

9:04 clgv: applies when loading custom clojure version in any classloader as well

9:04 dysfun: i don't intend to support that model. at least not just yet

9:04 clgv: at least for versions before 1.6

9:04 dysfun: i'll probably support loading 1.6 when 1.6.1 comes out

9:04 but i can't see it actually breaking anything

9:05 clgv: huh? 1.7 will be next ;)

9:05 dysfun: oh

9:05 in any case, i certainly have no intention of supporting clojure < 1.6

9:06 i expect most of the plugins i'm loading will be java anyway

9:38 nicola: Hi, how to wrap InputStream into async channel?

9:42 ohpauleez: nicola: In the labs namespace, there's a function called `spool`that puts a sequence onto a channel

9:42 you can get a sequence from the inputstream and spool it onto the channel: https://clojure.github.io/core.async/#clojure.core.async.lab/spool

9:43 If you want to push an inputstream directly onto a channel without the extra allocations, you'll need to implement a new input stream that is passed the channel in the constructor

9:45 ApeShot: So I am having a very mysterious error in a clojure project: lein compile has suddenly started failing with a null pointer exception and all it tells me is that it is on core.clj:1

9:45 No information about which core (of which there are many)

9:45 teslanick: Does onto-chan not work with seqs?

9:45 ApeShot: How can I cajole lein into compiling one file at a time

9:45 Or get it to give me more verbose output

9:47 nicola: @ohpauleez thx

9:48 ohpauleez: nicola: teslanick: Good question - It should. spool can consume a lazy seq though (iirc), without realizing the entire seq

9:48 clgv: ApeShot: do you have a :main namespace?

9:48 nicola: @ohpauleez i want run long shell command and >! progress into channel

9:49 teslanick: ohpauleez: I hadn't thought of putting an infinite seq on a channel, but I can see why that would be useful.

9:49 ApeShot: Maybe I accidentally deleted it?

9:49 It is a play-clj template

9:49 So there is some magic I don't get

9:50 But i've been working and building the project successfully for quite some time

9:51 clgv: ApeShot: it is probably the core.clj in your project since you cant change those of the dependency libraries

9:51 ohpauleez: nicola: Yep, use `line-seq` and the io/reader. Then use spool with that seq and you should have what you're looking for

9:54 ApeShot: clgv: the play-clj template and usage doesn't have you define the main ns yourself

9:55 clgv: ApeShot: you didn't use a VCS by any chance?

9:55 the_danko: wow, just getting to macros in brave clojure! sweeet!

9:56 mikepence: oh, yeah

9:56 hey, I am doing a presentation to our local Java UG tonight re: fp and clojure

9:56 looking for some sample code to share, something public on github

9:56 real-worldish

9:56 not fib seq or other minimalist stuff

9:57 ApeShot: I hadn't yet put in a git repo

9:57 I know, stupid

9:57 clgv: ApeShot: then it would be a matter of a view minutes to find that error ;)

9:57 *few

9:58 ApeShot: clgv: That was the first thing I checked, and then remembered that I had been programming without a net

9:58 I have a back up that is a day old

9:58 Which still compiles

9:58 So I can laborously do ugly diggs

9:58 diffs

9:59 But I figured someone else might have an idea about how to target that search

9:59 Looking for the main ns might be the thing

9:59 clgv: ApeShot: you can use "meld" or similar to compare the whole project directories

9:59 ApeShot: I don't know how I could have messed it up

9:59 clgv: ApeShot: well not without seeing the code...

10:02 ApeShot: Ok, so my project.clj has a line : :main all-ghosts-vs-all-skeletons.core.desktop-launcher

10:03 And indeed this is the entry point of the project and it exists

10:03 japro: maybe that is a Halloween joke :o)

10:04 oh wait, that is your project name i guess... nvm

10:04 clgv: ApeShot: on rethinking it that really does not matter, find the core.clj you wrote yourself

10:05 ApeShot: I have many

10:05 For different modules of the project

10:05 clgv: you have many core.clj in one project? O_o

10:05 stuartsierra: ApeShot: Comment out `:main`, do `lein clean`, start a REPL and `require` your namespaces one by one.

10:05 ApeShot: I know with each line my failure to use git makes me look dumb

10:05 CookedGryphon: What are people's opinions on side-effecting actions in transducers?

10:05 ApeShot: I'm sort of new to how people organize clojure projects, but mine has a variety slightly coupled components parts, each of which has a directory and a core

10:06 CookedGryphon: I'm re-writing a number of go-loops in my code to simply use transducers and pipes, which is fine for all the functional transformations that push on a different value down a different channel... but some of the go loops were listening to events and then acting as a result...

10:06 if I follow the pattern of converting to transducers, that means a side-effecting map

10:07 but leaving it as go-loops bugs me in other ways (not composable, etc)

10:07 TimMc: clgv: ++ for meld

10:07 clgv: TimMc: :D

10:07 if you can afford it, BeyondCompare is nice as well

10:10 stuartsierra: CookedGryphon: Transducers are evaluated "eagerly" so side-effects are generally less of a problem than they would be with lazy-seqs.

10:14 hyPiRion: stuartsierra: huh? I was under the impression that transducers doesn't enforce strictness nor laziness. Or perhaps that's why you wrote "eagerly".

10:15 CookedGryphon: stuartsierra: yeah, this was my quandry, I know that in this case it would work, but is it encouraged, or is there a better way to separate out the side effecty stuff...

10:15 stuartsierra: hyPiRion: Yeah, it depends on how you "consume" them.

10:15 rurumate: CookedGryphon: can you paste an example of how you're rewriting the go-loops using transducers? I'd like to see that thanks

10:15 stuartsierra: Like how I'm giving "advice" right now.

10:15 hyPiRion: right

10:16 CookedGryphon: or is it just a case of, I'm using it on a channel, I can expect it to process as it goes

10:16 sure, I'll try and pick a good example

10:17 stuartsierra: CookedGryphon: While I wouldn't necessarily say it's "wrong" to have a side-effect in a transduced process, I would be more inclined to try to isolate the side effects at the "end" of the process.

10:18 CookedGryphon: stuartsierra: indeed, and that's actually what's happening here

10:18 *but* I have an ulterior motive

10:18 stuartsierra: A side effecting fn can be passed to `run!` or used as the "sink" from a channel.

10:18 CookedGryphon: which is to reduce the number of namespaces depending on core.async macros, because it's a pain re-using the code in clojurescript

10:19 are you referring to a library fn run!, or is that a hypothetical fn I should write?

10:19 Bronsa: CookedGryphon: it's a new 1.7 function

10:19 ,(doc run!)

10:20 clojurebot: "([proc coll]); Runs the supplied procedure (via reduce), for purposes of side effects, on successive items in the collection. Returns nil"

10:20 CookedGryphon: will that work with core.async channels?

10:20 puredanger: if you do channel things in it, that should be fine

10:21 it doesn't know anything specifically about channels

10:22 CookedGryphon: other way round, I'm talking about doing a side effecting function for things being outputted from a channel

10:22 I don't think run helps me here

10:22 puredanger: no, don't think so

10:24 so I guess you can't use a thread if you want this to work in cljs too

10:24 seems like a go loop is probably your best bet in that case?

10:24 CookedGryphon: so yeah, *without macros* (i.e. just using pipes, transducers and other composable channel operations), what's the nicest way of having a sink function

10:25 which just does a side effecting thing on each element as it comes out of the channel

10:25 puredanger: isn't that obvious to write in a go loop?

10:25 CookedGryphon: yeah, and I wrote it the obvious way first time around

10:26 now it's structurally bitten me as none of the go-loop code is re-usable, adding functionality bloats the go loops because they're not composable

10:27 but this may well be one case where it's reasonable to leave it as a go loop

10:27 puredanger: I would try to put as little code as possible in the go loop and just keep it to primarily doing channel things and control flow

10:27 CookedGryphon: yep, which is exactly what I did

10:28 and I ended up with 4 lines of boilerplate for everything I wanted to do with go-loops

10:28 now I've rewritten most of the take a thing from these pipes, combine and put out to that pipe

10:28 as transducers and pipe operations

10:28 and it's lovely and concise

10:28 and composable

10:29 and so I'm exploring other options for this end point which takes a side effecting action on each item coming out of the channel

10:29 to see if there's a similar gain to be made

10:30 this rewrite also means I have taken the core.async dependency out of a lot of namespaces entirely, they just produce a transducer

10:30 puredanger: there definitely is a missing "sink" operation in core.async - there's a ticket for this out there

10:30 CookedGryphon: and the fact that it goes via async channels is now a detail which the caller is responsible

10:30 cool, I'll have a look and upvote it if I find it

10:31 puredanger: http://dev.clojure.org/jira/browse/ASYNC-67

10:32 CookedGryphon: Yeah, that

10:32 In fact, I might just take that into my code as a utility

10:37 stuartsierra: puredanger: thanks for that link

10:40 puredanger: we are trying to bring async tickets into the same review process we use for Clojure itself but that has been slow to take hold

10:41 Bronsa: puredanger: I thought the point of contribs was to have a faster contribution process than clojure?

10:41 puredanger: async is special

10:42 but it can also have releases independent of Clojure

10:42 and that's actually why it's hard to integrate - the reports are focused around a target release and those dimensions differ between core and async

10:42 I'm still trying to decide exactly how to deal with that

10:43 it's possible that some of async could move into core in the future. I'm not foretelling anything… just saying that's a possibility.

10:44 Bronsa: clojurebot: core.async |is| special

10:44 clojurebot: 'Sea, mhuise.

10:44 puredanger: my personal opinion is that async is important enough to be in the box. but I also think it's still changing enough that I'd like to be able to release separately and more frequently. just my opinion / not speaking for Rich or anything official.

10:45 Bronsa: puredanger: ok, thanks

10:46 ssa: can you not `import` in the body of a namespace?

10:46 Bronsa: sure you can ssa

10:46 ,Buffer

10:46 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: Buffer in this context, compiling:(NO_SOURCE_PATH:0:0)>

10:47 Bronsa: ,(import 'java.nio.Buffer)

10:47 clojurebot: java.nio.Buffer

10:47 Bronsa: ,Buffer

10:47 clojurebot: java.nio.Buffer

10:47 Bronsa: ^

10:47 ssa: cool, ok -- i am doing the following but am getting an exception:

10:47 (import 'org.apache.curator.retry.BoundedExponentialBackoffRetry)

10:47 (BoundedExponentialBackoffRetry. 100 120000 10)

10:47 Bronsa: ssa: what's the exception?

10:47 ssa: Unable to resolve classname: BoundedExponentialBackoffRetry

10:48 borkdude: object oriented programming: the blind leading the blind (haha, sorry, just wanted to rant)

10:48 Bronsa: ssa: is the import statement in the top-level?

10:48 ssa: also happens when i do (import [org.apache.curator.retry BoundedExponentialBackoffRetry])

10:48 no

10:48 it's in a function

10:48 Bronsa: ssa: that's your issue

10:48 ssa: ah awesome -- what's going on?

10:49 Bronsa: ssa: import works at runtime, class literals are resolved at compile time

10:50 ssa: also in your second import example, you're missing the quote

10:51 ssa: remember require/import/use & co are functions so when you're using them outside the ns macro, you need to quote the args

10:51 ssa: Bronsa: ah yes, got it

10:52 to describe what I'm trying to do: I want to make a retry policy configurable, and don't want to import unnecessary classes

10:52 ie, didn't want to import all retry policies

10:59 mavbozo: ssa: if you know which classes that you will eventually use, why not import them all?

10:59 ssa: any particular restriction from environment?

11:00 ssa: mavbozo: maybe I am wrong here; I am running that snippet of code in a prismatic graph node, which I am using as a config

11:01 mavbozo: ie, I know a retry policy will be specified by the user, but I don't know which one

11:01 mavbozo: is there no cost to importing everything?

11:03 mavbozo: ssa: jvm will use more Permanent Generation memory

11:04 ssa: but you can see the usage from, for example, jconsole

11:10 puredanger: in <= Clojure 1.6, importing a class will also cause it to be loaded, which is in some cases problematic

11:11 that behavior is actually changing in 1.7

11:11 http://dev.clojure.org/jira/browse/CLJ-1315

11:11 ApeShot: So the issue I mentioned above is quite mysterious

11:11 I commented out everything except for a naked skeleton in my entry point

11:11 And then it compiled

11:12 I gradually added everything back until it was at the original state and all compiled

11:12 I then did lein clean && lein build and I get the null pointer problem

11:12 excuse me, lein run

11:12 To make it go away, I have to comment everything out again, lein run, then uncomment out and lein run

11:12 It runs fine when it builds

11:12 no errors

11:13 But it seems that after a lein clean I must go through this ritual of commenting down to a trivial version

11:13 And then building, and then uncommenting out my code

11:13 Does this ring any bells with anyone?

11:13 sdegutis: Hi. What's a good local file backup setup for local files, including closed source Clojure repos?

11:13 ApeShot: Sounds like some stile class files are hanging around or something

11:13 sdegutis: I know redundancy is important, and I've heard the word RAID tossed around...

11:14 mavbozo: ApeShot: i remember a discussion a few months ago here. someone solve that kind of problems just by creating a new directory and copy every file to the new directory

11:16 ApeShot: mavbozo: I sort of did that. I might create a clean structure from the same template and copy the files in

11:16 See if that helps

11:16 clgv: ApeShot: sounds more like your project is somehow relying on stub class files that are not around after "lein clean"

11:16 ApeShot: thats theological computer science then ;)

11:16 ApeShot: clgv: how might I figure out where those classes are, then?

11:16 clgv: or what sort of code might generate them?

11:17 clgv: ApeShot: does the documentation of the libraries/frameworks you use state that some namespaces need to be AOT compiled?

11:17 ApeShot: clgv: this is for a game jam ending on the 31st, so I am not above computer science theology

11:17 I'm just using play-clj

11:18 And my own library cljan, which doesn't do anything fancy

11:18 Well, it does fancy things, but not so far as the administration of the project is concerned

11:18 Nothing in the play-clj docs indicates any such thing

11:19 clgv: can you post the complete stack trace?

11:19 you can do (compile 'my.evil.namespace) on the repl and then use clojure.stacktrace/print-cause-trace

11:20 ApeShot: when the problem happens, I can't even do `lein repl`

11:20 I get the same error

11:20 Can I ask lein to start a repl without trying to load the main ns?

11:21 clgv: yeah you can just comment out the :main line

11:21 ApeShot: In my project.clj

11:21 ?

11:21 clgv: yes

11:21 ApeShot: Cool

11:21 Thanks.

11:22 clgv: remove the namespace from :aot vector as well, if it is listed there

11:22 technomancy: lein update-in : assoc :main clojure.core -- repl

11:22 ApeShot: Incidentally, I have had some success building play-clj projects for android

11:22 clgv: technomancy: awesome. "update-in" is new to me

11:22 technomancy: clgv: it's a fun one

11:22 ApeShot: But I keep reading that the dalvik GC isn't really up to game-like functionality for clojure's memory profile

11:23 technomancy: err... dissoc :main, of course

11:23 clgv: technomancy: what was the procedure to get full stacktraces from leiningen when for example "lein repl" fails? some environment variable?

11:23 ApeShot: What is the newest intuition about this?

11:23 technomancy: clgv: proably something in :repl-options

11:25 clgv: technomancy: humm there is only :caught in the sample - that sounds as if it is operating in a running repl. I meant when the repl startup fails with an exception

11:29 ApeShot: can you report what "DEBUG=true lein repl" or same with "lein run" outputs?

11:37 SagiCZ1: i get this when running lein test: Could not locate project_name/core_test__init.class or project_name/core_test.clj

11:39 clgv: SagiCZ1: so you have a require/use somewhere that wants to load project-name/core.test

11:39 err: project-name/core-test

11:39 andyf_: SagiCZ1: Not sure, but perhaps that is a sign of a mismatch between file names and namespaces defined in them? If you are willing to try out Eastwood, it checks for that quite quickly. https://github.com/jonase/eastwood#installation--quick-usage

11:40 conner: What would be the most idiomatic way to turn ["x: FOO" 1 2 3 "x: BAR" 4 5 6] into { "FOO" [1 2 3] "BAR" [4 5 6] }?

11:41 bbloom: lein removed support for jars in lib/ really?

11:41 that's annoying as hell.

11:43 cbryan: now i remember why i don't use xchat

11:43 sorry for the leavejoin spam

11:43 ipostelnik: conner (->> (partition-by #(.startsWith % "x: ")) (map (juxt first rest)) (into {}))

11:44 SagiCZ1: andyf_: You got it right, i was renaming my project and forgot to renaim dependencies in the test ns

11:44 (inc andyf_)

11:44 lazybot: ⇒ 4

11:46 cbryan: thanks ipostelnik! im reading the docs on ->>, it seems like it 'just' prevents a sort of nested-hell?

11:46 nextstep: hello, what's the clojure way for expressing the following pattern. I have some function for mapping stuff in a collection. Some operation inside that function (calling an external program or a service) is very inefficient if i call it just item by item. How can i cleanly group these while still preserving the 1-by-1 mapping???

11:46 lazybot: nextstep: Yes, 100% for sure.

11:48 CookedGryphon: you could do partition on the output and doseq over the resulting batches

11:49 dbasch: either pmap or futures

11:49 andyf_: nextstep: If the collection you are mapping over can be treated as a generic sequence, you could use partition, and then concat afterwards if you want to put the groups back together.

11:49 cbryan: i just started clojure 3 days ago, and every time i find out about something like `partition-by` I get goosebumps. joy of clojure, indeed

11:49 SagiCZ1: ~pmap

11:49 clojurebot: pmap is not what you want

11:49 clgv: true

11:53 nextstep: yeah i think pmap is not a good solution, and i cannot see how partition would not entangle things either. i want to preserve my simple mapping function

11:53 perhaps futures?

11:54 as dbasch mentioned?

11:54 arohner: nextstep: I'd use partition & concat

11:55 also, core.async much better for parallel processing rather than futures

11:55 andyf_: futures by themselves won?t group multiple items together.

11:55 clgv: nextstep: can you b more specific. do you just want to group according to a criterion or do you want to parallelize expensive computation?

11:57 nextstep: clgv: i have a very big stream, and i apply a simple map to each element

11:57 inside the mapping function

11:57 i call an external program

11:57 but i want to call this program with batches of items, not just an item at a time

11:57 clgv: well then you have to explicitely partition the items and map over those partitions

11:58 provided the external program supports batches

11:59 e.g. (defn map-batched [size f coll] (apply concat (map f (partition-all size coll))))

11:59 puredanger: you map find the core.async pipeline function to be useful

12:00 nextstep: clgv: yes, the external program supports batches

12:00 clgv: nextstep: you can do something as shown above where `f` gets a list of elements, calls your program and returns a list of results

12:01 nextstep: but i want to avoid that my f function deals with multiple elements

12:01 so i was thinking of using async

12:01 and inside the f function sending items that get grouped

12:01 and then forwarded to the external program

12:01 i have many f functions, some have to deal with batches, some dont

12:02 so it gets very messy

12:02 clgv: I am not sure about the side constraints of your scenario

12:04 you should make explicit descriptions what the interface to that program is conceptually and what exactly your "different functions" are (clojure functions? calls to the program with different parameters? ...)

12:06 nextstep: clgv: the functions just take one parameter, the element of the collection to map

12:06 the external functions take many of these

12:07 clgv: what are "external functions"?

12:07 nextstep: unix programs that take thousands of items in one go

12:07 or REST services

12:08 clgv: ok.

12:08 andyf_: I?m pretty sure I?ve heard comments about core.async such as ?and it didn?t require changes to Clojure at all. Clojure is such that it could be implemented just as a library.? That is certainly true, but does it seem slightly disingenuous, in that part of that library is a reimplementation of most of the Clojure compiler (i.e. tools.analyzer{,.jvm,.js}) ?

12:08 ugh. stupid smart quotes

12:08 nextstep: clgv: therefore grouping items makes it much faster

12:08 danners: so i am reading through http://www.braveclojure.com/ and now i am on the vampire example. i get following error in the replArityException Wrong number of args (1) passed to: core/map clojure.lang.AFn.throwArity (AFn.java:429) . how do i know where my mistake in my clojure program is from this?

12:08 nextstep: but i want to hide that from the main program

12:09 this is probably some kind of Go pattern, forward stuff to a proxy that groups calls and gets back with results

12:09 clgv: nextstep: ok. so where is the problem to just write one function that deals with batching, sending to external program and concatenating the results again. this function would completely hide the abtching except for a batch size parameter

12:09 nextstep: but havent figured out

12:09 yes

12:10 but i havent been able to figure out a clean solution

12:10 cbryan: danners: check the stack trace

12:10 SagiCZ1: danners: hi, this means that the map didnt get the correct number of args

12:10 clgv: well I gave you a sketch of it above. you just have to specify what the variable part is that changes

12:11 SagiCZ1: cbryan: i have never found my mistake using stacktrace in clojure

12:11 cbryan: should be like "AFN.throw...AFN.invoke...yournamespace.yourtcode (blah.clj:2025)"

12:11 danners: cbryan: ah thanks

12:11 clgv: nextstep: can't you come up with examples how the map+batch should be invoked?

12:11 danners: thats why it also shows the stacktrace...

12:11 cbryan: SagiCZ1: yeah, but he asked how to know where the error was :)

12:12 nextstep: clgv: (defn map-batched [size f coll] (apply concat (map f

12:12 (partition-all size coll))))

12:12 you mean this sketch?

12:12 justin_smith: ApeShot: just reading some scrollback, FYI it's normal to include a larger variety of things in one clj namespace than in eg. a java class file. And a project need not have any core.clj file, not to mention having more than one. Lein templates use that name because they need something generic, but a more descriptive name for a namespace is always better.

12:13 clgv: yeah. it shows a basic principle - I couldnt be more specific since I have no idea what a variable `f` would look like in your case.

12:13 noncom: i need to support clojure syntax and formatting in emacs, but without support for anything else clojure - what is my best option ?

12:14 clgv: so in that example it is a function that executes on batches, could also be change to (defn map-batched [size call-external coll] (apply concat (map (fn [coll] (call-external (prepare-params coll))) (partition-all size coll))))

12:15 nextstep: clgv: ok let me figure this out, only started using clojure a few days ago, so im a bit slow :)

12:17 clgv: nextstep: ok, just identify the changing params to such a function as sketched above

12:19 nextstep: clgv: i dont think i get your proposed solution. I want to call the external program from inside the mapping function like (map (fn [i] ... (call-external j)) coll)

12:20 my mapping function makes some changes to the item i of the collection coll

12:20 on a case per case basis

12:21 so i think its the only way to go, and hide from the function the fact that calling this program on a case per case basis is expensive

12:21 clgv: nextstep: well, separate the manipulation of the elements from the sending to the program

12:22 nextstep: you can easily do (map call-external (map preprocess-element coll))

12:22 nextstep: then it is easy to sneak in the batching

12:23 e.g. (map-batched 100 call-external (map preprocess-element coll))

12:24 CookedGryphon: Is there a way to get a channel which closes at the same time as a mult, but doesn't get any of the values out of it

12:24 without tapping and just filtering everything

12:26 clgv: nextstep: the same applies to postprocessing btw

12:27 nextstep: clgv: aha, ok

12:28 clgv: thanks for your patient explanations :)

12:28 clgv: you are welcome

12:30 EvanR: can i get a map pretty print that is actually readable?

12:31 alternating lines of keyname value on the same column is not

12:32 justin_smith: EvanR: beyond a certain size clojure.pprint does the right thing

12:32 EvanR: i disagree

12:33 justin_smith: oh, I misread what you were saying

12:33 llasram: EvanR: you can try https://github.com/brandonbloom/fipp

12:33 SagiCZ1: ,(clojure.pprint/pprint {:a 0 :b 2})

12:33 clojurebot: #<ClassNotFoundException java.lang.ClassNotFoundException: clojure.pprint>

12:33 justin_smith: so what behavior do you actually want?

12:33 EvanR: i cant see where entries begin or end

12:33 borkdude: I miss a decent pretty printer that is usable from clojure and clojurescript

12:34 EvanR: ive take this for granted so much i can only think of php's print_r as an example of showing a map

12:34 clgv: llasram: fipp is not much better than pprint

12:34 EvanR: which i know sounds ridiculous

12:34 * EvanR looks at json pretty print web app somewhere

12:35 justin_smith: EvanR: is that so much different? you get keys in one column, vals in another

12:35 llasram: clgv: Except that it's much easier to modify how it prints

12:35 bbloom: clgv: what's the problem?

12:35 EvanR: pprint is optimizing for having very little screen width, which makes sense in intellij

12:35 justin_smith: i dont get keys in one column values in another

12:35 justin_smith: EvanR: the width is configurable

12:35 bbloom: both clojure.pprint and fipp offer configurable widths

12:35 EvanR: oh really

12:36 bbloom: do you want pretty printing for debugging?

12:36 tree whidbey

12:36 try* whidbey rather

12:36 EvanR: yes, and ok. checking on this width thing

12:36 bbloom: https://github.com/greglook/whidbey

12:36 EvanR: "miser-width"

12:37 borkdude: bbloom does that also work with a browser repl?

12:37 bbloom: borkdude: no

12:37 clgv: llasram: yeah some options are better to use

12:37 SagiCZ1: once i change ns from 'user' i cant access pprint anymore via 'pprint' .. someone suggested 'injections' in leiningen but it doesnt work for me.. what can i do to be able to always use pprint whenever i want?

12:37 bbloom: EvanR: i'm bias, as i wrote fipp and whidbey is built on fipp, but if you're looking for a good pretty printer for interactive debugging, whidbey is the way to go

12:38 EvanR: it's faster and the output is less ambiguous (ie supports records and things) compared to pprint

12:38 clgv: llasram: bbloom: but I didnt gain much with fipp in comparison to pprint for nested data structure

12:38 EvanR: how do i configure this global variable, *print-miser-width*

12:38 bbloom: clgv: but you lose the multi-second delay that sometimes happens when printing large structures with clojure.pprint

12:40 clgv: bbloom: I didn't want to criticize your lib in general. I just wanted to provide the information that I experienced the same with respect to how hash-maps are printed

12:40 bbloom: clgv: i'm not insulted, don't worry :-P i'd like to improve it, if you can explain what's wrong

12:41 EvanR: set! set def

12:41 clgv: bbloom: well that would probably lead to a general lib to format clojure code ;)

12:41 SagiCZ1: so how can i keep pprint loaded in repl no matter in what ns i am?

12:41 bbloom: clgv: fipp has recently added a code pretty printer

12:41 Shayanjm: are there any well-supported distributed programming packages for clojure?

12:41 justin_smith: ,(require 'clojure.pprint)

12:41 clojurebot: nil

12:41 bbloom: clgv: but it makes no effort to beautify code. that's a non-goal

12:41 Shayanjm: or is it mostly "just use hadoop"?

12:42 clgv: bbloom: ah nice.

12:42 justin_smith: ,(binding [clojure.pprint/*print-miser-width* 200 clojure.pprint/*print-right-margin* 500](clojure.pprint/pprint {:a 0 :b 1 :c 2 :d 3 :e 4 :f 5 :g 6 :h 7 :i 8 :j 9 :k 10 :l 11}))

12:42 clojurebot: {:e 4, :l 11, :k 10, :g 6, :c 2, ...}\n

12:42 noonian: SagiCZ1: you can also construct your own user namespace and require what you like there

12:42 cbryan: Shayanjm: Storm

12:42 justin_smith: ,(clojure.pprint/pprint {:a 0 :b 1 :c 2 :d 3 :e 4 :f 5 :g 6 :h 7 :i 8 :j 9 :k 10 :l 11})

12:42 clojurebot: {:e 4, :l 11, :k 10, :g 6, :c 2, ...}\n

12:42 Shayanjm: cbryan: much appreciated, will look into it

12:42 will be building a big crawler/scraper project

12:42 bbloom: clgv: fipp provides generic pretty printing infrastructure for *fast* pretty printers. where pretty printing is defined as an indenter that respects the right margin

12:42 Shayanjm: will likely need a LOT of parallelization

12:42 SagiCZ1: justin_smith: so whenever i change ns i have to call the require function? sure there must be a better way..

12:42 bbloom: full on code beautification is a much harder problem and one for which a generic infrastructure can't make good performance promises

12:42 mdrogalis: Shayanjm: If you can afford a little more risk with a newer project, I released Onyx about a month ago.

12:43 justin_smith: EvanR: without the truncation clojurebot does, one of those would have had newlines, the other not

12:43 cbryan: Shayanjm: https://storm.apache.org/

12:43 Shayanjm: mdrogalis: could probably afford risk. I'll look into both. What does onyx provide over storm?

12:43 SagiCZ1: bbloom: yeah, you need fuzzy logic and genetic algorithms!

12:43 bbloom: SagiCZ1: not really, but you do need context sensitivity

12:43 justin_smith: SagiCZ1: not change ns? I wasn't showing that to demonstrate how you should handle things though, I was trying to demonstrate the pprint control parameters

12:43 technomancy: SagiCZ1: there is no good in-clojure solution for keeping stuff like pprint available everywhere. IMO that needs to be handled by your repl tools.

12:43 mdrogalis: Shayanjm: https://github.com/MichaelDrogalis/onyx/blob/0.3.x/doc/user-guide/what-does-it-offer.md

12:43 bbloom: which you can encode in to your transformation from your source data in to the "pretty document" format of fipp

12:44 EvanR: justin_smith: i have to wrap every pprint in this binding?

12:44 SagiCZ1: justin_smith: oh sorry

12:44 Shayanjm: interesting mdrogalis

12:44 justin_smith: EvanR: or you could set those bindings at the top level with the help of lein

12:44 Shayanjm: are you actively maintaining the project?

12:44 cbryan: mdrogalis: very cool

12:44 bbloom: but choosing an optimal layout may involve speculatively trying various layouts, which fipp explicitly disallows b/c it can be slow

12:44 SagiCZ1: so when developing do you usually stay in user ns and load everything in there?

12:45 mdrogalis: Thanks. Next release might be out tomorrow morning. One more bug I want to fix before I unleash a bunch more features.

12:45 justin_smith: SagiCZ1: I make experiments in the user ns, define the final version of my code in a file, then require that file

12:45 SagiCZ1: that's not the only way to do it of course

12:47 EvanR: justin_smith: well, now its all on one line

12:48 clgv: SagiCZ1: I am a namespace nomad. always switching to the namespaces where I need to dev something - or in a namespace that is using the ns to change

12:48 * EvanR tries other values

12:49 justin_smith: EvanR: I still have no idea what behavior you are actually looking for, you named a php function I googled it, and it had things in two columns in the example I saw

12:49 EvanR: i have yet to get pprint to do that

12:49 even that

12:50 technomancy: SagiCZ1: I typically use cider commands instead of calling tooling like that in the repl

12:50 SagiCZ1: nrepl-discover makes it super easy to expose arbitrary functions like pprint or trace from cider

12:50 EvanR: i can coerce it to do one of two things. one is {k v k v k v k v} the other is

12:50 k

12:50 technomancy: should be easy to do from vim or ccw or whatever too

12:50 EvanR: v

12:50 k

12:50 v

12:50 justin_smith: EvanR: do you have long v values?

12:51 EvanR: no they are all nested other things

12:51 i have a string at the bottom somewhere which is "SecondAndFurtherGivenNamesOrInitialsThereof"

12:52 if it just always did

12:52 k v

12:52 k v

12:52 regardless of content then i would be ok

12:54 heres an example http://codepad.org/1zndckFV

12:54 of what pprint never does

12:54 for me

12:57 bbloom: EvanR: that code is not pretty printed with respect to a right column, it's simply indented

12:58 SagiCZ1: justin_smith, clgv, technomancy thanks for opinions, interesting to see that there is not just one "correct" way

12:58 bbloom: EvanR: if you set the width to 0 (or 1?), you can force maximum indenting

12:58 EvanR: ill try that

12:59 bbloom: the reason you don't typically see json style indenters for lisps is b/c they are practically useless

12:59 most sequences are short enough that it doesn't make sense to spread them over multiple lines

13:00 and since lists are so common, it would be hideous to see "(\t\nfoo\t\nbar\n)"

13:00 EvanR: i dont have a single list

13:00 this is a map

13:00 bbloom: sure, so if yuo really just want indenting for it, then set the width to 1

13:00 EvanR: i set the width to zero, and it did some stuff, seems like everything except put the k and value not on alternating lines with the same colum

13:01 bbloom: i can't speak for pprint with width = 1, but my library fipp will do what you expect

13:02 whidbey probably will do the right thing too, but I can't say for sure as it's only using my printing engine, not my specific printer

13:02 EvanR: that is to say, width zero causes k and v to be on alternating lines

13:02 bbloom: EvanR: may i ask why you want this anyway?

13:02 ie why is the default behavior not good enough?

13:02 EvanR: i cant read my json-like data?

13:03 k

13:03 v

13:03 k

13:03 v

13:03 i cannot read it

13:03 anymore than if it was k v k v k v on one line

13:03 in this case, it is the transpose, all on one column

13:03 with no separation

13:04 bbloom: *shrug* ok well, most people find it more readable for small collections to be horizontally laid out, so i don't really know if i can help you

13:04 try fipp with width set to 1

13:04 it always keeps key/value pairs together on a single line no matter what

13:04 tolstoy: ll

13:04 Oops. ;)

13:04 EvanR: also, the default behavior does indent, by one space. which is fine, but its just incomprehensible with the k v on alternating lines, which i guess its calling "miser style"

13:04 bbloom: small collections?

13:05 just to be clear, its not horizontally laid out, its very vertical

13:06 bbloom: EvanR: i understand, but you don't: pprint (and fipp) attempt to make a non-stupid layout. they do not blindly indent everything

13:07 things will be laid out horizontally if they fit, or vertically if they don't

13:07 hence width = 1 means nothing fits

13:07 however, clojure.pprint will let keys and values be separate, fipp will not

13:07 so try fipp with width = 1

13:07 EvanR: i can see where the reasoning came from for this

13:08 katratxo: hi all, any hints on changing the logging level of a namespace at runtime? i'm using tools.logging

13:08 bbloom: try (clojure.pprint/pprint [(repeat 3 :short) (repeat 10 :some-longer-keyword)]) and you'll understand

13:09 EvanR: i have a lot of horizontal space, but if i set the width to very wide, it will do k vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv k vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv which im trying to say is very in convenient

13:09 justin_smith: katratxo: there is such thing as per namespace variable logging levels in tools.logging?

13:09 bbloom: EvanR: i'm done with this conversation until you tell me you've tried fipp with width = 1

13:09 EvanR: ill say again, im talking about record-like maps, with field names and keys, its not some generic collection concept

13:09 clgv: justin_smith: there is per java class

13:10 EvanR: fipp is installed, trying

13:10 bbloom: (fipp.edn/pprint {:foobar 123 :baz "asdfasdf"} {:width 1}) does exactly the thing you want

13:11 katratxo: justin_smith: not sure about that ... the documentation suggests that you can define the logging level of a namespace (at least with log4j)

13:12 clgv: katratxo: yeah I have seen it per java class

13:13 justin_smith: katratxo: oh, I did not see anything like that in the api overview doc page. But timbre explicitly supports per-namespace control

13:13 clgv: katratxo: you can modify system properties for logging

13:14 samflores: is there some roadmap for core.async leaving alpha?

13:15 clgv: samflores: sssshhh! you are openening pandora's box :P

13:15 samflores: 👀

13:15 * samflores run to the hills

13:15 EvanR: im getting no namespace fipp.edn

13:16 and no namespace fipp.clojure

13:16 katratxo: justin_smith: do you know if timbre can capture the System.out and redirect it to a log? similar to log/with-logs ?

13:16 bbloom: EvanR: i'm happy to offer you support for fipp, but i'll leave general "how do i use clojure" support to the rest of the channel

13:16 EvanR: yeah

13:16 justin_smith: katratxo: not sure, doesn't it use tools.logging?

13:16 clgv: samflores: last time this discussion happened, I had the impression that the maintainers think that human rememberable versions have no use

13:17 katratxo: justin_smith: will check it out ... thanks

13:22 EvanR: frustrated now

13:23 i have [fipp "0.5.1"] in my project.clj, lein deps does nothing

13:23 (require '[fipp.edn]) in lein repl gives CompilerException java.lang.RuntimeException: Unable to resolve symbol: record? in this context, compiling:(fipp/edn.clj:42:11)

13:23 samflores: clgv, I guess I'll wait quietly then

13:24 llasram: EvanR: That function was added in Clojure 1.6

13:25 EvanR: Using an older version?

13:25 EvanR: Clojure 1.5.1

13:25 llasram: Well there you go

13:26 EvanR: what am i doing with an old version

13:26 llasram: A question humans throughout history have asked themselves

13:27 EvanR: this is ubuntu 14.04

13:27 llasram: eh?

13:27 EvanR: Clojure version is per-project, a feature of what you have in your Leiningen project.clj

13:27 EvanR: oh k

13:28 bbloom: if you installed leinigen with apt, you should uninstall it and use the preferred install method

13:28 * llasram somewhat sadly concurs

13:28 bbloom: http://leiningen.org/

13:28 EvanR: [org.clojure/clojure "1.5.1"] is in my project file so that explains that, also i installed leiningen the way the site told me to

13:29 llasram: Awesome

13:29 EvanR: so ubuntu fortunately has nothing to do with it

13:29 technomancy: babilen: hate to be a broken record, but what's the odds of lein2 getting into debian jessie?

13:29 EvanR: so fipp depends on a particular version of clojure

13:30 bbloom: EvanR: a minimum version of clojure, yes

13:30 EvanR: shouldnt lein deps tell me?

13:30 * bbloom bites his tongue regarding dependency management

13:30 EvanR: good time to go to lunch

13:31 technomancy: EvanR: there's no way to distinguish between "minimum version" and "recommended version" in pom-speak

13:31 EvanR: pom pom ...

13:31 Project Object Model

13:33 technomancy: EvanR: however, lein deps :tree will warn you about this

13:33 [org.clojure/clojure "1.5.1"] overrides [fipp "0.5.1"] -> [org.clojure/clojure "1.6.0"]

13:44 csd_: where's the best place to host a small clojure web app for free?

13:44 r4vi: heroku

13:45 csd_: r4vi: only downside there is they use postgres and i made this with mysql :-/

13:45 technomancy: there are mysql addons too; we just don't run them ourselves

13:45 but, maybe that's a good excuse to stop using mysql =)

13:46 csd_: technomancy: you work for heroku?

13:46 technomancy: yeah

13:46 csd_: cool

13:47 technomancy: lemme know if you have any questions

13:47 csd_: technomancy: do you think the server will complain if my app does some minor web scraping?

13:47 technomancy: csd_: shouldn't be a problem

13:47 I mean, please respect the terms of service of the site being scraped, but that has nothing to do with us =)

13:52 xeqi: EvanR: `lein deps :tree` should produce some warnings about version mismatches, though that was broken for a couple of point releases in 2.4.*

14:32 justin_smith: ,(deref (doto (promise) (deliver :ping)))

14:32 clojurebot: :ping

14:49 borkdude: ,(chan)

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

14:50 justin_smith: borkdude: I don't think clojurebot will do anything with threads

14:51 borkdude: blame the bot quine

14:51 borkdude: justin_smith you don't need threads per se for core.async right

14:51 justin_smith: borkdude: I guess we could port clj core.async to clojurebot?

14:51 borkdude: justin_smith clojurescript

14:52 justin_smith: borkdude: sure, but clojurebot is not clojurescript

14:52 point being we would need a clj version of core.async that did not use threads

14:52 borkdude: justin_smith k, well, one liners don't work well with core.async anyway probably

14:53 justin_smith: borkdude: yeah. I would make it easier to show people with questions how core.async stuff works though

14:53 s/I/It

14:56 borkdude: actually, a cljsbot would be good too

14:56 borkdude: justin_smith yeah

14:57 justin_smith: I wonder if there is a way to do that that isn't totally insane

14:57 borkdude: { (js/alert "haha"} }

14:57 justin_smith could look at clojurescript.net?

15:01 justin_smith: yeah, that would likely be a good start

15:02 borkdude: they link to this as their source https://github.com/kanaka/clojurescript

15:03 mix that with Raynes irc lib, and bob's your uncle

15:04 perplexa: is there a better way to do (fn [a & option] (or option "default"))?

15:05 justin_smith: ,((fn [a & option] (or option "default")) nil nil)

15:05 clojurebot: (nil)

15:06 justin_smith: ,((fn [a & [option]] (or option "default")) nil nil)

15:06 clojurebot: "default"

15:06 danielszmulewicz: I would like to emit javascript to a string. Not via the cljs build process, but by using the compiler directly from source. Input is some clojure form (defn three+three [] (+ 3 3)), output should be: "node_test.core.three_PLUS_three = (function three_PLUS_three(){return ((3) + (3));" How do I achieve that?

15:07 perplexa: ah, so & pushes the following params into a seq

15:07 justin_smith: perplexa: yeah, because it takes any number of params

15:08 perplexa: yeah makes sense :)

15:23 SagiCZ1: would it benefit me to create a memoized version of count? i use count often and the linear time is really slow for me

15:24 mgaare: SagiCZ1: do you often find yourself counting the same thing multiple times?

15:25 SagiCZ1: mgaare: yeah

15:26 i guess thats a bad design though

15:26 justin_smith: SagiCZ1: you could use vectors or sets instead of lazy-seqs where applicable, they implement count in constant time

15:26 SagiCZ1: vectors count is constant?

15:26 justin_smith: yup

15:26 SagiCZ1: thats cool then, i use vectors mostly

15:26 bbloom: SagiCZ1: putting a memo table at the call site is likely to be a memory management nightmare -- justin_smith is right, prefer better data structures

15:26 SagiCZ1: thanks

15:27 mmeix: If I want to partition a sequence of numbers, so that consecutive numbers are packed into separate vectors like so:

15:27 [1 2 3 5 6 9 12 13] => '([1 2 3] [5 6] [9] [12 13])

15:27 partition-by doesn't help me much, because it only looks at one element at a time

15:27 justin_smith: mmeix: it can be done in a one-liner with reduce

15:29 mmeix: ok, I guessed this to be a case for reduce

15:29 but didn't get it - will think further

15:29 hyPiRion: reduce, transduce

15:30 mmeix: ok

15:30 thanks

15:32 justin_smith: ,(def input [1 2 3 5 6 9 12 13])

15:32 clojurebot: #'sandbox/input

15:32 justin_smith: ,(reduce (fn [[acc contig] n] (if (= (inc (peek contig)) n) [acc (conj contig n)] [(conj acc contig) [n]])) [[] [(first input)]] (rest input))

15:32 clojurebot: [[[1 2 3] [5 6] [9]] [12 13]]

15:32 justin_smith: wait, that's a bit off isn't it :)

15:33 ,(apply conj (reduce (fn [[acc contig] n] (if (= (inc (peek contig)) n) [acc (conj contig n)] [(conj acc contig) [n]])) [[] [(first input)]] (rest input)))

15:33 clojurebot: [[1 2 3] [5 6] [9] [12 13]]

15:33 SagiCZ1: beautiful

15:35 justin_smith: heh, thanks

15:37 hyPiRion: I feel this problem pops up quite often for some reason. And I always want to use (partition 2 1 ...) on it and it gets all messy

15:37 it's for some reason not as straightforward to implement it

15:37 mmeix: ah, missed that because of laptop sleep (after (def input...)

15:37 justin_smith: hyPiRion: yeah, my goto for that is multi-accumulator reduce

15:37 mmeix: should I repaste the code?

15:38 hyPiRion: I wonder if a multi-accumulator version of reduce without destructuring would be worth it?

15:38 mmeix: tried partition 2 1, got lots of parens ...

15:39 hyPiRion: justin_smith: multi-accumulator?

15:39 mmeix: justin_smith if you would be so kind ...

15:39 justin_smith: ,(apply conj (reduce (fn [[acc contig] n] (if (= (inc (peek contig)) n) [acc (conj contig n)] [(conj acc contig) [n]])) [[] [(first input)]] (rest input)))

15:39 clojurebot: [[1 2 3] [5 6] [9] [12 13]]

15:39 justin_smith: hyPiRion: I have two accumulator values, thanks to destructuring

15:40 hyPiRion: but I guess that doesn't make sense beause apply would have to be used internally anyway since you would need to return a collection...

15:40 hyPiRion: or just use recur, of course

15:40 mmeix: wow, that's a fat oneliner :-) will study it thoroughly

15:40 justin_smith: mmeix: doesn't qualify as a one-liner, I don't think

15:41 mmeix: it's not so bad when on a few lines and indented properly

15:41 mmeix: just doin that

15:42 justin_smith: mmeix: so as I was saying, the main trick is using destructuring / returning a vector in order to have more than one accumulator

15:42 mmeix: ah, that's a new technique for a beginner

15:43 ah: that was the point I couldn't get: "multiple accumulators"

15:43 thanks a lot

15:44 (inc justin_smith)

15:44 lazybot: ⇒ 108

15:44 hyPiRion: It's not very common I think

15:45 justin_smith: hyPiRion: I do it often, maybe it's because I am weird

15:45 mmeix: this is something I expect to need a lot: segemnting vectors of musical notes by some criterion

15:45 thanks for input!

15:46 hyPiRion: mmeix: oh, just a warning: That one won't work on infinite lists

15:46 mmeix: understand ...

15:47 I don't expect my musical phrases to be of infinite length though :-)

15:47 justin_smith: mmeix: I bet you could do some fun stuff with derive and multimethods to describe musical rules

15:47 mmeix: derive? (looking up)

15:48 ok, have to leave

15:48 thanks again

15:48 justin_smith: np

15:50 hyPiRion: I guess a lazy version could be done with (partition 2 1 ...) and take-while

15:50 and lazy-seq of course

15:58 arohner: running new Cider (installed from melpa today), I don't get stacktraces when an error occurs. The error window pops up, but it's empty

15:58 any ideas?

15:59 FWIW, my previous version didn't have working stacktraces either, which is why I tried to upgrade

15:59 I got the error about missing the cider-nrepl .jar, but I fixed that

15:59 justin_smith: arohner: I assume you can at least use (pst)

15:59 arohner: yeah

15:59 technomancy: have you tried the stable version?

16:00 arohner: technomancy: which one is that? from melpa-stable?

16:00 justin_smith: arohner: 0.7.0

16:01 arohner: also, the clojure-emacs channel has at least one cider dev who doesn't follow this channel on it

16:01 technomancy: arohner: 0.7.0 and 0.6.0 are both a lot more likely to work than whatever melpa gives you

16:01 melpa-stable will probably give you 0.7.0 claiming to be some nonsense datestamped version

16:02 arohner: justin_smith: technomancy: thanks

16:02 technomancy: how do you recommend I install it?

16:02 technomancy: arohner: I ... =(

16:02 I don't have a recommendation.

16:02 arohner: git clone and stick in ~/.emacs.d/?

16:02 technomancy: if you use emacs 24.3, you can install from marmalade

16:02 but emacs 24.4 has a bug that breaks transitive deps over HTTPS

16:03 obviously don't install over non-TLS (melpa, melpa-stable)

16:03 so yeah, manual clone is nice because you're in control, but the deps are tedious to track down

16:03 arohner: I think marmalade gave me 0.6.0, which also didn't work

16:03 but sounds like that's more likely to get working

16:04 technomancy: el-get works, but I can't recommend it out of the box, it's only safe to use if you (setq el-get-allow-insecure nil)

16:04 I'm using 0.6.0

16:04 dysfun: i think life would be particularly miserable without melpa

16:04 dbasch: I had problems with 0.7.0, sticking to 0.6.0 because it works fine for me

16:04 technomancy: all the package.el sources are fatally flawed at the moment

16:05 unless you use marmalade and hold off on the emacs 24.4 upgrade

16:05 dysfun: yeah, but it's still pretty new tech

16:05 technomancy: dysfun: that's not a good excuse

16:05 even if it were true, which it's not

16:06 dysfun: frankly, pre-melpa, i didn't bother at all

16:06 because there just wasn't enough stuff available

16:06 csd_: technomancy: question about heroku

16:06 technomancy: dysfun: now you're installing software in a way that's trivial to MITM. is this an improvement?

16:06 arohner: ok, so I'm back on cider 0.6.0, and stacktraces don't pop up in a buffer

16:06 technomancy: csd_: sure, go ahead

16:06 arohner: I just get the first line of the stacktrace in the repl

16:07 csd_: i'm trying to deploy and i'm running into a boot timeout error. my app is getting killed while its compiling basically. would this recompile happen every time the dyno restarts?

16:07 dysfun: technomancy: i *have* installed software in a way that is trivial to MITM. And probably won't be MITMed. and i try not to live my life in a tinfoil hat manner

16:07 justin_smith: arohner: I think there is a config variable for that

16:07 technomancy: dysfun: well, luckily I don't use any software you've released in a production setting where user data is at stake

16:08 arohner: justin_smith: I have (setq cider-show-error-buffer t)

16:08 technomancy: csd_: that's common if you're not creating an uberjar at git push time. the uberjar approach is strongly recommended for this reason.

16:08 dysfun: technomancy: everything you use is already backdoored and you're worried about a highly improbable event instead?

16:09 technomancy: dysfun: the level of sophistication to pull off an HTTP MITM is laughably low

16:09 csd_: do people that take that tack include the .jar in their git repo?

16:09 dysfun: how many times do you think i'm going to have to install a package from elpa?

16:09 csd_: or is there another way to upload it

16:09 dysfun: melpa*

16:09 clojurebot: A nod, you know, is as good as a wink to a blind horse.

16:09 llasram: clojurebot: or?

16:09 clojurebot: or is there another way to upload it

16:09 technomancy: csd_: no, you push the git repo to the build servers and the uberjar is created there

16:10 dysfun: this is basic computing hygiene

16:10 "don't put that in your mouth, you don't know where it's been" of ones and zeroes

16:10 dysfun: i suppose you have a strip of tape over your webcam just in case the NSA is watching too

16:11 technomancy: it's one thing to guard against a nation state adversary, it's another to guard against attacks that are trivial to preform

16:11 dysfun: i'm not arguing the services shouldn't be better, but there are much bigger things for me to worry about

16:11 csd_: technomancy: guessing i just need to specify :uberjar-name in project.clj and that should take care of things?

16:11 technomancy: csd_: yeah

16:11 dysfun: i install elisp from melpa once in a blue moon. i'm not going to get paranoid about that

16:11 csd_: cool thanks

16:11 technomancy: csd_: and change your procfile to use the uberjar instead of lein run or whatever

16:12 justin_smith: dysfun: he's someone who works on the dependency resolution and deployment stack, I'd say he's doing us a favor by letting us know when something is sketchy, and we can decide how to act on that info

16:12 csd_: is there a way to do lein ring server-headless via uberjar

16:13 technomancy: my laptop has credentials that would allow me to steal data from customers that include bitcoin exchanges.

16:13 dysfun: you mean you want your main class to start a server?

16:13 ah. well i certainly wouldn't keep credentials like that on here

16:14 technomancy: if I use a dysfun-produced jar in one of my projects, I've created a large incentive for someone to attack melpa.

16:14 dysfun: on the other hand, since all of my modules are on github, you can read the source

16:14 technomancy: there would be very little technically challenging about pulling off this attack

16:15 dysfun: I'm not going to build from source, I'm going to get it from clojars.

16:16 even if I built from github, you probably haven't disable force-push on your repos

16:16 dysfun: see, that sounds like a terrible idea now, because you never know that all of those people releasing to clojars are quite as careful as you

16:17 but my point about it being on github was merely that if you don't trust the code, you can read it and determine if it's a risk

16:17 technomancy: it is pretty terrible, but at least clojars can't be trivially MITM'd any more.

16:17 there are really easy things you can do to prevent simple attacks.

16:17 there are really difficult things you can maybe do to hopefully prevent sophisticated attacks.

16:18 dbasch: dysfun: sneaking malicious obfuscated code in open source is trivial and it’s been done

16:18 technomancy: just because some of it is hard doesn't mean the easy stuff isn't worth bothering with.

16:18 TimMc: dysfun: I do in fact keep a sticky note over my webcam. It's easy and makes sense.

16:18 dysfun: dbasch: thousands of times. thousands of times in linux alone i'd wager

16:19 TimMc: It's not weird to guard against attacks that have already happened to other people.

16:19 dbasch: not like anybody ever looks at the source code of even a fraction of what they run blindly

16:19 technomancy: I don't have a webcam, FWIW.

16:19 justin_smith: TimMc: dysfun: I leave mine uncovered, the sight any attacker would witness if they turned it on would be its own punishment

16:19 dysfun: technomancy: no. but on the other hand, the fact that i'm going to install each package precisely once does somewhat limit the vector of attack

16:19 technomancy: but the fact that they aren't hard-wired into the activity LED pisses me off

16:19 dysfun: they are on some laptops

16:20 TimMc: technomancy: Even that doesn't help -- you can turn it on, take a picture, and turn it off again without the user noticing.

16:20 dbasch: listening in on someone is much more useful than looking at them with a camera anyway

16:20 dysfun: exactly

16:20 dbasch: tracking your keystrokes even more so

16:20 TimMc: Microphones are even worse, of course. No activity light.

16:20 justin_smith: my favorite recent conspiracy theory: FBI complains loudly about google / apple not giving them back doors into their mobile systems as a cover for the fact that they already have access

16:20 dysfun: and of course there was that malware that used microphones and speakers as a back channel too

16:21 TimMc: Anyway, point is, it's silly to not take precautions where there's low cost and high gain.

16:21 And layered security is a thing.

16:21 dysfun: and it would be lovely if it was there, don't get me wrong

16:22 i would like to see SSL be used everywhere, all the time

16:26 bodie_: anyone tried cursive with clojurescript?

16:26 IDEA fork built around lein I guess?

16:27 I've been using lighttable but its cljs integration is a little wack

16:27 justin_smith: bodie_: it's an idea plugin by cfleming that uses lein

16:27 mdrogalis: GitHub changed Clojure code highlighting. Do not like D:

16:27 SagiCZ1: bodie_: i've been using cursive for weeks now

16:27 bodie_: but only clojure

16:27 borkdude: bodie_ yes, works with clojurescript

16:27 bodie_: hm

16:27 interesting

16:28 borkdude: bodie_ in the sense of highlighting etc

16:28 bodie_ I build from lein cljsbuild externally

16:30 boblarrick: how do I flatten something like [ [1 2 3] :b 'a] into (1 2 3 :b 'a) ?

16:30 bodie_: borkdude, do you have a live browser setup you like? i.e. auto refresh, eval from the repl perhaps

16:30 I've been really digging the decently tight integration lighttable has there

16:30 borkdude: bodie_ you can have a look at lein new liberagent, that's basically my setup

16:30 bodie_ it's inspired by chestnut

16:31 I want to cover om + reagent in a 40 minute talk... I think I'm already short in time

16:32 boblarrick: (reduce conj …) i guess

16:32 justin_smith: boblarrick: apply conj would suffic

16:32 mdrogalis: reduce/conj is my favorite Clojure idiom, I think.

16:32 ,(reduce conj (list) (range 5))

16:33 clojurebot: (4 3 2 1 0)

16:33 justin_smith: ,(apply conj [1 2 3] :b ;a)

16:33 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

16:33 justin_smith: ,(apply conj [1 2 3] :b 'a)

16:33 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Symbol>

16:33 justin_smith: err

16:33 bodie_: borkdude, so cljsbuild auto + figwheel = live js updating, right?

16:33 justin_smith: ,(apply conj [[1 2 3] :b 'a]) ; that's what I meant

16:33 clojurebot: [1 2 3 :b a]

16:34 borkdude: bodie_ true

16:34 bodie_: and then there must be some way to tie in the repl as well

16:34 borkdude: bodie_ if you read the docs on lein new liberagent it says it all

16:34 bodie_: okay, cool

16:34 was just glancing over the list of deps

16:34 borkdude: bodie_ fighweel = lein cljsbuild auto + updating

16:34 justin_smith: mdrogalis: except for conj reduce doesn't do anything apply wouldn't be doing

16:34 bodie_: most of it is backend stuff I don't need right now

16:34 SagiCZ1: can i map backwards? like this (map #(% coll) [foo1 foo2 foo3 ..])

16:35 borkdude: bodie_ just comment them out and remove it

16:35 justin_smith: SagiCZ1: sure, that works, or you can use juxt

16:35 bodie_: yeah, figuring out what I *do* need :) hehe

16:35 thanks for the pointer!

16:35 mdrogalis: justin_smith: Eh? Oh, I guess I should've qualified that with "reverse" idiom. Not in general.

16:35 justin_smith: ,(map #(% [1 2]) [+ * / -])

16:35 clojurebot: #<ClassCastException java.lang.ClassCastException: Cannot cast clojure.lang.PersistentVector to java.lang.Number>

16:35 SagiCZ1: justin_smith: ok

16:35 justin_smith: ,(map #(apply % [1 2]) [+ * / -])

16:35 clojurebot: (3 2 1/2 -1)

16:35 SagiCZ1: it says unable to resolve symbol foo1 in this context.. so idk

16:36 justin_smith: ,(apply (juxt + * / -) [1 2])

16:36 clojurebot: [3 2 1/2 -1]

16:36 justin_smith: SagiCZ1: well you need to define things before you can call them...

16:36 rubber_duck: can someone point me to a minimal implementation of a transducing process so I can wrap my head arround the spec - it's kind of hard to figure out how to implement one without types :(

16:37 justin_smith: ,(apply conj () (range 5)) ; mdrogalis

16:37 clojurebot: (4 3 2 1 0)

16:38 SagiCZ1: justin_smith: yeah my mistake.. and can i get name of the function from the IFn object? (name (defn foo [] ..))

16:38 justin_smith: SagiCZ1: it sounds like you are trying to do something weird here...

16:39 SagiCZ1: justin_smith: yeah.. just want to save some typing

16:39 let me explain

16:40 i want to have a map where keywords are made from function names, and values are results of calls to those functions like so {:foo1 (foo1 coll) :foo2 (foo2 coll) ..}

16:41 rubber_duck: SagiCZ1, IIRC fns don't have names vars do

16:42 SagiCZ1: rubber_duck: how would i turn the var name into keyword?

16:42 rubber_duck: but I'm not 100% on that It's been a long time since I mucked around with that

16:42 mdrogalis: justin_smith: Hah, cool :D

16:43 stuartsierra: Yes, vars have names, you can get it from their metadata as :name and :ns, then ns-name, …

16:43 rubber_duck: SagiCZ1, from the sound of what you're trying to do I'd say you would use a macro

16:44 SagiCZ1: ,(def foo)

16:44 rubber_duck: (mymacro (foo ...) (bar ...)) -> expand in to {:foo (foo ...) :bar (bar ...)}

16:44 clojurebot: #'sandbox/foo

16:44 SagiCZ1: ,(meta foo)

16:44 clojurebot: nil

16:45 SagiCZ1: rubber_duck: sounds correct, but i am a macro virgin.. i bet i will do something wrong, forget some gensym or someting and my whole project literally explodes

16:45 justin_smith: ,(into {} (for [f [#'+ #'- #'* #'/]] [(keyword (:name (meta f))) (f 1 2)])) ; SagiCZ1

16:45 clojurebot: {:+ 3, :- -1, :* 2, :/ 1/2}

16:45 justin_smith: rubber_duck: can be done without a macro ^

16:45 SagiCZ1: justin_smith: do i need those ugly hashmarks?

16:46 justin_smith: ,(= #'+ (var +))

16:46 clojurebot: true

16:46 stuartsierra: SagiCZ1: What's wrong with writing {:foo (foo …) :bar (bar …)} ?

16:46 justin_smith: ,(into {} (for [f [(var +) (var -) (var *) (var /)]] [(keyword (:name (meta f))) (f 1 2)])) ; SagiCZ1

16:46 clojurebot: {:+ 3, :- -1, :* 2, :/ 1/2}

16:46 justin_smith: stuartsierra: excellent point

16:47 SagiCZ1: stuartsierra: i was just being lazy and curious

16:47 thank you for help

16:48 * stuartsierra successfully stifles another burst of creativity.

16:48 stuartsierra: ;)

16:52 boblarrick: OK nevermind still stuck

16:52 how to flatten something like '((168 99) 68 (407 53 335) 158 (168 99)) ?

16:53 mearnsh: ,(flatten '((168 99) 68 (407 53 335) 158 (168 99)))

16:53 clojurebot: (168 99 68 407 53 ...)

16:53 justin_smith: boblarrick: how did it get that shape in the first place?

16:53 boblarrick: combo/cartesian-product

16:55 justin_smith: wait, clojure.math.combinatorics/cartesian-product mixes sequences and elements in its output?

16:57 dbasch: boblarrick: if your single elements were one-element lists you could do apply concat, but really you shouldn’t have created that output

16:57 justin_smith: boblarrick: anyway, the right way to deal with something like that isn't flatten, it's using something that gives you the shape of data you need and using it apropriately, because flatten can do bad things if any of the elements you are working with are themselves collections

16:57 boblarrick: /shrug

17:00 I've got millions of these things, and i need the generation and the flattening to be quick

17:01 worried doing things "the right way" might add overhead, that would add up to a runtime I can't tolerate

17:01 dbasch: ,(apply concat (map #(if (coll? %) % [%]) '((168 99) 68 (407 53 335) 158 (168 99))))

17:01 justin_smith: flatten is not quick, apply concat would be quicker if the data format were consistent

17:01 clojurebot: (168 99 68 407 53 ...)

17:02 justin_smith: boblarrick: inconsistent data formats cause all code that interacts with them to be more complex, it can be a rippling effect that increases complexity throughout a codebase. Better to deal with it directly where the data is generated

17:03 boblarrick: this is where the data is generated

17:03 sorry I have to run, I'll benchmark some things and see what's u

17:03 up

17:05 dbasch: boblarrick: can you paste a gist/refheap with the code that generates the data

17:05 ?

17:05 justin_smith: boblarrick: also, I have no idea how one gets combo/cartesian-product to output anything but sequences

17:07 dbasch: nice hack - better than flatten at least

17:08 boblarrick: https://www.refheap.com/92464

17:09 dbasch: (map flatten) works as part of comp'ed transducer, didn't have similar luck with (apply concat (map irc://card.freenode.net:6667/#(if (coll? %) % [%])

17:09 really gotta run, thanks for help!

17:11 justin_smith: so cartesian-product did not output any individual items, but it was asked to intermingle two element lists (cows) with three elements lists (foos) and single items (bars)

17:11 redefing bars would be enough to make a concat based solution work

17:12 (def bars [[:b] [:c] [:d]]) - then one can do consistent data operations on the result

17:16 dbasch: flatten really should be deprecated

17:16 it probably causes more problems than it solves

17:16 amalloy: dbasch: (apply concat (map f xs)) is just (mapcat f xs)

17:16 dbasch: true

17:16 justin_smith: dbasch: it's a codependent partner to bad design

17:18 dbasch: mapcat is a very useful function, I usually remember it when I’m coding something from scratch

17:18 I tend to think differently when I’m solving someone else’s problem for some reason

17:20 I have yet to see a justifiable use of flatten though

17:21 perhaps when parsing horrendous html?

17:23 dav_: nick dav

17:23 justin_smith: dbasch: it could argubly be useful when using results apis that insist on turning every single element list into a single item with no list

17:24 dbasch: but once again, it's just a sign of bad design somewhere else

17:25 dbasch: reminds me of the tagline for nokogiri, an html parser for ruby

17:25 puredanger: ,(defn flatten' [s] (map (constantly '__) (flatten s)))

17:25 clojurebot: #'sandbox/flatten'

17:25 puredanger: ,(flatten' ['tomato (range 5)])

17:25 clojurebot: (__ __ __ __ __ ...)

17:25 dbasch: “XML is like violence - if it doesn’t solve your problems, you are not using enough of it.”

17:25 justin_smith: lol

17:25 puredanger: see, I flattened it

17:26 that's my new tag line, btw

17:28 danielszmulewicz: (inc puredanger)

17:28 lazybot: ⇒ 19

17:28 danielszmulewicz: that's for making me laugh

17:28 puredanger: I shall treasure that inc

17:28 ,(flatten' 'danielszmulewicz)

17:28 justin_smith: ,(defn flatten'' [s] (map #(symbol (apply str (map (constantly \_) (str %)))) (flatten s)))

17:28 clojurebot: #'sandbox/flatten''

17:28 ()

17:28 danielszmulewicz: Hey I disappeared instead...

17:29 justin_smith: ,(flatten'' '(daniel ((szmulewicz))))

17:29 clojurebot: (______ __________)

17:29 puredanger: danielszmulewicz: forgot to make it seqable

17:29 justin_smith: that should be called redact

17:29 justin_smith: good point

17:30 danielszmulewicz: I feel better.

17:30 a bit flat

17:31 justin_smith: ,(defn carbonate [s] (map #(symbol (apply str (map (constantly `\') (str %)))) (flatten s)))

17:31 clojurebot: #'sandbox/carbonate

17:31 justin_smith: ,(carbonate '(daniel ((szmulewicz))))

17:31 clojurebot: ('''''' '''''''''')

17:31 danielszmulewicz: that's worth an inc too

17:31 (inc justin_smith)

17:31 lazybot: ⇒ 109

17:33 danielszmulewicz: Does clojurescript has something like emit-string which compiles and hands over a string?

17:34 Here's an example of what I'm after: (emit-string '(defn three+three [] (+ 3

17:34 3))

17:35 Output should be: "ns.core.three_PLUS_three =

17:35 (function three_PLUS_three(){return ((3) + (3));

17:36 Basically what emit does in cljs.compiler.

17:36 where's dnolen?

17:37 justin_smith: danielszmulewicz: touring europe with his band last I heard

17:37 danielszmulewicz: justin_smith: oh, right!

17:38 I saw the tweets. I had forgotten.

18:04 csd_: I'm looking for some blog posts on best practices for managing code across developing locally, production server, etc. E.g. the fact that you want to juggle having one code base, but having to support different configurations for database server or what have you... anyone know of anything?

18:05 hiredman: the old standards are environment variables and configuration files

18:05 technomancy: use bcrypt

18:05 oh wait, wrong meme

18:05 hiredman: there are libraries that deal with both, pick one and do that

18:05 technomancy: csd_: env variables are arguably simpler, but they can't handle nested values or really anything non-string.

18:06 if you're on heroku, I recommend environ. otherwise carica.

18:06 csd_: so basically i should create on my local comp and on the remote comp a path variable like PRODUCTION? and then if it's true do one things, and otherwise the other?

18:06 hiredman: https://twitter.com/hiredman_/status/527581910155800577 tweetsare basically blog posts, right?

18:06 technomancy: csd_: don't set PRODUCTION, set whatever it is you actually care about doing differently in production vs dev.

18:06 joshuafcole: csd_ We use node at my dayjob, but it's the same concept. We define a NODE_ENV=<key>

18:06 where <key> is the key in an enumeration of available configurations

18:07 including dev, stage, and prod

18:07 technomancy: I would recommend against bundling them up like that.

18:07 mdeboard: Anyone having issues with github atm

18:07 hiredman: https://github.com/sonian/carica is generally what we use at sonian (surprise)

18:07 it uses configuration files over environment variables

18:07 technomancy: your provisioning tool should handle grouping configs, and your application should just read single values it cares about.

18:07 hiredman: and does some merging stuff

18:07 csd_: why not just have a true/false env for development vs not, and then a config file with the different types of options depending on how the env var is set

18:07 mdeboard: hiredman, You work at Sonian eh? Your blog post on transitioning from backbone to react was a great help.

18:08 joshuafcole: You can, but it's a lot less flexible

18:08 csd_: how so

18:08 puredanger: some people like the environ library to help with this stuff https://github.com/weavejester/environ

18:08 joshuafcole: What if you want to introduce an integration server?

18:08 or a staging server?

18:08 that has some of the features of dev and some of prod?

18:08 technomancy: csd_: why would you put production config on your dev machines?

18:08 hiredman: csd_: it depends on how many places you might deploy to

18:08 csd_: gotcha

18:09 hiredman: csd_: for example at work we have dev, qa, ua, plus multiple production environments

18:09 csd_: so when you guys are working on a project you stick those vars into your bash_rc? or is there a tool that manages them

18:10 joshuafcole: Depends on your deploy system. If it's flexible enough, you can have a single config that's provisioned by the deploy system

18:10 technomancy: csd_: for env vars I put the default value in the code and only set the env var to override it, but I don't feel great about it.

18:10 joshuafcole: a good middle ground is to have a set of control scripts for your applications in each environment that have the right env var baked in

18:10 technomancy: one big downside of env vars is you can't change them without restarting the JVM, which is super tedious.

18:10 joshuafcole: mhmm

18:13 technomancy: ideally you'd only set them in actual deployments and not in development, because everyone gets super confused about how to reliably set env vars in dev in ways that will work outside bash.

18:13 csd_: puredanger: that library looks pretty useful

18:14 technomancy: environ might fix the change-without-restart problem; I forget

18:16 puredanger: well that's not an issue with java system properties

18:16 and those are supported by environ, so there's probably options at least

18:19 technomancy: nice

19:12 EvanR: is there a thing where you can put (example (my-fun a b c) d) which does a sanity check/doc. assert?

19:13 {blake}: ,(println ["Y" "N"])

19:13 clojurebot: [Y N]\n

19:13 {blake}: (map println ["Y" "N"])

19:13 ,(map println ["Y" "N"])

19:13 clojurebot: (Y\nN\nnil nil)

19:13 {blake}: huh

19:14 justin_smith: {blake}: the output of println gets mixed with the return value of map

19:14 {blake}: justin_smith, Right.

19:14 justin_smith: ,(dorun (map println ["Y" "N"]))

19:14 clojurebot: Y\nN\n

19:14 justin_smith: I assume you would never need that list of nils

19:15 {blake}: justin_smith, No, it's the sort of thing that trips me up when I hit one thing I don't understand, then start inserting println to try to figure it out.

19:16 justin_smith: right :)

19:16 using a proper logger helps

19:16 {blake}: What would qualify as a proper logger?

19:17 justin_smith: {blake}: another trick I like is (defonce debug (atom [])) followed by various calls to (swap! debug conj [:descriptor value])

19:17 {blake}: justin_smith, creates a running log of whatever you swap?

19:18 justin_smith: {blake}: right, and you can play with the data in the repl

19:18 {blake}: sometimes it helps because you can actually play with the values in the repl

19:18 but that's not a proper logger

19:18 it's just a technique I like

19:18 {blake}: *nod*

19:18 justin_smith: for a proper logger I would use tools.logging or timbre

19:19 {blake}: 'k. I'll have to check those out.

19:19 So, I =think= I have a vector of ["Y" "N"]. But when I try to map I just get a LazySeq.

19:20 justin_smith: map returns lazyseqs...

19:20 ,(class (map identity [1 2]))

19:20 clojurebot: clojure.lang.LazySeq

19:20 justin_smith: ,(class (into (empty [1 1]) (map identity [1 2])))

19:20 clojurebot: clojure.lang.PersistentVector

19:21 justin_smith: the problem with into / empty is it reverses the order of lists

19:21 but it preserves the type!

19:21 andrei: justin_smith: on the debugging atom, then you repeatedly ask for debug atom value after you do something?

19:21 utsc: hey guys, what is the transducer equivalent of "map<" from core.async?

19:22 justin_smith: andrei: I deref the debug atom in the repl, and do things with the data until I understand my bug

19:22 andrei: I also sometimes copy the data in said atom over into unit tests

19:23 andrei: justin_smith: but this is really nice :) I like that you could also take just a couple of items and inspect them instead of browsing through screens of logs

19:24 justin_smith: andrei: yes, I find it a very productive way to figure out what my code is doing while developing

19:24 {blake}: I'm trying to take a list and produce HTML, like (map #("<option>"%"</option>") l) and instead I'm getting back "lazySeq".

19:24 Which is the sort of thing I thought I was beyond at this point. :/

19:24 justin_smith: andrei: of course log still have their purpose (for example figuring out what is actually going on at runtime on the production server)

19:25 arrdem: {blake}: apply str? or just use hiccup :P

19:25 justin_smith: {blake}: apply str

19:25 (inc arrdem)

19:25 lazybot: ⇒ 38

19:25 agarman: question re: java generics interfaces in reify; do I just ignore the parameterized portion of the interface when implementing reify because java generics are erased anyhow?

19:25 {blake}: arrdem, Yeah. I don't usually mix up apply and map these days.

19:25 justin_smith: yeah, no downside to just using hiccup

19:25 {blake}: And, yeah, I'm going to use hiccup.

19:26 justin_smith: agarman: yeah, generics are an illusion :)

19:26 arrdem: hiccup is pure awesome

19:26 justin_smith: or more precisely - a java compiler concept, and we are not using the java compiler

19:26 {blake}: I was just throwing up some output.

19:26 arrdem: for sure

19:26 justin_smith: {blake}: hope it's not ebola!

19:26 {blake}: Generics are part of the long war of statically typed languages against their type systems.

19:26 * justin_smith waits for his rimshot.

19:27 {blake}: justin_smith, badum-tish

19:28 justin_smith: ,(str (map inc (range 5))) ; {blake}

19:28 clojurebot: "clojure.lang.LazySeq@1c3e4a2"

19:28 justin_smith: ,(apply str (map inc (range 5))) ; {blake}

19:28 clojurebot: "12345"

19:32 {blake}: justin_smith, Yeah. My face is red. And not from the Halloween makeup.

19:34 justin_smith: (pr-str (map inc (range 5))) ; another option

19:34 ,(pr-str (map inc (range 5))) ; another option

19:34 clojurebot: "(1 2 3 4 5)"

19:34 justin_smith: pr-str produces better output for debugging

19:35 ,((juxt str pr-str) "a")

19:35 clojurebot: ["a" "\"a\""]

19:35 {blake}: Fair point.

19:35 Ima use hiccup.

19:35 justin_smith: the pr-str differentiates a symbol from a string, str does not

19:36 {blake}: justin_smith, I've used it. Then forgot about it.

19:37 justin_smith: {blake}: reminds me of things I do :)

19:38 {blake}: justin_smith, It's been an amazing year spent with Clojure. I forgotten more than I've learned. Wait.

19:47 amalloy: oh boo, i just realized i actually do use C-z for things other than suspending. might need to find a new tmux prefix key

19:48 C-c C-z to go to emacs's repl is just too hardwired into my fingers for me to train out of

19:49 justin_smith: emacs' repl as in ielm?

19:49 nwolfe: I like ` as my tmux prefix key

19:49 justin_smith: I thought I was the only one who ever used that

19:50 amalloy: justin_smith: no, slime, of course

19:50 justin_smith: heh

19:50 amalloy: nwolfe: that sounds horrific. don't you ever type a `?

19:51 nwolfe: amalloy: Haha it's not horrific - the few times I do need to actually enter a ` character I just press it twice

19:53 * tuft is finally learning DataHand, which is going slooow.

19:54 tuft: crazy to tire mentally because i'm back to little muscle memory

19:54 nwolfe: amalloy: I believe all I had to set were these 3 lines: https://github.com/nwolfe/dotfiles/blob/master/lib/tmux.conf.symlink#L78-L82

19:55 amalloy: tuft: i forget, does it need two hands, or is there a one-handed way to do it?

20:06 justin_smith: wow, fascinating

20:06 the personal version duplicates qwerty

20:06 http://www.shareware-beach.com/2007/08/datahand-review/

20:08 danielszmulewicz: This is a proof of concept to show how ClojureScript can be used in the context of Apple's JavaScript for Automation. https://gist.github.com/danielsz/9c4ed2fbf4c0ac6b2d95

20:08 EvanR: is there a function to consume a seq and give the first non-nil value

20:08 justin_smith: EvanR: (first (filter (complement nil?) s))

20:09 ,(some identity [nil false 3])

20:09 dbasch: or (first (remove nil? s))

20:09 clojurebot: 3

20:09 justin_smith: ,(keep idenity [nil false 3])

20:09 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: idenity in this context, compiling:(NO_SOURCE_PATH:0:0)>

20:10 justin_smith: ,(keep identity [nil false 3])

20:10 clojurebot: (false 3)

20:10 justin_smith: dbasch: yeah, that one is better :)

20:13 EvanR: i saw this identity function, is it the identity function?

20:13 i guess the keep is relying on natural truthiness

20:13 justin_smith: EvanR: keep is like map, but it discards nils

20:14 EvanR: ok id still need first

20:14 justin_smith: yeah

20:14 if you don't want false, (some identity s) works

20:14 or you can just do (first (remove nil? s))

20:15 EvanR: i need to distinguish between nil and false here

20:15 so keep should work

20:16 and im going the hell home

20:17 * EvanR presses the "moon" key on the keyboard and sees what happens

20:21 amalloy: EvanR: ☽ 263D FIRST QUARTER MOON?

20:21 technomancy: isn't that ... the werewolf key?

20:21 * technomancy hides

20:21 rpaulo: heh

20:28 justin_smith: 🌕 is the werewolf key

20:30 AeroNotix: could any one point me to where `try` is implemented?

20:31 justin_smith: ,(special-symbol? 'try)

20:31 clojurebot: true

20:31 technomancy: huh, TIL

20:31 justin_smith: that means somewhere in java I guess

20:31 technomancy: ,(:added (meta #'special-symbol?))

20:31 clojurebot: "1.0"

20:32 justin_smith: technomancy: I found it via apropos because I wanted a way to know if something was a special form

20:32 I should do a "how to interrogate clojure" blogpost

20:32 technomancy: inc

20:35 justin_smith: I could do it all noir style. "So I'm sitting at my keyboard and up comes the most immutible lisp I've ever seen. Data structures up to here, concurrency like nobody's business"

20:36 AeroNotix: technomancy: yeah I was trying to see if I could write a slightly different try

20:36 then I thought that it's going to be tricky since it has atypical syntax

20:36 justin_smith: of all the repls in this city, she just had to dump her stack trace into mine

20:36 technomancy: "the most immutable lisp I've ever seen" hehe

20:37 AeroNotix: take a look at slingshot; it implements try+

20:39 AeroNotix: technomancy: hm, I wanted to make the catch expression more like python's

20:48 justin_smith: AeroNotix: in what way?

20:48 AeroNotix: justin_smith: (catch (ExceptionA ExceptionB) e ... )

20:51 justin_smith: AeroNotix: you could construct that with a macro, turining (my-try ... (catch [ExceptionA ExceptionB ExceptionC] e ...)) into (try ... (catch ExceptionA e ...) (catch ExceptionB e ...) (catch ExceptionC e ...))

20:51 AeroNotix: justin_smith: that's what I am doing

20:52 justin_smith: Oh, OK then :)

20:52 AeroNotix: but getting the semantics of the built-in try is a bit different from a normal macro

20:52 since you need to parse the body for the catch expression

20:53 justin_smith: isn't it treated like a lambda body? in what way do you need to parse it?

20:53 AeroNotix: justin_smith: because you need to know where to start looking for the list of Exception types

20:54 justin_smith: the source link on thie page is messed up https://clojuredocs.org/clojure.core/try

20:55 jeffterrell: Ah, you have to parse the body of the try expr to find where the catches begin. Is that it?

20:56 AeroNotix: jeffterrell: yeah

20:56 I'm like half way done

20:56 justin_smith: if I was doing this, I would take the body as a list, map over it, operating on all nodes that start with the symbol catch

20:57 AeroNotix: that's what I am doing

20:57 it's simpler than i thought

20:57 but it's like 2am so I may leave this til tomorrow

21:15 arrdem: ambrosebs: I feel like I owe you an appology now :P

21:15 ambrosebs: arrdem: no you win the awesome award

21:16 justin_smith: ambrosebs: watching your latest strange loop talk right now, good stuff so far btw

21:16 arrdem: ambrosebs: seriously tho if I could get core.typed dispatch I'd put that shit on everything

21:16 ambrosebs: justin_smith: why thank you

21:16 arrdem: I suppose I owe you a few more PRs before I get to complain about limitations tho

21:17 ambrosebs: arrdem: it might happen during my PhD, I've entertained combining predicate dispatch and Typed Clojure with the Typed Racket ppl

21:18 although that might quite be what you mean?

21:18 arrdem: ambrosebs: threw money at you once, 8/8 would do again

21:18 ambrosebs: core.typed enabled predicate/patern matching dispatch would be totally awesome

21:19 ambrosebs: haha well it might happen again during the summer. My visa rules are pretty darn strict.

21:19 but I still owe everyone a bunch of videos

21:19 I guess that's what christmas break is for

21:19 arrdem: :D

21:19 ambrosebs: yea, PhD and moving country kind of happened...

21:19 :P

21:20 arrdem: hehe odds are very good I'll manage to get out without a masters

21:20 but I'll be back of one

21:20 ambrosebs: you're aiming for phd?

21:21 arrdem: probably not, but the sort of lang/compiler stuff I think is fun is masters or better territory

21:21 so who knows. I sure don't yet

21:22 ambrosebs: well I hope you keep it in mind. you'd probably have a lot of fun

21:24 arrdem: I'm sure that being a grad/phd candidate would be more fun... my primary complaint against my undergrad is the non-cs/non-research work which I find really soul sapping. :/

21:24 also you're not the first person to tell me to stick around for a PHD. peer pressure alone may yet do it.

21:24 TEttinger: arrdem, you've got skills for sure. It would be great to see what you come up with as a researcher

21:25 ambrosebs, you're the main force behind Typed Clojure, is that right?

21:25 ambrosebs: TEttinger: that's me

21:25 TEttinger: it certainly looks good.

21:25 I haven't used it yet

21:26 arrdem: core.typed is good when you have some code you know mostly works and you want to really push types through and get assurance

21:26 AeroNotix: I found it incredibly annoying to use

21:26 arrdem: I've found that because there isn't type dispatch it tends to be a little heavyweight for exploratory use

21:27 AeroNotix: there's so much code out there that's untyped that you end up typing and then your code becomes a mismash of type specifiers and your real code

21:27 ambrosebs: it takes a while to figure out when to just give up type checking something. It can happen fairly often for certain types of code

21:27 AeroNotix: and then sometimes you need to change your code to make it more obvious to the type checker

21:27 ambrosebs: yep. That's a real problem at the moment because there's no runtime enforcement of types

21:27 arrdem: AeroNotix: yeah I've had a couple of those

21:27 AeroNotix: all in all -> don't care.

21:28 Try it out if it works for you but for any non-trivial codebases you really ought to start off with core.typed instead of adding it in later.

21:28 and even then the value is questionable.

21:28 arrdem: I mean... mad props to ambrosebs, for a project built by 1.01 undergrads it's awesome, it just needs more than one mans's worth of work.

21:28 justin_smith: ambrosebs: how well would core.typed and prismatic/schema work together? chocolate and peanut butter or ice cream and pickles?

21:28 ambrosebs: justin_smith: theoretically just fine. Right now, there's been no effort to figure out the details.

21:29 amalloy: (inc justin_smith) ; for lisp-noir

21:29 lazybot: ⇒ 110

21:29 ambrosebs: in theory you could use core.typed to ensure you're writing the correct Schema contracts and actually using them in the right spots to prevent type errors

21:29 the problem is core.typed doesn't understand schemas

21:30 and I've been apologising for that for about a year

21:30 justin_smith: so there would be duplicate effort

21:30 ambrosebs: no I think core.typed should be able to read schema definitions automatically

21:30 justin_smith: by duplicate effort I mean describing the same thing to core.typed and to schema

21:31 making core.typed understand schemas would by a one time cost that eliminates that duplication I would think

21:31 ambrosebs: that's what I think.

21:32 the problem is that if you have no static type annotations, functions arguments would always be inferred to have type Any statically

21:32 because schemas get applied in the body

21:32 so you wouldn't get as many static type errors as you might like, but they would be turned into runtime errors

21:33 justin_smith: I'm still finding my bearings with both schema and core.typed, thanks for the input

21:35 ambrosebs: unfortunately the biggest barrier to understanding Schemas is the map schema can have more than just keywords as keys

21:35 {:a Int (optional :b) Boolean}

21:35 HMaps in core.typed only allow keywords

21:36 so there's some shuffling that needs to be done, as well as figuring out how much structural equality I want to encode in the type system

21:37 I'd hope it's downhill from there?

21:37 :)

21:37 very optimistic

21:37 justin_smith: cool

21:38 ambrosebs: core.typed already understands merge/assoc etc, so that can be automated.

21:38 which is actually a pretty cool thing

21:39 being able to understand dynamically constructed contracts

21:39 justin_smith: nice

21:39 ambrosebs: *crosses fingers*

21:40 AeroNotix: justin_smith: https://github.com/AeroNotix/crap/blob/master/src/crap/exceptions.clj#L20-L36

21:40 despite it being 2AM (and now 2:30AM) I decided to give it a go

21:40 there's probably a better way to do that.

21:41 justin_smith: AeroNotix: looks fairly solid

21:42 AeroNotix: bedtime

21:42 fairuz: Hi guys

21:43 justin_smith: AeroNotix: the usage of both mapcat and unquote-splicing is something I would take a second look at

21:43 fairuz: Normally what do you guys use to make things modular? Something like a database module, booking module etc?

21:43 justin_smith: fairuz: namespaces and functions

21:43 fairuz: Or is it not a practice in clojure?

21:43 So all of them will be in the same project?

21:43 Nothing like different package or something

21:44 and module A add dependencies to module B, something along this way

21:44 Just need some ideas on how to start off my first clojure project

21:44 justin_smith: fairuz: that's what namespaces are for

21:45 fairuz: using immutibility changes the game a bit, and the need for data hiding is reduced

21:45 so it's common to put multiple related functionalities in one namespace

21:46 ambrosebs: curious if anyone's ever been bitten by ArraySeq's in Clojure and ClojureScript being mutable if you change the underlying array?

21:46 fairuz: justin_smith: Ok got it

21:47 Does we can have several files with the same namespaces? Or the namespace is tied with the file name?

21:47 justin_smith: namespaces should be reflected by the file name

21:48 amalloy: reiddraper: i don't think i ever mentioned it to you: i think you'd be interested to know i wrote a test.check generator for instances of Thrift schemas: https://github.com/amalloy/thrift-gen

21:49 justin_smith: ambrosebs: as I think I mentioned on twitter, I think the strong consensus is that it's something you just shouldn't be doing.

21:49 ambrosebs: justin_smith: right, that's assuming *you* are the one changing the array

21:49 amalloy: (which could be useful for anyone who works with thrift, even if you don't really care about test.check)

21:49 justin_smith: ambrosebs: though I could see an argument for having a warning / error if you can't prove the underlyign array does not escape scope of the immutible collection's creation

21:50 ambrosebs: well the "don't do that" would extend not just to mutating it, but using something visible for others to mutate

21:50 fairuz: justin_smith: ok got it. Thanks

21:51 justin_smith: ambrosebs: that would be nice actually, now that I think about it, to warn if you are constructing something immutible using a mutable basis that escapes that scope...

21:52 arrdem: ambrosebs: is this the aset on seq that's been floating around for a bit or is this a different case?

21:52 bbloom: ambrosebs: i think this is a cafe of "fast and loose reasoning is morally correct"

21:52 you can do better type checking if you just assume it's actually immutable

21:53 ambrosebs: bbloom: sure I've come around to the pragmatics of it

21:53 mindbender1: ,(bit-or 1 2 3 4)

21:53 clojurebot: 7

21:53 bbloom: s/cafe/case

21:53 mindbender1: ,(apply bit-or '(1 2 3 4))

21:53 clojurebot: 7

21:53 ambrosebs: ,(let [a (into-array [1 2 3]) p (seq a) _ (aset a 0 2)] p)

21:53 clojurebot: (2 2 3)

21:53 ambrosebs: arrdem: that one ^

21:53 arrdem: ambrosebs: yep

21:54 ambrosebs: bbloom: we should be able to still build a sound gradual type system that assumes seqs are immutable in the static portion.

21:54 reiddraper: amalloy: woah that's neat

21:54 ambrosebs: we basically need to track array mutations in static code, and also ensure any foreign arrays are copied before they are made seqs.

21:55 reiddraper: amalloy: i should create a 'test.check libraries' thing on the readme or something

21:55 mindbender1: sorry (apply bit-or '(1 2 3 4)) doesn't give the correct answer in cljs-repl.

21:55 arrdem: ambrosebs: is there a compelling reason to do that rather than declare the above an abstraction fault and unsupported?

21:55 mindbender1: there's no way to replicate it here

21:55 amalloy: ,(doc bit-or)

21:55 clojurebot: "([x y] [x y & more]); Bitwise or"

21:56 ambrosebs: arrdem: yes, a gradual type system is designed to protect the typed code to preserve its soundness at all costs

21:56 bbloom: ambrosebs: would be cool if you could mark the array type as aliased to an immutable position, and then throw an error on future changes to it

21:56 justin_smith: arrdem: well, you could create something "immutible" from a mutible source by mistake, and get bugs later. I think the ability of static typing to detect that would be nice.

21:56 mindbender1: amalloy: it doesn't work correctly in cljs-repl

21:56 ambrosebs: so even to protect someone passing an array from the Java API to clojure

21:56 bbloom: ambrosebs: but then of course i'm going to play devil's advocate and say that i want idempotent sets to be statically allowable ;-)

21:56 amalloy: mindbender1: what does it produce?

21:57 mindbender1: it keeps producing 3

21:57 that is the first 2

21:57 ambrosebs: bbloom: yes that's one direction my phd could go :)

21:57 I'll dig into linear types next year probably

21:57 amalloy: mindbender1: the cljs version of bit-or doesn't accept multiple args

21:57 ambrosebs: bbloom: what do you mean by your last remark?

21:57 amalloy: it takes exactly two

21:58 ambrosebs: what is an idempotent set

21:58 bbloom: ,(let [a (into-array [1 2 3]) p (seq a) _ (aset a 0 1)] p)

21:58 clojurebot: (1 2 3)

21:58 mindbender1: amalloy: but (bit-or 1 2 3 4) does the right thing

21:58 ambrosebs: oh right an aset :)

21:58 bbloom: ambrosebs: ^^ setting a[0] to 1 is totally safe to do

21:58 heh yeah

21:58 ambrosebs: i would love it if you figured out how to type check transients implementations

21:58 ambrosebs: that's just crazy

21:58 yea!

21:58 bbloom: ambrosebs: i dunno if you saw my various twitter ramblings about it

21:58 ambrosebs: this all sounds related

21:59 yes I did

21:59 I think I briefly talked to samth about it offline. but I was despairing about mutable seqs at the time.

22:00 amalloy: mindbender1: i see. bit-or is implemented as a variadic macro, but there's also a function version of it which only accepts two args

22:01 i'd say that's a bug: the function version should accept any number of args

22:01 mindbender1: amalloy: is there a function I can use to work around that immediately

22:01 justin_smith: how well does cljs handle / reflect the laxity about argument count in js?

22:02 amalloy: mindbender1: (defn good-bit-or [& args] (reduce #(bit-or % %2) 0 args)) is probably fine

22:02 justin_smith: not well

22:02 if you call a function with too many args, the extras just fall on the floor

22:03 mindbender1: amalloy: thanks it's working. I'd manage that for now!

22:16 Rakko: How can I make Clojure scripts into .exes instead of .dlls using Clojure-CLR?

22:27 justin_smith: Rakko: it looks like there was an unmerged patch for this (dunno if it really works) http://dev.clojure.org/jira/browse/CLJCLR-25

22:30 Rakko: also, it looks like lein-clr generates exe files https://github.com/kumarshantanu/lein-clr

22:30 you could use that, or figure out how it does it I guess

22:35 hiredman: ugh, the way pprint prints out vars is just terrible

22:35 every time I use it I cringe

22:35 amalloy: ,(clojure.pprint/pprint #'inc)

22:35 clojurebot: #<ClassNotFoundException java.lang.ClassNotFoundException: clojure.pprint>

22:36 Rakko: thanks, justin_smith !

22:36 amalloy: ,(do (require 'clojure.pprint) (clojure.pprint/pprint #'inc))

22:36 clojurebot: #<Var@107e78: #<core$inc clojure.core$inc@f278dd>>\n

22:36 justin_smith: (require '[clojure.pprint :as ugly-print])

22:38 hiredman: is it not the worst?

22:39 justin_smith: I'd hate to see the representations that weren't chosen for vars

22:39 TimMc: It's ... just ... *awful*.

22:39 [said in the voice of Cecil from Welcome to Night Vale]

22:39 amalloy: ,(str #'inc)

22:39 clojurebot: "#'clojure.core/inc"

22:41 hiredman: amalloy: what happens is vars aren't handled special they fall through to pprints deref handler

22:42 you can actually work around it, but having to do it over and over every time you use it is not great

22:49 http://dev.clojure.org/jira/browse/CLJ-1576

22:49 vote early, vote often

22:51 justin_smith: votd

22:52 Rakko: wow, there are at least two devins in the clojure world

22:58 Raynes: Two whole devins???????

22:59 TimMc: What a deal!

23:00 justin_smith: Raynes: any big picture hints of where I would start with making lazybot use the new irclj? If not I'll just dive right in

23:00 TimMc: Raynes: I feel like I haven't seen you in forever.

23:00 Raynes: justin_smith: One moment sir.

23:00 TimMc: I'm always around. :)

23:01 I just only hop in periodically. I've been rather preoccupied for a while now.

23:03 justin_smith: Ran 0 tests containing 0 assertions. 0 failures, 0 errors.

23:03 :)

23:03 Raynes: justin_smith: https://github.com/Raynes/lazybot/blob/master/src/lazybot/irc.clj

23:03 justin_smith: lazybot core is one thing, plugins are another.

23:04 justin_smith: Raynes: cool

23:04 Raynes: You'll probably break half the plugins no matter what you do.

23:04 justin_smith: that's a small namespace, promising

23:04 that's not promising

23:04 haha

23:04 I guess I may end up making some tests and or using schema for sanity's sake

23:04 Raynes: The important thing is to get the core connection stuff moved over, get the core plugin system using the new stuff

23:05 lazybot was not well written enough for unit tests to be very useful for it.

23:05 :P

23:05 You can probably get a testing framework in there pretty easily though.

23:05 justin_smith: Raynes: this is someting I have dealt with before. I'll see how crazy it gets.

23:06 Raynes: Well, you can do testing plugins really easily,.

23:06 justin_smith: Raynes: it's an approach to code reading

23:06 Raynes: All you have to do is emulate the mechanism that calls the plugin system.

23:06 justin_smith: "I think I know what this does, now I'll write a test to prove / disprove that" - then attempt your fix and see how the test responds

23:07 Raynes: sounds about right, yeah

23:07 TimMc: Just use Spring's PluginSingletonAbstractDependencyInjectionEmulatorEngineFactory to do it.

23:07 Raynes: TimMc: I wrote a factory for the first time a few days ago.

23:07 justin_smith: TimMc: oh of course, why didn't I think of that

23:07 Raynes: In Python :3

23:08 TimMc: https://www.refheap.com/92467

23:08 Look at that shit.

23:08 LOOK AT IT!

23:09 justin_smith: Raynes: man, if I squint my eyes I can see the conveyor belts and the little ladies with hair nets and latex gloves

23:09 Raynes: =D

23:09 I used dropwhile for the first time in python today.

23:09 Then realized getting the index of the item + using slicing was a better solution.

23:10 Then I took a swig of rum and cried myself to sleep.

23:10 TimMc: Every time you write the word "factory" a mid-level manager gets their wings.

23:14 kenrestivo: http://xkcd.com/224/

23:14 s/perl/python/g

23:17 Raynes: kenrestivo: you okay bro

23:18 kenrestivo: doing well. laffing at your riffs on python factories etc

23:23 Raynes: kenrestivo: I made some tunes recently. Didn't even listen to them for quality. Sending them to you for approval. :P

23:23 kenrestivo: my god, this whole town just went berserk

23:24 Raynes: Oh the sportsball

23:31 chenglou: how is clojure's = implemented for collections?

23:31 does it just compare the hashes?

23:31 TimMc: kenrestivo: Did the local sports team sports hard enough, or not hard enough?

23:31 chenglou: and always fast?

23:31 Raynes: TimMc: In PM he described it as cheering.

23:32 TimMc: Oh good!

23:32 Raynes: I think that means the local sportsball team did well.

23:32 At sportsball.

23:32 Dunno about the rest of their lives.

23:32 But the sportsball they've solidly done well

23:32 chenglou: also is there any blog post explaining how the hashing is done efficiently

23:32 kenrestivo: if people got this excited about $thing_that_actually_matters, we'd have all the world's problems solved

23:32 TimMc: I'm sure they will make good decisions.

23:33 chenglou: That's actually a really good question!

23:33 justin_smith: chenglou: it first checks for object identity, then structural equality iirc. Something to look at is hasheq as puredanger mentions here http://stackoverflow.com/questions/26622511/clojure-value-equality-and-sets

23:34 chenglou: because if the args are literally the same object, there's no need to go deeper, of course

23:36 chenglou: justin_smith: how is the structural equality comparison done? Just naive comparison?

23:37 justin_smith: chenglou: best to check the source at that point I would say

23:37 chenglou: kk. I guess I shouldn't be worrying about perf this early on but for some random experiments I have to compare large quantities of collections against others (freshly created, no structural sharing). I was wondering if the magic of clojure's hashing could make this not slow

23:38 justin_smith: chenglou: well, if nothing is shared I don't know of any alternative that wouldn't involve walking every collection at least once

23:40 chenglou: right, but if the hash's already produced beforehand then this isn't a problem

23:40 justin_smith: chenglou: well, hash can only tell you there isn't a match

23:40 chenglou: also interested in knowing the collision rate

23:40 justin_smith: if it's the same hash, you still need to walk and double check

23:40 it just rules out possibilities, it doesn't mark them

23:40 chenglou: true...

23:41 justin_smith: chenglou: puredanger could probably help you more than I but he seems not to be around, but I assume most of your answers sit in this directory here: https://github.com/clojure/clojure/tree/master/src/jvm/clojure/lang

23:43 Raynes: youre readme mentions ".lazybot/info.clj" - do you have an example or template for that file?

23:43 Raynes: lol my readme

23:43 My readme last updated when I was 12 or something

23:43 justin_smith: heh

23:43 chenglou: thanks

23:43 amalloy: justin_smith: it's config.clj now, iirc. should be one of those in the project root or thereabouts

23:44 justin_smith: Raynes: is it related to config.clj

23:44 oh, got it

23:44 lol

23:44 Raynes: justin_smith: It probably *is* confi

23:44 Oh hi amalloy

23:44 justin_smith: So amalloy apparently knows more about this bot than I do at this point.

23:44 Discouraging.

23:44 justin_smith: Raynes: awesome, I have my first edit going in right now (to the readme) :)

23:45 amalloy: Raynes: 683 commits / 145,375 ++ / 7,850 --; amalloy: 170 commits / 5,848 ++ / 5,387 --

23:45 i wonder how on earth you found 145k lines to add

23:45 Raynes: I worked hard

23:46 justin_smith: a very particular coding style: (\ndefn\nfoo\n[\narg\narg2\n...]\n...\n)

23:46 bbloom: wtf? `lein repl` is OOM-ing on a random project of mine now

23:53 does anybody have any ideas why i'm getting OutOfMemoryError when trying to run `lein repl` on a pretty simple project?

23:53 it happens during startup, before the repl is ready

23:54 justin_smith: bbloom: ick - bad plugin interaction? middleware bug?

23:54 bbloom: this project has no plugins or middleware

23:54 git on my dotfiles says i haven't changed my profiles.clj in 2 weeks

23:54 justin_smith: and nothing coming in from profiles.clj that would interact badly with that project.clj?

23:54 bbloom: this project worked a few days ago

23:54 justin_smith: oh

23:55 snapshot in the deps tree?

23:56 bbloom: only one snapshot, and it's something that shouldn't be in any public repos, so it shouldnt' have changed

23:56 Raynes: bbloom: Are you by chance on a raspberry pi?

23:56 justin_smith: I guess you could turn on heap dumps and analyze the dump in a profiler

23:56 bbloom: Raynes: sometimes my mac feels as slow as a raspberry pi

23:57 Raynes: bbloom: lol you should try a raspberry pi

23:57 I nearly tied compiling deps for a python project once

23:57 died, even

23:58 chenglou: justin_smith: TimMc seems like it's just plain item-by-item comparison

Logging service provided by n01se.net