#clojure log - Jun 26 2014

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

2:30 visof: hi

2:31 i tried to require (require 'clj-wordnet.similarity.algo.hso :reload) , but i got errors FileNotFoundException Could not locate clj_wordnet/similarity/algo/hso__init.class why it try to loat clj_wordnet not clj-wordnet

2:31 ?

2:32 i'm using tutorial here https://github.com/delver/clj-wordnet

2:40 vpm: willgorman: 25

2:41 oh fracking irssi, sorry :-/

3:06 cespare: technomancy: is there a way to change the column width slamhound uses?

3:11 latk: What does the hash symbol signify in this code: #(= contact %) ?

3:25 justin_smith: latk: # introduces a reader macro

3:25 here's a neat trick:

3:26 ,'#(= contact %)

3:26 clojurebot: (fn* [p1__25#] (= contact p1__25#))

3:26 justin_smith: we can see from the quoted form's expansion that it creates an anonymous function

3:26 the var name is a bit weird, but it should be clear what it did

3:27 sometimes you get the # back in the read form

3:27 ,#{1 2 3}

3:27 clojurebot: #{1 3 2}

3:27 justin_smith: ,(class #{1 2 3})

3:27 clojurebot: clojure.lang.PersistentHashSet

3:29 clodeindustrie: hi there, newbie here, can someone explain to me why I can do (= '(1) '(2)) and not (= (1) (2))

3:31 cmdrdats: clodeindustrie: '(1) is a list with 1 element, (1) is trying to call 1 as a function

3:35 clodeindustrie: The problem I was working on had ((fn foo [x] (when (> x 0) (conj (foo (dec x)) x))) 5) returning (5 4 3 2 1)

3:36 I guess I can't consider a list ?

3:52 latk: Is destructuring just the same as tuple unpacking in python ?

4:01 ddellacosta: latk: seems similar in the case of vectors, although I'm not sure what would be analogous for how hash-map destructuring works in Clojure--is there a way to do destructuring assignment with dictionaries in python?

4:02 latk: ddellacosta: There wasn't the last time I used Python :p

4:02 But yes, I suppose I meant similar rather than the same

4:03 ddellacosta: &(let [[x y] [1 2 3]] (println "x: " x ", y: " y))

4:03 lazybot: ⇒ x: 1 , y: 2 nil

4:03 ddellacosta: latk: & I guess that example is pretty similar to how Python does it, right?

4:03 er, ^

4:03 &(let [{:keys [x y]} {:x 1 :y 2}] (println "x: " x ", y: " y))

4:03 lazybot: ⇒ x: 1 , y: 2 nil

4:04 ddellacosta: ,(println "still locked out of clojurebot?")

4:04 clojurebot: eval service is offline

4:04 * ddellacosta curses at clojurebot

4:04 latk: ddellacosta: Pretty similar, yeah

4:21 I see the function keys returns the keys of a map. What does {:keys [delete]} mean?

4:22 Is this still using the keys function, or something else ?

4:24 clgv: latk: that's associative destructuring of maps

4:24 latk: it extracts the value bound to keyword ":delete" and binds it to symbol "delete"

4:25 latk: clgv: Ah, okay. That value can be any other datastructure, presumably ?

4:25 clgv: Also, why does it get the value bound to :delete?

4:25 clgv: latk: you mean the value that is finally bound to "delete"?

4:26 latk: clgv: Yes

4:26 clgv: yeah thats arbitrary

4:26 latk: Okay

4:27 clgv: ,(let [my-map {:a 42 :b (zipmap (range 5) (range 5)}, {:keys [a b]} my-map] (prn a b))

4:27 clojurebot: #<RuntimeException java.lang.RuntimeException: Unmatched delimiter: }>

4:27 clgv: ,(let [my-map {:a 42 :b (zipmap (range 5) (range 5))}, {:keys [a b]} my-map] (prn a b))

4:27 clojurebot: 42 {4 4, 3 3, 2 2, 1 1, 0 0}\n

4:27 clgv: latk: ^^

4:27 latk: clgv: Huh, okay. I would not have guessed that this is what :keys does :P

4:28 clgv: Incidentally, where is the best place to search for this kind of thing? Is there a clojure-specific search that will understand :keys ?

4:28 clgv: latk: just search for "clojure destructuring" or "clojure map destructuring"

4:29 there are at least two blog post explaining the details

4:29 latk: clgv: No sure, I meant in general if I found something I didn't understand :p

4:29 clgv: latk: ask here how it's called so that you can search properly ;)

4:29 latk: hah, okay :)

4:31 clgv: latk: or if you are new get one of the recent books and work through it. in my experience thats the fastest way to learn clojure. depending on your speed you can be through a book in 3-5 days fulltime with trying examples

4:33 latk: clgv: I skimmed through a book, but found some tutorials online that seemed more interesting.. if I get stuck today, I will go back to it

4:51 clgv: latk: ok, maybe that's the academic in me that wants to read such a book completely to get a solid basic knowledge ;)

4:52 latk: clgv: I tend to learn best by doing :P

4:58 clgv: latk: that's tricky with clojure since you have to learn a lot of new concepts (depending on your background) and thus you simply can't do the thing you dont know the concepts of ;)

4:59 by working through the book I dont mean just reading but also experimenting with examples ;)

5:22 latk: clgv: I'm most comfortable programming in Haskell, so I'm relativley comfortable with functional stuff. Admittedly I have no experience with lisps..

5:27 clgv: latk: yeah just wanted to share my thoughts ;)

5:27 latk: clgv: You may well be right - will have to see how it goes !

5:52 Could anyone explain the let binding in: http://bpaste.net/show/VeTUgekGw8tdmudTfIqX/ ?

5:53 It is more complicated than the simple examples I have read, and I don't quite get it.

6:06 viperscape: latk: http://bpaste.net/show/hyGOYllsePNAKNus2gh3/

6:07 it's destructuring the string's parts into a vector, called parts

6:09 you could just as well do (second parts) within the let bindings, or simply "last" since it's techinically bound to it through the destructuring

6:11 also, I wouldn't suggest using key terms such as first and last

6:11 latk: viperscape: Isn't all of the stuff inside the first set of [] in the same let binding ?

6:13 viperscape: ,(let [[f m l :as parts] (clojure.string/split "first last" #"\s+")] (= m (second parts)))

6:13 clojurebot: true

6:15 viperscape: the second line is simply reordering the f m l parts, essentially dropping middle-name if needed

6:15 or last, rather

6:15 latk: this is what I suspected

6:16 viperscape: http://blog.jayfields.com/2010/07/clojure-destructuring.html

6:21 clgv: be carefull with the combination of :or and :as ;)

6:44 hyPiRion: oh, that one's always "funny"

6:44 Also the fact that either :or or :as does its argument in reverse

7:06 latk: ,(.. "string" (substring 2) (equals "ring"))

7:06 clojurebot: true

7:07 latk: ,(-> "string" (substring 2) (equals "ring"))

7:07 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: equals in this context, compiling:(NO_SOURCE_PATH:0:0)>

7:08 ro_st: if i use key destructuring inside a when-let, does the when part look at each of the destructured locals?

7:11 luxbock: https://gist.github.com/luxbock/425ae5912656b9ff7803

7:11 what is the right way to translate the (new Date(d)) part to CLJS?

7:13 hyPiRion: ,(= (subs "string" 2) "ring")

7:13 clojurebot: true

7:13 latk: How can I find the documentation on .. and . in clojurescript ?

7:18 TimMc: latk: It's the same as in Clojure. (doc ..)

7:19 latk: . is a special form, though, and probably doesn't have doc from the REPL.

7:19 http://clojure.github.io/clojure/clojure.core-api.html#clojure.core/.

7:26 clgv: (doc ..)

7:26 clojurebot: "([x form] [x form & more]); form => fieldName-symbol or (instanceMethodName-symbol args*) Expands into a member access (.) of the first member on the first argument, followed by the next member on the result, etc. For instance: (.. System (getProperties) (get \"os.name\")) expands to: (. (. System (getProperties)) (get \"os.name\")) but is easier to write, read, and understand."

7:50 jonathanj: i feel like i'm being silly here

7:51 i created a new project with lein and do lein repl but i can't access stuff defined in my code as i was expecting:

7:51 clj-neon.core=> -input-stream

7:51 CompilerException java.lang.RuntimeException: Unable to resolve symbol: -input-stream in this context, compiling:(/private/var/folders/qj/lb3tbsp97gg74jpcxtcw30zm0000gn/T/form-init698424686803171253.clj:1:941)

7:51 core.clj:6: (defn -input-stream

8:27 jcromartie: can any Enlive contributors comment on https://github.com/cgrand/enlive/pull/107

8:29 2 weeks and no comments or nuffin

8:49 latk: Where can I find the docs for om.dom ?

9:07 ollivera: how can I access locale value in the array? :pageid "1" :translation [{:locale "ja_JP"},{:locale "zh_CN"}]

9:09 bbloom: that's a "vector" not an array

9:09 (doc get-in)

9:09 clojurebot: "([m ks] [m ks not-found]); Returns the value in a nested associative structure, where ks is a sequence of keys. Returns nil if the key is not present, or the not-found value if supplied."

9:09 ollivera: okay, thank you

9:09 bbloom: (get-in yourmap [:translation 0 :local])

9:46 visof: ,(clojure.string/split "helloWorld" #"(?=[A-Z])")

9:46 clojurebot: ["hello" "World"]

9:46 visof: ,(clojure.string/split "helloWOrld" #"(?=[A-Z])")

9:46 clojurebot: ["hello" "W" "Orld"]

9:46 visof: that's problem for splitting

9:47 how can i fix this ?

9:50 TimMc: visof: You haven't explained why you tthink that's wrong. :-)

9:51 visof: TimMc: i need to split in the first upper letter

9:51 if i got two or n upper letter consecutive then split at first one

9:52 ,(clojure.string/split "helloWOrld" #"(?=[A-Z][A-Z])")

9:52 clojurebot: ["hello" "WOrld"]

9:52 visof: ,(clojure.string/split "helloWORld" #"(?=[A-Z][A-Z][A-Z])")

9:52 clojurebot: ["hello" "WORld"]

9:52 TimMc: ,(clojure.string/split "helloWOrld" #"(?=[A-Z]+)")

9:52 clojurebot: ["hello" "W" "Orld"]

9:52 TimMc: Hmm, right.

9:53 visof: this techinque do what i need, so the solution maybe to check if there is [A-Z]+ pattern

9:53 if i got [A-Z] pattern then split at [A-Z]

9:53 TimMc: You could include a negative lookbehind for uppercase.

9:53 visof: if there is two then split at [A-Z][A-Z]

9:54 if there are n split at [A-Z]..n

9:54 is there a good way to do this?

9:55 TimMc: ,(clojure.string/split "helloWOrld" #"(?<![A-Z])(?=[A-Z])")

9:55 clojurebot: ["hello" "WOrld"]

9:56 TimMc: visof: but maybe you actually want the camel-snake-kebab library?

9:57 Dutch|AFK: quit

9:57 visof: TimMc: can it handle myAPI ?

9:57 have you checked it?

9:58 TimMc: visof: Haven't used it myself, but I think it handles this sort of thing.

9:58 visof: TimMc: i'm trying it

10:18 Shayanjm: Is there a way that I can completely replace the values in a ref with totally new values?

10:18 update-in seems to modify state with some applied function

10:18 but that seems a bit roundabout for what I'm trying to do

10:20 TimMc: Shayanjm: ref-set

10:20 Shayanjm: wow.

10:20 thanks TimMc

10:20 i should probably just generally read the API docs shouldn't I

10:20 TimMc: Shayanjm: I keep telling myself that one of these days I will skim through clojure.core.

10:20 Shayanjm: lol

10:20 TimMc: http://clojure.org/cheatsheet is good though

10:21 Shayanjm: ah

10:22 so if I'm understanding correctly: refs have write guarantees when transacted upon?

10:22 so I'm assuming to reap those benefits you would have to be transacting over multiple refs?

10:23 (i.e: can't be a ref & an atom?)

10:23 TimMc: yeah

10:23 Shayanjm: k cool

10:23 TimMc: Only refs (and in a certain sense, agents) participate in txs,

10:23 .

10:24 (Txns delay agent sends until they complete.)

10:26 Shayanjm: gotcha

10:27 Yeah basically I'm just getting a bunch of stuff from the NYT API, sticking it in (what used to be an atom) what is now a ref, performing SA on the URLS in the ref, and storing the results to a second ref so they can be 'gotten' easily

10:29 TimMc: Shayanjm: Make sure you understand what ensure does.

10:31 (Watch out for write skew.)

10:34 Shayanjm: wait what DOES ensure do?

10:34 it says it provides 'more concurrency than ref-set'

10:34 looking online, the provided examples aren't really clear either...

10:35 My best guess is: if I'm altering ref1 via ref-set or something, i'd need to throw ensure on ref2 to make sure it's not accidentally transacted on in the meanwhile?

10:35 but if I'm ref-setting BOTH refs within a single dosync, would using ensure matter?

10:37 TimMc: You got it. (in *2)

10:38 It prevents ref2 from being written to if you're only reading from it.

10:38 Shayanjm: I see

10:38 but isn't the whole clojure mantra 'no side effects'?

10:38 err, i guess lisp mantra?

10:38 TimMc: but multiple txns can call ensure on the same ref without interfering with each other (more concurrency)

10:38 Shayanjm: oic

10:39 so i could have 3x ensure on a ref without issues?

10:39 does ensure just last the lifetime of the txn?

10:40 TimMc: yeah

10:40 Shayanjm: cool

10:40 TimMc: (Theoretically, haven't tested or read the source.)

10:40 Shayanjm: kk

10:41 TimMc: Various Lisps use side-effects all over the place.

10:41 (mutablle cons, etc)

10:41 Clojure is focused on reducing *uncontrolled* mutation.

10:42 Shayanjm: gotcha

10:43 koreth__: That's even true of something like Haskell, really -- they're not against side effects per se over in Haskell land, it's just about keeping them well-contained and nailing down the semantics.

10:43 Shayanjm: gotcha

10:55 benzap: when destructuring, is there a way to bind a key to a new key name? like (let [{:keys [x :as blah]}]...

10:56 cbp: (let [{a :c} {:c 1}] c)

10:56 er

10:56 ,(let [{a :c} {:c 1}] a)

10:56 clojurebot: 1

10:57 benzap: ah ok

11:21 mocker: Is there a difference between these two things?

11:21 ,(merge {:a 1 :b 2} {:b 3 :c 4})

11:21 clojurebot: {:c 4, :b 3, :a 1}

11:21 mocker: ,(conj {:a 1 :b 2} {:b 3 :c 4})

11:21 clojurebot: {:c 4, :b 3, :a 1}

11:22 ndaly: I think merge can take an arbitrary number of arguments and conj only conjoins one

11:22 but I'm a total newb, so I could be wrong

11:22 mocker: :)

11:22 newbs unite!

11:24 llasram: When everything is a map I believe they have the same result, but `merge` makes that intent more explicit and handles a `nil` initial argument differently

11:24 ,(conj {} {:a 1} {:b 1} {:c 1})

11:24 clojurebot: {:c 1, :b 1, :a 1}

11:25 llasram: ,(conj nil {:a 1} {:b 1} {:c 1})

11:25 clojurebot: ({:c 1} {:b 1} {:a 1})

11:25 llasram: ,(merge nil {:a 1} {:b 1} {:c 1})

11:25 clojurebot: {:c 1, :b 1, :a 1}

11:25 mocker: Nice, thanks.

11:26 llasram: Hmm, and `merge` can apparently take 0 arguments

11:26 ,(merge)

11:26 clojurebot: nil

11:26 llasram: ,(merge {})

11:26 clojurebot: {}

11:26 llasram: Fun times

12:04 jjl`: llasram: quite a few functions 'do the right thing' with zero arguments

12:08 cbp: (merge) => nil is hardly the right thing

12:08 ddellacosta: cbp: what would the right thing be?

12:08 cbp: {}

12:09 ddellacosta: cbp: but merge doesn't work exclusively on hash-maps

12:09 although the docs seem to suggest it does...weird

12:10 huh, the implementation is pretty generic. Not sure why the docs say what they do.

12:13 ndaly: cbp: (seq {}) => nil

12:13 cbp: ndaly: ?

12:14 ndaly: cbp: not sure, just thought it might be relevant for the rationale behind (merge) => nil

12:15 something that's merging in a loop will probably need to know when the merge results in an empty map

12:15 TimMc: jjl`: That's a low bar, though. I mean, base cases are *kind of a big thing* in functional programming.

12:15 ndaly: and nil let's them use a truth test for that

12:15 anyway, I don't know enough to know what the right thing would be, but that may be part of the rationale

12:15 TimMc: Nil punning is the worst.

12:16 cbp: {} would be the identity value of merge

12:16 like how 0 is of +

12:16 ndaly: ,(merge {})

12:16 clojurebot: {}

12:16 TimMc: (Worst reason for a design decision, at least.)

12:16 ndaly: ,(merge)

12:16 clojurebot: nil

12:17 jjl`: TimMc: and there are many ways to solve them. e.g. the little schemer provides simple rules of recursion to catch them

12:18 TimMc: jjl`: I'm just continually surprised at how many Clojure fns don't support nullary or unary forms.

12:18 jjl`: TimMc: and there's where it comes down to opinion about what 'the right thing' is

12:20 TimMc: &(assoc-in {:a :b} [] 5)

12:20 lazybot: ⇒ {nil 5, :a :b}

12:20 edw: Do we have a One True Matrix library? Or something resemblng one? I see clatrix…

12:20 TimMc: It's shit like that.

12:21 Not only is the base case not supported, it clearly wasn't even considered.

12:21 seangrov`: &(get (assoc-in {:a :b} [] 5) nil)

12:21 lazybot: ⇒ 5

12:21 seangrov`: uhg, wow

12:21 clgv: TimMc: there is a ticket for that or update-in ...

12:21 rplaca: thus foiling my PAAS platform arbitrage edw: core.matrix is headed that way - it can wrap Clatrix and others

12:21 TimMc: ,(assoc-in {:a :b} [] 5)

12:21 clojurebot: {nil 5, :a :b}

12:21 rplaca: edw: core.matrix is headed that way - it can wrap Clatrix and others

12:21 edw: rplaca: Ah, thanks.

12:22 rplaca: I don't see a clojure/core.matrix repo on GitHub… Is it unofficial yet?

12:24 rplaca: edw: it's not officially part of Clojure yet, but I think it's on that road

12:24 edw: rplaca: Ah. I'll widen my search.

12:24 rplaca: the subject has been discussed and Rich, et al., are open to the idea of adding it when the time is right

12:25 edw: https://github.com/mikera/core.matrix

12:25 edw: rplaca: Thanks. Addin' it to my project.clj

12:25 rplaca: edw: cool

12:29 amalloy: TimMc: for what it's worth, it's not clear what the behavior of (assoc-in {} [] 5) should be, or the equivalent with update-in

12:30 TimMc: amalloy: The result should be 5.

12:30 amalloy: that's a result that's reasonable in this peephole focus, but do you really want to be the guy who tells everyone that assoc-in doesn't always return a map?

12:30 {nil 5} is stupid, but there's nothing that's great. {}, 5, throw-an-exception, are all sorta plausible

12:32 useful has versions of assoc-in and update-in that do in fact return 5 in that case, but it's not really the kind of behavior i'd welcome in clojure.core - https://github.com/flatland/useful/blob/develop/src/flatland/useful/map.clj#L95-L118

12:32 TimMc: I'm OK with it not always returning a map.

12:32 amalloy: i'd prefer it throwing an exception, personally

12:32 TimMc: I'd understand if people were upset, but... *shrug*.

12:32 amalloy: and if you want a version that returns 5 (which is a fine thing to want), that's easy to write

12:33 clgv: amalloy: for update-in there is a reasonable default, apply the function to the root map

12:33 amalloy: clgv: that's exactly the same as for assoc-in

12:33 you want to make update-in not always return a map; that's going to create as many issues as the current behavior

12:33 TimMc: &(update-in {:a :b} [] (constantly 5))

12:33 lazybot: ⇒ {nil 5, :a :b}

12:34 TimMc: &(assoc-in nil nil nil)

12:34 lazybot: ⇒ {nil nil}

12:34 TimMc: phweeee

12:34 ambroseb_: clearly that should throw an exception, but clojure.core error handling ..

12:35 amalloy: ambroseb_: well, as a static-typing enthusiast, of course you want it to never return a non-map! but TimMc thinks it's just as clear that it should return 5

12:36 clgv: amalloy: well for update functions that return maps that would be useful. if you use it with a function that does not return a map its your fault. at least the regular use case for empty path works...

12:36 amalloy: let's have it return a Maybe

12:36 clgv: i find it useful also; that's why i put it in org.flatland/useful

12:36 jjl`: and how is that going to be any different from using a sentinel value (such as nil) in practice, in a language like clojure?

12:36 TimMc: ambroseb_: Does core.typed support the notion of "non-empty coll"?

12:37 amalloy: but it's hardly the only sensible behavior - i'd argue it's not much better as a default than the current nonsense

12:37 clgv: amalloy: ah ok^^

12:37 ambroseb_: TimMc: yes.

12:37 amalloy: jjl`: Maybe was not a real suggestion

12:37 TimMc: So assoc-in could be described as returning a map if given a non-empty keyseq.

12:37 jjl`: amalloy: you never know. i saw a 2014 java article about a maybe type. and of course they missed the point :)

12:38 ambroseb_: assoc-in is special cased in core.typed, but it falls back on basically Any -> Any https://github.com/clojure/core.typed/blob/master/module-check/src/main/clojure/clojure/core/typed/base_env.clj#L1024

12:38 amalloy: i'm a big fan of haskell and its types, but you can't just dump them into clojure

12:40 ambroseb_: rich declined an enhancement for fixing assoc-in, but I think it's really a job for linters like Dynalint anyway.

12:40 same as the open ticket about `get` throwing on non-Associative

12:40 amalloy: for linters? how can a static linter fix assoc-in?

12:41 ndaly: it can't, but it can point out pathological uses

12:42 ambroseb_: sorry, Dynalint isn't really a linter, it redefines core vars to include better errors and warnings on undefined behaviour.

12:42 ndaly: interesting

12:42 ambroseb_: I consider assoc-in on empty path & get on non-Associative to be undefined behaviour, so Dynalint would complain if it gets evaluated.

12:43 amalloy: ambroseb_: couldn't the type be [(U nil (Associative Any Any)) (Seqable Any) Any -> (Associative Any Any)]? assoc-in always returns a map

12:43 ambroseb_: amalloy: correct, it's a dumb type either way.

12:43 cbp: :-P https://github.com/clojure/core.typed/blob/master/module-check/src/main/clojure/clojure/core/typed/base_env.clj#L865

12:43 Just in case comment doesn't work

12:43 ambroseb_: amalloy: ideally there'd be fancy dotted types linking the paths to the output map

12:43 * cbp hides

12:44 Bronsa: cbp: comment would insert a nil

12:44 ambroseb_: grep for "insane"

12:44 amalloy: cbp: yeah, comment is no good there. the comment is in case #_ doesn't work; exactly the opposite of what you thought

12:45 cbp: :-(

12:45 ambroseb_: cbp: as someone pointed out to me, core.typed uses every kind of comment, and then some

12:46 amalloy: well, actually comment wouldn't insert a nil after all, Bronsa

12:46 because this is inside another macro

12:46 so comment wouldn't even get macroexpanded, it would confuse the outer macro first

12:47 just like you can't write (defn (comment lol) f [x] x) - not because (comment lol) expands to nil, but because defn is baffled

12:47 Bronsa: amalloy: oh, sure. I assumed the wrapping expression was a function call

12:49 ambroseb_: I hear core.typed is in the new 7 languages book?

12:49 oh core.logic

12:49 haha, finger memory.

12:50 anyway, that's awesome.

12:53 on that note, I hope dnolen isn't still stuck in some airport :)

12:53 heard he had a nightmare travel to EuroClojure

12:54 TEttinger: I spent 24 hours in transit from australia to california once

12:54 ambroseb_: ouch

12:54 TEttinger: and there were people on my flight who had further to go

12:54 (when the family got back, the car battery was dead too)

12:55 ambroseb_: haha

12:55 TEttinger: there was everything, mechanical failure on a plane, while waiting for replacement there's a bomb threat..

12:56 so I hope dnolen doesn't have to deal with that

12:56 ambroseb_: my travel time to the US when everything goes *smoothly* is usually 30 hours.

12:56 TEttinger: ouch

12:56 going from asia or europe?

12:56 ambroseb_: Perth, Western Australia

12:56 TEttinger: ah.

12:56 even further

12:57 ambroseb_: yea, I'm sick of it so I'm moving to Indiana.

12:57 ;)

12:57 TEttinger: perth is IIRC incredibly hot, has unusual weather and extremely poisonous wildlife?

12:57 ambroseb_: haha sure!

12:57 TEttinger: which is why the trip didn't go visit

12:58 mdeboard: What's wrong with Indiana

12:58 dbasch: mdeboard: have you been to Indiana?

12:58 mdeboard: dbasch: I am here right now :)

12:58 dbasch: mdeboard: is that where you're from?

12:58 TEttinger: my brother watched a cricket game in melbourne in the summer. the heat was rough

12:59 tasmania was nice though

12:59 mdeboard: dbasch: ya, only been back a few years and moving out again next month

12:59 ambroseb_: I meant Indiana means I don't need to travel 30 hours to get anywhere :)

12:59 dbasch: ambroseb_: it depends on where you want to go. If you want a more central location try Denver or Chicago

13:00 TEttinger: atlanta is where 2 of the airlines have hubs I think

13:00 dbasch: the Traveling Clojurist Problem, also known as TCP

13:00 Indiana Pacers, also known as IP

13:00 mdeboard: lol

13:01 TEttinger: but it's hard to beat SF I imagine for meeting clojurists

13:01 ambroseb_: I have conferences in Montreal, St Louis and London, probably a few hours closer than Perth :)

13:01 mdeboard: Indiana has a really modern airport that is very uncrowded, TSA is best I've ever been through (and I *HATE* the TSA)

13:01 dbasch: SF rocks in that sense

13:01 mdeboard: I will miss Indianapolis airport and Indianapolis traffic the most

13:01 when I move to Austin

13:01 rplaca: but the only place to find Dan Friedman is in Indiana...

13:02 :)

13:02 dbasch: SFO is not bad compared to other airports in the US

13:03 amalloy: wait, is ambroseb_ actually moving to indiana? i can't keep track of the real statements in this conversation

13:03 ambroseb_: amalloy: yes, PhD starting at Indiana Bloomington in about a month.

13:04 amalloy: man, i'll have to start saying nicer things about core.typed

13:04 TEttinger: dr ambrose b

13:04 amalloy: now that i'm in striking distance

13:04 dbasch: ambroseb_: funny, a friend of mine is there right now at the ACM Web Science conf

13:05 amalloy: web science? i can't believe there's much science about the web, unless this conference is focused on actual spiders

13:05 dbasch: amalloy: go tell them :P http://websci14.org/

13:05 ambroseb_: amalloy: where are you?

13:05 amalloy: oh, LA. not actually that close, but closer than australia

13:06 my sister's getting her phd at purdue, though

13:06 ambroseb_: certainly

13:06 dbasch: I'm in LA too, but only for today

13:06 amalloy: so i've spent two days in indiana

13:06 practically a native

13:07 dbasch: my friend speaking at websci is now "Head of Query Understanding" at LinkedIn

13:08 cbp: wat

13:08 dbasch: cbp: exactly

13:08 better than another old coworker of mine who called himself "Chief Entomologist"

13:08 clgv: dbasch: you certainly need a head for query understanding :P :D

13:09 dbasch: clgv: and you want to hold on to it

13:09 one time I collected all the ways in which people had ended up at britneyspears.com through a query

13:10 you wouldn't believe the spelling creativity of the web

13:10 (you can tell this was 10 years ago, when Britney Spears was relevant)

13:11 $google brittny spiers

13:11 lazybot: [britney spiers 123 remix - YouTube] http://www.youtube.com/watch?v=goeAUbtolEE

13:11 amalloy: buttery spores

13:11 dbasch: damn, I get britney spears

13:11 btirnsy spirss works too

13:12 you can find britney spears on google while wearing box gloves

13:12 amalloy: dbasch: by induction, any google search at all yields britney spears, yes?

13:12 dbasch: boxing gloves

13:13 amalloy: enough monkeys typing will only create the works of shakespeare if they don't get distracted by britney spears first

13:14 it would be a fun game: guess the google result

13:14 rianah -> rihanna

13:15 google distance is always closer than Levenshtein's

13:21 aconz2: quick q on clojure-contrib libs. I'm looking to use clojure.contrib.java-utils, tho it seems like this has moved and/or been dropped from contrib? seems like a lot of libs listed on http://richhickey.github.io/clojure-contrib/java-utils-api.html have been dropped in the move to the clojure repo

13:21 dbasch: ~contrib

13:21 clojurebot: Monolithic clojure.contrib has been split up in favor of smaller, actually-maintained libs. Transition notes here: http://dev.clojure.org/display/community/Where+Did+Clojure.Contrib+Go

13:26 aconz2: thanks! @dbasch : could some work be done to update the page I linked? pretty deceiving, tho only as an artifact of googling. I'd be happy to do the work and make a PR if helpful

13:34 amalloy: aconz2: the work that should be done is to delete richhickey.github.io - no official clojure stuff has been hosted in his repo for years

13:35 it's all just old and decaying versions of stuff long since superseded by clojure.github.io

13:42 aconz2: amalloy: has an attempt been made to delete already? I mean the problem of "misinformation" is solved for me, but I imagine it would still be an issue for any other new(ish)comer

13:43 xeno__: Given 2 similar web apps written in Rails and Luminus, running on a quad-core i7 with 32GB RAM, would Clojure + jetty be more efficient in resource usage compared with Rails + Unicorn? I will be deploying a single-box app soon and wondered about memory usage and process size.

13:44 mdeboard: xeno__: Withoutknowing anything abou tyour application that's basically impossible to answer. With the JVM you can set max memory usage

13:44 dbasch: xeno__: it's kind of hard to answer that question in the abstract. "web app" doesn't say much about memory usage, the question is more about what you're doing in the backend

13:46 amalloy: xeno__: with rails, memory usage scales pretty quickly with number of processes, right? since you need N different rails processes. whereas the jvm has a high up-front cost just to start a single jvm, but threads are very cheap

13:51 xeno__: amalloy: So you give up, say, 200MB RAM for the JVM but can then get each process using a fraction of a comparable Rails process?

13:51 amalloy: xeno__: it's not close to 200MB

13:51 xeno__: amalloy: What, then?

13:51 amalloy: well, maybe it is. it's hard to say because a lot of it is disk buffers

13:51 mmapped jars, etc

13:51 xeno__: amalloy: Typically, I mean.

13:51 dbasch: xeno__ amalloy it also depends on what you're using to run Rails

13:51 amalloy: he said unicorn

13:52 not that i'm a rails expert or anything

13:52 dbasch: I only used Passenger, which I believe lets you play with processes and threads

13:53 xeno__: amalloy: Just trying to get some idea of trade-offs for a CRUD app which also does some quick calculations for about 1 in 3 requests.

13:53 amalloy: xeno__: well, okay, maybe it is close to 200MB. i have some clojure servers running, with the java heap size set small, so most of the overhead is the jvm itself. they have a resident set size of around 150MB

13:53 i've no idea how much of that they'd be willing to "give back" if there were memory pressure

13:53 xeno__: Just thinking if I have the basic principle correct, ie. allocate so much for JVM then each process is much cheaper?

13:54 amalloy: xeno__: well, there's only one process

13:54 threads inside the jvm aren't full OS-level processes, although i confess i'm not sure exactly what they are

13:54 justin_smith: xeno__: unlike in ruby, in the jvm it is viable to have multiple threads in one vm

13:54 xeno__: amalloy: 200/300MB is no big deal for me if there is 32GB in total available.

13:55 dbasch: 32GB for a web server. I feel old.

13:55 amalloy: you should have no trouble running just about anything on 32GB

13:55 my linode has 3GB and is running five or six different clojure webservers

13:55 justin_smith: xeno__: another data point: I have never had to restart a production clojure app because of a memory leak.

13:56 amalloy: i have!

13:56 dbasch: my crappy mp3 search engine in 1998 handled a peak of 200k queries in one day with 128 mb

13:56 amalloy: i spent weeks, maybe a month, on and off trying to track down a memory leak

13:56 cbp: it certainly didnt use lucene amirite

13:57 justin_smith: amalloy: yeah, wasn't saying it was impossilbe. But from what I hear from ex ruby users at my old job, constantly restarting ruby tasks that had their memory usage balloon uncontrollably was a routine thing

13:57 xeno__: dbasch: Check 'em out at Hetzner. 32GB/quad-core i7 for under 500 quid a year.

13:57 amalloy: yeah, that seemed to happen all the time when i was at geni, justin_smith

13:57 xeno__: justin_smith: Yes, exactly what I'm trying to avoid.

13:57 amalloy: they had a monit task that hunted for ruby processes whose memory usage was too high and automatically destroyed them

13:59 justin_smith: xeno__: from what I can tell, in clojure a task that has memory usage blow up isn't routine, it's considered an anomoly. I have clojure servers with very long uptime, only limited by the need restart in order to deploy updates

13:59 amalloy: yeah, for sure

13:59 my clojure servers have uptime that's the same as the machine itself

14:00 well, except 4clojure. that one restarts itself all the time because its fundamental requirement is to do stupid stuff (ie, evaluate user-supplied code)

14:00 xeno__: justin_smith: Yes, I'm attracted to what seems to be easier server management with Clojure/JVM compared with Rails

14:01 justin_smith: I started writing the app in Rails while learning Clojure and was going to rewrite later in Clojure but now I'm thinking get it done right at the outset.

14:02 amalloy: xeno__: that sounds like a good approach. it'll give you something concrete to work towards while learning clojure

14:02 avoid the classic problem of "anyone know an OSS project that wants help from someone who doesn't know how to do anything?"

14:03 justin_smith: xeno__: I think that would be good. And about your above question, I think the only way clojure would use more ram would be a fixed size price you pay at the outset (the size of clojure, size of the jvm), and that size is not enough to flatten a server, and after that it scales much better than ror / unicorn

14:03 xeno__: amalloy: Trouble is you get too deeply into the Rails MVC OO mindset.

14:03 tuft: xeno__: you're probably in a similar situation to me with django. our provisioning is so complex compared to just installing the JVM and deploying fat jars

14:04 xeno__: justin_smith: That was my concern. If there's plenty of RAM available it sounds like JVM is more efficient as the app scales.

14:04 tuft: yeah, real threads always helpful with conserving that shared stuff =)

14:05 justin_smith: xeno__: at my previous place of employment we had an in house clojure web framework that started as a rails replacement

14:05 xeno__: this, as you can imagine, was advantageous in some ways, and in others was an impediment

14:06 it's pretty heavyweight, and in the clojure world we do prefer combining modular libs over big kitchen sink included frameworks, but caribou is out there if you want to try it

14:06 and it does work

14:07 latk: could anyone point me to some more complicated examples of om applications? The example code I have found is pretty limited in scope.

14:07 gtrak: justin_smith: the choice of domain wording can be a little uncomfortable? :-)

14:07 xeno__: justin_smith: Had a look at it a while ago briefly. So it's a Rails clone?

14:08 justin_smith: But not heavier than Rails itself?

14:08 gtrak: how would you make a rails clone?

14:08 justin_smith: gtrak: let-caribou.in ? heh, I picked let-caribou since that had kind of a clojure-esque feel to it, and my tech manager decided it should be a .in domain because he was a perv

14:08 gtrak: justin_smith: hahaha

14:09 justin_smith: xeno__: not a rails clone, just developed as a smooth upgrade from rails

14:09 gtrak: well, it doesn't even have to go there, 'let the caribou in to our house? you're crazy?'

14:09 justin_smith: xeno__: so it was a priority to re-implement workflows and functionality that the workplace had grown fond of

14:09 gtrak: it'll wreck all the china and scratch the furniture.

14:09 xeno__: justin_smith: Could be very useful to me then unless I just drop the Rails prototype approach altogether.

14:10 justin_smith: Is it being developed actively?

14:11 justin_smith: xeno__: the company divested from clojure, and laid the clojure team off (both of us!)

14:11 we still address bug reports on github, and some day I may start up where I left off with some of the features

14:11 but it is less active after the layoff to be sure

14:12 mind that it has been used in many production sites, so it's pretty stable and mature (if very large)

14:13 xeno__: justin_smith: What's missing at present?

14:14 justin_smith: I started out with Luminus.

14:23 Frozenlock: I'll give plenty of love to whoever can solve this https://github.com/dakrone/clj-http/issues/202

14:24 * Frozenlock puts on sexy lingerie

14:26 gtrak: Frozenlock: does http-kit actually verify the certs?

14:27 I thought at least the server didn't do ssl at all.

14:30 amalloy: gtrak: it uses java's http library, which does verify certs

14:31 afaict java doesn't yet support SNI

14:31 gtrak: ugh I hate security

14:32 justin_smith: gtrak: Frozenlock: I've generally gotten the recommendation to do ssl via an nginx layer

14:32 nginx should be in front of whatever you have public facing, regardless

14:32 amalloy: justin_smith: oh, for sure. that's not the problem

14:32 they're talking about client-side

14:32 justin_smith: oh, that

14:33 amalloy: if you have one server with nginx serving ssl for two different domains, then java clients get mad

14:34 i had some trouble recently with the 4clojure.com server, which also hosts refheap, and does ssl for both of them. browsers can handle it because they have SNI support, but clojure and python do their ssl negotiation before sending the Host header, so nginx can't know which ssl cert to use

14:36 gtrak: at least you hide your lein-in-production behind an nginx

14:36 amalloy: i always thought lein was an abbreviation for leininproduction

14:36 german all sounds the same to me

14:37 gtrak: did you konw taht a cbaimrgde uvenisitry stduy...

14:38 arrdem: ow my face

14:38 * gtrak lost patience typing that way

14:38 gtrak: that could be a really simple clojure app

14:39 amalloy: gtrak: that story is actually a bit dubious - it's typically presented with "random" rearrangements that are easier to read than most orderings

14:41 Frozenlock: amalloy: "afaict java doesn't yet support SNI" I hope it's not the case. I've read it's somehow supported since 1.7, but I don't know enough about this particular subject :-(

14:42 About 4clojure and refheap, did you find a solution? Different servers?

14:42 amalloy: user> (munge "gtrak: that story is actually a bit dubious - it's typically presented with \"random\" rearrangements that are easier to read than most orderings") => "gratk: that sorty is atlucaly a bit douibus - it's tailclypy ptersneed with \"rdanom\" rgmaerenenrats that are eseair to raed than most orirnegds"

14:43 basically it works pretty well for short or common words, but things like "ptersneed" or "tailclypy" are pretty tough to figure out

14:43 gtrak: ptersneed is pretty funny

14:44 benzap: amalloy: you need to reduce the amount of characters movements from it's point of origin

14:44 amalloy: Frozenlock: we arranged for refheap's cert to be used in the case of clients that don't support SNI. that works fine because nobody ever uses 4clojure outside of a browser

14:46 ndaly: re: 4clojure.com: "So wait, I can't buy cheap real estate here?" … rofl

14:49 Frozenlock: https://github.com/OpenSourceFieldlinguistics/FieldDB/issues/1435

14:49 Damned be my limited brain. I don't understand why it doesn't work for Clojure.

14:50 DomKM: Are URI fragments not available in ring request maps? I don't see fragment/anchor/hash in the ring spec and ring mock is not parsing them.

14:50 amalloy: DomKM: they're not sent to the server at all, right?

14:53 a difficult scrambled word: dtcnuesrutirg

14:53 cbp: destructuring?

14:53 clojurebot: destructuring is http://clojure.org/special_forms#binding-forms

14:54 amalloy: well, okay, not *that* difficult. but harder than wehre

14:55 Frozenlock: ,(take 5 (slurp "https://www.4clojure.com"))

14:55 clojurebot: #<SecurityException java.lang.SecurityException: denied>

14:55 Frozenlock: err

14:56 Anyhow, how comes slurping works?

14:56 cbp: Frozenlock: what is the issue?

14:56 (doc slurp)

14:56 clojurebot: "([f & opts]); Opens a reader on f and reads all its contents, returning a string. See clojure.java.io/reader for a complete list of supported arguments."

14:56 amalloy: hm, good question. not sure; i thought that was broken

14:57 cbp: (doc clojure.java.io/reader)

14:57 clojurebot: "([x & opts]); Attempts to coerce its argument into an open java.io.Reader. Default implementations always return a java.io.BufferedReader. Default implementations are provided for Reader, BufferedReader, InputStream, File, URI, URL, Socket, byte arrays, character arrays, and String. If argument is a String, it tries to resolve it first as a URI, then as a local file name. URIs with a 'file' protocol are converted to

14:57 Frozenlock: cbp: clj-http can't handle SNI (https with multiple certs on the server), but `slurp' can.

14:57 cbp: oh

14:57 sorry i misunderstood :-P

14:57 TimMc: Frozenlock: What happens if you slurp a site with an invalid cert?

14:57 Frozenlock: TimMc: Good question...

14:58 * cbp scrolls up

14:58 Frozenlock: Anyone has one around?

14:58 gtrak: *BOOM* goes the JVM

14:58 TimMc: Maybe slurp just ignores the "cert failure" due to SNI.

14:58 DomKM: amalloy: I don't know. I guess I should find that out first.

14:58 TimMc: Frozenlock: https://www.cacert.org/ assuming you dno't have their root cert installed

14:59 amalloy: $google http spec fragment

14:59 lazybot: [RFC 3986 - Uniform Resource Identifier (URI): Generic Syntax] http://tools.ietf.org/html/rfc3986

14:59 DomKM: amalloy: Looks like you're correct. Thanks :)

15:00 Frozenlock: BOOM! javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

15:00 gtrak: just shell out to curl

15:00 TimMc: OK, so it doesn't ignore *that* kind of failure. :-)

15:01 Frozenlock: technology, y u no work?

15:02 gtrak: security is a pain-fractal

15:02 tuft: software is hard =(

15:03 gtrak: normal software at least creates value :-)

15:03 Frozenlock: security doesn't?

15:03 gtrak: unless of course it's getting hacked, sigh..

15:03 cbp: creates more jobs to maintain it at least

15:04 TimMc: I guess there can't be a pathod-like service that responds with whatever SSL cert properties you specify in the request.

15:08 (slurp "https://12345.sni.velox.ch/&quot;)

15:09 ndaly: gtrak: "security is a pain-fractal" is now my quote of the day

15:09 TimMc: Great! Your client [Java/1.7.0_51] sent the following TLS server name indication extension in its ClientHello: 12345.sni.velox.ch

15:10 Frozenlock: So, java 1.7 indeed supports TLS

15:10 TimMc: So slurp is doing the right thing.

15:10 Frozenlock: clj-http ---> javax.net.ssl.SSLException: hostname in certificate didn't match: <12345.sni.velox.ch> != <alice.sni.velox.ch> OR <alice.sni.velox.ch> OR <carol.sni.velox.ch>

15:11 gtrak: Frozenlock: most definitely httpclient doesn't use the same code paths.

15:12 Frozenlock: https://issues.apache.org/jira/browse/HTTPCLIENT-1119

15:12 check your version

15:12 Frozenlock: gtrak: https://github.com/dakrone/clj-http/issues/202

15:13 gtrak: oh, heh.

15:13 Frozenlock: Thanks anyway ;-)

15:14 gtrak: well, maybe clj-http is using an older version, is what I meant.

15:14 cbp: i think http-kit client should work? :-P

15:14 gtrak: nope, I'm wrong.

15:17 pain-fractal can be a black-metal overtone band.

15:57 benzap: is there a way to do exception handling on (load-string "")? It doens't seem like my try catch statement is catching anything

15:59 amalloy: there aren't a lot of good reasons to call load-string

16:00 jcromartie: benzap: how do you mean? (try (load-string …) (catch Throwable t …)) works fine

16:00 when the code loaded from the string contains errors

16:07 shaun_: Om as string cursor question: why does this fail? https://gist.github.com/shaunlebron/bca0fd36f26dee6fc6dd

16:10 ndaly: I'm trying to understand the statement, "Elegance and familiarity are orthogonal."

16:10 is there any chance someone knows in what context Rich said it?

16:10 shaun_: petehunt do you use Om?

16:10 petehunt: shaun_: no i don’t really know clojure very well

16:10 and i don’t have time to get good right now

16:10 bbloom: ndaly: you don't really need the context to process that statement

16:10 nullptr: petehunt: do you have a hammock?

16:11 bbloom: ndaly: it's simply the easy vs simple distinction rehashed

16:11 petehunt: nullptr: at work yes, not at home :P

16:11 shaun_: petehunt: I can imagine, well, thanks for react

16:11 bbloom: ndaly: elegant == simple, familiar == easy

16:11 ndaly: assuming you've watched simple made easy

16:11 ndaly: I haven't watched simple made easy

16:11 petehunt: shaun_: ;) lots of people over here. we owe the cljs community for a lot as well

16:11 ndaly: but that does illuminate it some, thank you

16:11 bbloom: ~simplemadeasy

16:11 clojurebot: Titim gan éirí ort.

16:11 bbloom: ~easy

16:12 clojurebot: Titim gan éirí ort.

16:12 bbloom: ~simple

16:12 clojurebot: Gabh mo leithscéal?

16:12 bbloom: *shrug*

16:12 ndaly: you can find it. it's worth watching for sure

16:12 ndaly: I'll look for it. Thanks.

16:14 benzap: I have this, am I doing something wrong with (try? http://pastebin.com/6aEsBs1j

16:14 ndaly: think this is it, if anyone else is interested: http://www.infoq.com/presentations/Simple-Made-Easy

16:15 oskarkv: ndaly yes. best video ever

16:15 Frozenlock: Pff, Rich Hickey is good, but he's no Carl Sagan :-p

16:16 oskarkv: :p

16:16 nullptr: "...billions and billions of state changes, but only one identity..."

16:16 oskarkv: hehe

16:16 shaun_: I told my intern simple != easy when teaching her clojurescript

16:16 gtrak: haha

16:16 shaun_: she interpreted that as meaning clojurescript is very difficult even though it's simple

16:16 Frozenlock: shaun_: clojurescript is neither simple nor easy ...

16:17 arrdem: Rich also isn't a god sadly :P

16:17 shaun_: Frozenlock: I thought that was the whole argument, that cljs is simple

16:17 arrdem: Frozenlock: simple compared to javascript perhaps

16:18 Frozenlock: ok, I could accept this comparison

16:18 gtrak: Frozenlock: the idealized CLJS is simpler than the current state of things.

16:18 bbloom: it's certainly simpler than javascript... up to, but excluding, javascript interop

16:18 which of course has all the complexity of javascript itself, and then some

16:19 shaun_: Frozenlock: if you can learn the syntax in 15 minutes, I would say simple: https://github.com/shaunlebron/ClojureScript-Syntax-in-15-minutes

16:19 amalloy: benzap: map is lazy

16:19 arrdem: shaun_: syntax is almost universally easy :P

16:19 Frozenlock: shaun_: I'm pretty sure this doesn't cover dealing with externs

16:19 benzap: amalloy: so it's evaluated outside ofthe try?

16:19 amalloy: your map immediately returns a lazy seq, then you exit the try/catch scope, then you realize the seq at some later date

16:19 arrdem: benzap: yep

16:19 Frozenlock: Also, "b isn't defined" is a terrible error message :-p

16:19 benzap: hmm, how would I ensure it's not lazy? wrap it in (seq?

16:20 arrdem: benzap: doall

16:20 gtrak: if clojure didn't already exist, we might not accept the principles, but the principles and the kinds of programs you can write with those abstractions are what's 'simple'.

16:20 amalloy: well, (try (doall (map ...))) is the smallest change

16:20 or i guess using mapv instead is smaller

16:21 benzap: ah thank you

16:21 mapv did the trick

16:21 amalloy: i'd recommend using a more explicit side-effecting construct like doseq, since i bet you don't care about the results of load-string at all

16:21 shaun_: Frozenlock: true, you mean interop? or externs for advanced mode

16:21 benzap: hmm

16:21 i might care about the side effects, it depends

16:22 amalloy: not the side effects, the return value

16:22 Frozenlock: shaun_: advanced compilation

16:22 amalloy: tbh i'm a little surprised load-string actually returns anything. i would have guessed it returns nil

16:26 arrdem: amalloy: well load returns the value of the eval of the tail form AFAIK, so that's not surprising..

16:27 amalloy: i just would never use load in a context where i want a return value; that's what eval is for. so i imagined that it doesn't give you a return value

16:27 Bronsa: arrdem: man you have short memory. load returns nil, you even patched t.e.jvm's load to return nil

16:28 arrdem: Bronsa: why do you think I leave type signatures and verbose docs behind? I can't remember this crap.

16:28 nor should I...

16:29 Bronsa: wut https://twitter.com/raymcdermott/status/482222051659632640

16:30 arrdem: er....

16:31 Frozenlock: For speed?

16:33 arrdem: Bronsa: HAH the reason I patched t.e.jvm is that clojure.core as usually is silly. (eval-string "(+ 1 2)") -> 3

16:33 bbloom: Bronsa: odd, i wonder why

16:34 arrdem: s/eval-string/load-string/g

16:35 Bronsa: bbloom: given the core.async impl I really cannot figure out what could go into the compiler

16:36 bbloom: Bronsa: maybe just some of the analysis needed to trigger the state machine rewrite

16:38 arrdem: bbloom: but what for? Clojure has eschewed TCO and other state machine rewrites for a long time..

16:39 bbloom: see amalloy's argument for this directed at me in the logs a few days ago, and Rich's old comments on TCO on Scheme lists.

16:40 bbloom: arrdem: i don't think i have those logs & our various bots seem down...

16:40 amalloy: a few days ago? i don't remember talking about this recently

16:41 bbloom: arrdem: anyway, it's not just for TCO

16:41 arrdem: core.async uses the state machine rewrite

16:41 but there dozens of other useful reasons to do state machine or other transforms to avoid stack consumption

16:41 Bronsa: bbloom: that seems a bit unlikely given that it just moved to t.a.jvm for that

16:41 bbloom: maybe he had another one in mind and needs some real compiler analysis data

16:42 Bronsa: bbloom: oh you mean the ssa transformation?

16:42 bbloom: the ssa transform depends on some ad-hoc analysis

16:42 but yeah, the ssa transform may be useful for other compiler stuff

16:43 * arrdem questions the utility of t.e.jvm/oxcart

16:43 bbloom: maybe there's a particular hot path in datomic or something that needs some optimization that ssa would simplify, that could justify some local transforms in the compiler

16:43 probably not worth speculating, tho

16:43 arrdem: bottom line: it's Rich's language and he's gonna do as he sees fit.

16:44 Frozenlock: inb4 clojure fork

16:44 arrdem: Frozenlock: inb4 inb4

16:44 bbloom: i mean, why even bother writing your own language if you're not gonna do as you see fit? :-P

16:45 hyPiRion: isn't the go block only able to detect visible <! and >! calls?

16:46 bbloom: hyPiRion: yes, but the compiler wouldn't help much with a dynamic extent transform b/c called functions are already compiled to byte code and need to support hot swapping vars

16:50 benzap: i'm wodnering, is there any clojure functions that sortof work like a rollback?

16:51 I want to try and load-string some scripts, but I want to make sure that I can rollback if anything doesn't evaluate

16:51 or does load-string take care of that?

16:51 hyPiRion: bbloom: Yeah, I wasn't thinking about the compiler analysis part though. Neither Go nor Erlang could do that either.

16:52 bbloom: huh? i'm 99% sure that go does inter-function analysis optimizations, at least within a single compilation unit

16:52 amalloy: there's no such thing, benzap. load-string can perform arbitrary side effects, like delete your hard drive, if that's what the code you're loading says to do. how do you roll that back?

16:52 arrdem: benzap: clojure's namespace and var binding structures are not first class and are not trivial to manipulate or restore. Consequently what you are asking for is very, very hard.

16:53 amalloy: arrdem: easier, it's impossible

16:53 m_m: Hi. What i can put at 'x' place for getting true: (= 2400 (reduce (fn [a b] (* a b)) x [1 2 3 4]))

16:53 amalloy: m_m: do you understand what that code is doing?

16:53 gtrak: amalloy: arrdem: benzap: you just need an 'inverse' function that takes a function, easy-peasy.

16:53 Frozenlock: benzap: if you want to deal with atoms you could use https://github.com/Frozenlock/historian, but otherwise I don't see how this could be done.

16:54 bbloom: Bronsa: https://gist.github.com/philandstuff/299cda371c7e74b03f18#q-other-possible-extensions

16:54 gtrak: it'll run the bytecode backwards

16:54 or forwards on an anti-jvm

16:54 benzap: hmm yeah, i'm probably going to be careful how I approach this

16:54 amalloy: gtrak: inverse :: IO b -> (a -> b) -> a -- this would be awesome

16:54 bbloom: Bronsa: had a brief chat w/ rich about generators/yield back when i gave a talk in NYC on Fipp

16:54 m_m: amaloy: I think that I need to add 1000 to vector [1 2 3 4]...but I dont know how. I understend rest of the code.

16:54 gtrak: it's like a turing machine, you just turn the tape the other way.

16:55 bbloom: Bronsa: basically i used reducers to emulate generators, but he suggested i try core.async's >! to emulate yield

16:55 hyPiRion: bbloom: Not generally I think?

16:55 amalloy: m_m: observe that reduce is being called with three arguments, a function, x, and a vector. you can't change the vector by changing x, of course - do you know what reduce does when it gets three args?

16:55 hyPiRion: Let me try to come up with an example

16:56 bbloom: Bronsa: thread here: https://twitter.com/BrandonBloom/status/356873464461791234

16:56 m_m: amalloy: So my x will be an in line function which will be conj 1000 to vector [1 2 3 4] ?

16:57 gtrak: the hard part is making sure that the inverse function halts.

16:57 amalloy: m_m: what does (reduce f x y) do?

16:57 bbloom: this is what i was trying to do w/ the CPS transform, where i labeled functions with :cps metadata... never did get it working, but i was operating at the macro level too

16:57 core.async puts locals in to fields on state machine object

16:57 m_m: amalloy: Use funtion 'f' on x and y ?

16:58 gtrak: ((inverse +) 3) -> ([1 2] [0 3] [-1 3 1] ...)

16:59 ((inverse delete-my-hard-drive)) -> (for [x universe-of-possible-hard-drives] x)

16:59 amalloy: here is an example: ##(reduce #(cons %2 %1) () '(a b c d))

16:59 lazybot: ⇒ (d c b a)

16:59 arrdem: "declare a fn as async"....

16:59 amalloy: that's quite different from ##(#(cons %2 %1) () '(a b c d)), isn't it?

16:59 lazybot: ⇒ ((a b c d))

17:01 m_m: amalloy: Aahhh i see...

17:01 amalloy: so (reduce f x y) is definitely not the same as (f x y), but rather (f (f (f x (first y)) (second y)) (third y)) ... and so on until ys is empty (and pretending here that third is a function that exists)

17:02 sveri: Hi, I just found this thread, trying to store an uri: https://groups.google.com/forum/#!msg/datomic/4bZUz2JjlbI/hKB_s3t5nIoJ Is there still no way to store a uri?

17:03 hiredman: sveri: you can create your own data reader that creates uri objects

17:04 sveri: it looks like according to that exchange you can store uris just fine

17:05 alandipert: or ye olde read-eval

17:05 hiredman: sveri: seems likely you are getting tripped up on loading a file but not evaluating it

17:05 alandipert: sure

17:05 alandipert: ##{:x #=(list java.net.URI. "http://foo.com")}

17:06 hiredman: alandipert: but that only works if the code is evaulated, in which case, why not just call the constructor?

17:06 alandipert: +1 tagged literal though

17:06 hiredman: ,(read-string "{:x #=(list java.net.URI. \"http://foo.com")}")

17:06 clojurebot: #<RuntimeException java.lang.RuntimeException: EvalReader not allowed when *read-eval* is false.>

17:06 hiredman: feh

17:06 anyway, you won't get a URL object

17:17 aaelony: Can a defrecord defined in namespace A be instantiated in namespace B ? I've seen this (http://cyrax.wordpress.com/2013/07/22/clojure-importrequireuse-defrecord-from-another-namespace/) but I still get an "Unable to resolve classname" error. Perhaps due to bad aliasing... any help appreciated.

17:20 bbloom: aaelony: use the -> factory function that gets generated

17:20 ,(defrecord Point [x y])

17:20 clojurebot: sandbox.Point

17:20 bbloom: ,(->Point 5 10)

17:20 clojurebot: #sandbox.Point{:x 5, :y 10}

17:20 bbloom: ,(fn? sandbox/->Point)

17:20 clojurebot: true

17:21 aaelony: bbloom: Thanks. I am using (->Point 5 10) and tried (->sandbox/Point) but not (sandbox/->Point)

17:21 bbloom: aaelony: the -> is just part of the name

17:22 ,`->Point

17:22 clojurebot: sandbox/->Point

17:22 bbloom: ,'you-can<-have-#strange->names%like*this+

17:22 clojurebot: you-can<-have-#strange->names%like*this+

17:23 aaelony: bbloom: that's perfect. Works like a charm, many thanks...

17:23 bbloom: it's not syntax, see (doc defrecord)

17:23 noonian: there is also (map->Point {:x 5, :y 10})

17:26 aaelony: On a similar note, suppose I have several defrecords defined and I want a way to instantiate an appropriate defrecord based on a keyword. I'm currently doing a cond on the keyword and if it matches then instantiating. But maybe there is a better way...?

17:26 bbloom: aaelony: any reason you can't just use the function directly?

17:26 ie are you serializing these keywords or anything like that?

17:26 ->Point is a value

17:26 it's just not round-trip serializable

17:27 ,(defrecord Rect [l t r b])

17:27 clojurebot: sandbox.Rect

17:28 bbloom: ,(let [cmd [:rect 5 10 15 20]] (apply ({:rect ->Rect :point ->Point} (first cmd)) (next cmd)))

17:28 clojurebot: #sandbox.Rect{:l 5, :t 10, :r 15, :b 20}

17:29 bbloom: just def a lookup table

17:29 aaelony: bbloom: well, here's what I'm trying to do. I have n file types, each in their own format. Each file type has a corresponding defrecord that knows about the fields expected in each file. Each defrecord also has a function that knows how to extract file datestamp information embedded in the filename (which unfortunately is different for each filetype). I know at runtime which file I'm interested in and I want th

17:29 e dispatch to work to get the right parsing of the datestamp info

17:30 noonian: aaelony: if you know the set of possible file types then a lookup table as bbloom suggests should work fine

17:30 you could also use multimethods for dispatch here

17:31 aaelony: noonian: I already rely on the defrecords for other things as well. I'd love to be able to have a lookup table from keyword to defrecord that would instantiate the appropriate defrecord.

17:31 bbloom: aaelony: a map of format to line parser seems like the no brainer way to go

17:32 aaelony: bbloom: so defrecords are out?

17:32 bbloom: defrecord is totally orthogonal

17:32 noonian: ,(defrecord Markdown [content])

17:32 clojurebot: sandbox.Markdown

17:32 noonian: ,(defrecord Org [content])

17:32 clojurebot: sandbox.Org

17:32 aaelony: bbloom: I kinda just want polymorphism

17:33 bbloom: aaelony: but you want polymorphism per file type, right?

17:33 noonian: ,(def lookup-table {:md ->Markdown, :org ->Org})

17:33 clojurebot: #'sandbox/lookup-table

17:33 aaelony: yes

17:33 noonian: that looks exactly like what I need

17:33 bbloom: aaelony: do you have any pressing need for *open* polymorphism?

17:33 aaelony: thanks

17:33 bbloom: aaelony: that's exactly what i showed you, go look at my example about :rect

17:33 heh

17:34 but i suspect that this isn't what you want really

17:34 do the different file formats have the same info in them?

17:34 or are they totally unrelated?

17:34 aaelony: bbloom: maybe I didn't understand initially. Let me try noonian's answer

17:34 the file formats are completely unrelated

17:34 bbloom: and how many records are in each file type?

17:34 order of magnitude. 10? 10000?

17:35 noonian: aaelony: my answer is the same idea as bblooms, i was just trying to illustrate a possible implementation

17:35 aaelony: each file type can have as many records as it needs

17:35 noonian: yes, that is correct. I just didn't understand what was meant without the example implementation.

17:36 bbloom: less than 30 records

17:36 noonian: but do the files represent the same things? with the format being just the representation

17:36 bbloom: aaelony: don't bother with defrecord

17:36 just use amap

17:36 it's overkill here

17:36 noonian: because in that case you might just want a single record with a polymorphic function to instantiate them from different formats

17:36 aaelony: yes, I like maps a lot. But I wanted to try dispatch with defrecords

17:37 bbloom: but you want polymorphic construction

17:37 you said the records from different file types are totally unrelated

17:37 aaelony: correct

17:37 bbloom: defrecord is for optimizing field storage (totally unecessary for small row counts) and for type dispatch on the record itself

17:37 you're dispatching on the file format... once.... before any records are created

17:38 noonian: to hook into the record dispatch you need to use protocols and have a record instance in the first place. since you want polymorphic construction you need to use a different method to get the instance in the first place

17:38 aaelony: there are 2 unrelated concepts, defrecords for the data in each file, and defrecords for data in each file's name

17:38 bbloom: aaelony: don't bother with defrecords

17:38 aaelony: unfortunate

17:38 bbloom: {:format :type1 :path "some/file"}

17:39 put :type1 and :type2 in a map and look up a parse function from that

17:39 no reason to bring complexity like types in to this

17:39 aaelony: maps are nice

17:39 well this is one area where it would have been nice to have a more OO view

17:40 bbloom: aaelony: not that i can tell

17:40 aaelony: suppose there are functions like parse-x where the implementation will differ depending on the file name format

17:41 there are many X's too

17:41 noonian: you can think of a map as an object whose entries are its fields

17:41 there are more ways than records to get polymorphism in clojure

17:41 bbloom: (def parsers {:format1 some-parser-fn :format2 some-other-fn})

17:41 aaelony: yes yes

17:41 of course

17:41 bbloom: if you need open dispatch:

17:41 (defmulti parser :format)

17:41 aaelony: bbloom: I'd prefer open dispatch

17:42 noonian: yeah, multi-methods are the way to go then

17:42 bbloom: (defmethod parser :format1 [file-map] (fn [line] ...)))

17:42 aaelony: I have used multi methods in the past, and they were very slow

17:42 bbloom: you're going to do ONE multimethod dispatch per file

17:42 i promise you, they are fast enough for that

17:42 sveri: hiredman: I see, I guess, thank you :-)

17:43 aaelony: anyways, I appreciate the help. I've got the defrecord solution working the way I want it.

17:44 bbloom: I believe you. Thanks again

17:44 noonian: you could also just take an optional argument which is a parse fn or another lookup table that you merge with the first one

17:45 aaelony: cool

17:55 ivan: why does putting code into :repl-options {:init ... without a (do wrapper magically break things with "Wrong number of args (2) passed to [whatever]"?

17:56 bbloom: ivan: i'm not an expert on this, but i think the init code is merged in to a bigger do in some way when you have plugins or layered protocols

17:56 seems like the rule is just always use do

17:56 ivan: that's depressing

17:56 thanks

17:56 bbloom: agreed

17:57 seems like it should be straightforward to put it in to a nested do & not have this problem

17:57 *shrug*

17:57 layered procotols => i meant profiles

18:00 ivan: my new security-hole-free REPL setup is { cat init.clj; cat; } | java -Xmx192M -Dfile.encoding=UTF-8 -cp "$(lein classpath)" reply.ReplyMain

18:00 I need that second cat to prevent it from quitting immediately, but unfortunately I need to EOF/ctrl-c a second time to exit or something

18:01 amalloy: ivan: i don't understand what problem you're talking about. :repl-options {:init (println 'hi)} works fine for me

18:01 ivan: amalloy: that's probably just println. try a load-file or an eval.

18:01 amalloy: if you mean :repl-options {:init ((println 'hi) (println 'bye))}, then of course that doesn't work

18:02 :repl-options {:init (eval '(println 'hi))} works fine too, of course. what is a specific thing that doesn't work for you?

18:02 ivan: :init (load-file "init.clj")

18:03 bbloom: amalloy: iirc i ran in to an issue where a plugin adds repl-options & lein tries to compose them

18:03 dunno if something has changed

18:04 amalloy: that load-file works fine too. i'm with bbloom: some middleware is putting stupid stuff in your project

18:04 ivan: amalloy: apparently it works without (do ...) if you don't have some lein plugins in your ~/.lein/profiles.clj

18:04 amalloy: try lein pprint

18:04 i have plugins in my profiles. you just have one that breaks things

18:04 probably in the manner bbloom describes

18:05 ivan: :plugins [[lein-ancient "0.5.4"]] was responsible

18:05 amalloy: (ie, by concatting together two lists into a list)

18:05 bbloom: amalloy: i think it's lein that does it

18:05 at least that's what i recall

18:05 it assumes your :init value is a list beginning with do

18:05 calls `next on it, then concats them in to another do

18:06 ivan: sorry, wrong culprit, lein-ancient is fine

18:06 :plugins [[mvxcvi/whidbey "0.2.2"]]

18:07 amalloy: bbloom: i'd guess that it doesn't assume that, but rather just merges lists by concatting them

18:07 as a generic merge on lists, not specific to repl-init

18:08 cespare: I'm having trouble with lein checkouts, where occasionally running 'lein jar' puts the .class files for a checkout dependency (say, mylib) into target/classes/. Once those are in there, they shadow any changes to the mylib source, so my project is broken until I run lein clean.

18:08 This is with :aot :all in the profile I'm using for lein jar btw.

18:09 also I've spent a long time trying to get a reliable repro without luck. I've seen it happen on a fresh pair of lein projects once, but now I can't make it happen again.

18:10 (It's an issue for our team because this breaks our projects for us once or twice a day on average)

18:10 amalloy: AOT compilation is a creeping misery, spreading sadness to all it touches

18:12 right, i think https://github.com/technomancy/leiningen/blob/f73a9998ff2992ab7574448e5884e08417c21526/leiningen-core/src/leiningen/core/project.clj#L512-L518 is all that's responsible for combining your repl-init values

18:13 if you were to lein-pprint, you'd see that your repl-init is set to something bad like ((load this) (print that))

18:13 bbloom: amalloy: is metadata "inherited"?

18:13 seems like the base profile could specify a sensible merge policy for repl-init

18:13 amalloy: bbloom: i dunno, he does all sorts of weird gyrations with metadata

18:13 i don't try to keep up

18:14 bbloom: nor do i, i do the absolute minimum leinfu to make the couple plugins i use work... frankly, i totally understand rich's preference for CLASSPATH=whatever java -jar

18:14 amalloy: it does look like the base profile could have :repl-init ^{:reduce (fn [a b] `(do ~a ~b))} ()

18:15 but i dunno

18:15 stephenjudkins: i have asked this question before, but: where does the documentation for `->` live?

18:16 arrdem: #(clojure.repl/doc ->)

18:16 hiredman: ,(doc ->)

18:16 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."

18:17 stephenjudkins: thanks

18:18 cespare: amalloy: okay, I got a repro with :aot

18:18 so it's not actually that.

18:19 *without :aot

18:19 cbp: lol arrdem

18:19 amalloy: cespare: if you can reproduce it without a :main or :aot i'll be impressed

18:21 (because :main implies AOTing the main namespace, which typically entails AOTing everything under the sun)

18:25 cespare: amalloy: yeah, you're right about :main.

18:26 Any ideas how to fix this? It seems like a bug

18:30 amalloy: i stay away from AOT as much as i can. what solution you choose will depend on why you have a :main and what tradeoffs you're willing to make

18:31 cespare: amalloy: all our projects have mains

18:31 they are servers

18:31 the problem i'm seeing is that it (apparently non-determistically) breaks checkouts

18:32 *deterministically

18:33 at this point, the main other alternative we're considering is getting rid of checkouts and going back to our old solution of symlinking our shared_lib code into all our projects.

18:33 which is pretty nasty, but at least doesn't break unexpectedly.

18:33 amalloy: you're being too generous - it nondeterministically breaks all kinds of things, checkouts being just one specific case. but i also stay away from checkouts, so i don't have any particularly good advice for you

18:34 cespare: so to summarize, you're saying that lein is broken?

18:34 amalloy: s/lein/clojure, really. aot just blows

18:34 cespare: you can put your shared_lib in a maven repo, and release it when there's a new feature, updating dependencies as needed

18:34 it's a hassle, but it's reproducible and works

18:34 cespare: we change it very rapidly along with our other code

18:34 that overhead wouldn't be acceptable.

18:35 hiredman: you could just not aot anything

18:35 cespare: but I need a main, yes?

18:35 cj3kim: Hi. I'm new to clojure. I downloaded a library called gaussian_elimination and I have placed it into my project directory that has a src/core.clj and project.clj file. Gaussian_elimination has the same structure. How do I require gaussian_elimination code in my project src/core.clj code?

18:35 cespare: our projects are mainly ring servers

18:36 amalloy: you can have a main which doesn't load anything else at compile time, but compiles it at app startup with a dynamic require

18:36 hiredman: cespare: there are tons and tons of possibilities

18:36 amalloy: it'll slow down startup significantly, but that's the price you pay

18:36 possibilities: but there's only one @possibilities

18:36 amalloy: ~lein

18:36 clojurebot: lein is http://github.com/technomancy/leiningen

18:37 hiredman: cespare: clojure comes with a clojure.main class that has a handy -m option

18:37 cespare: you can write some java stubs

18:39 cespare: you can create war files that run in some container instead of jars that run their own http server (althought the easiest way to do that stupidly aot compiles your code, but fixing that takes an afternoon)

18:41 speaking of which

18:43 amalloy: I think we talked about lein-ring aot breaking stuff at some point, I made some changes to a fork and now it doesn't aot https://github.com/hiredman/lein-ring/commit/aa2f9ad12502e3502af03087f6bb2e72e850a917

18:43 cespare: what if I put ^:skip-aot on my main

18:44 hiredman: cespare: why have a :main then?

18:44 cespare: just leave it out of your project.clj

18:44 use java -cp … clojure.main -m foo.bar to launch

18:45 cespare: ok, i'll give that a shot.

18:45 amalloy: hiredman: you must have a keyboard macro for "TODO: delete"

18:45 hiredman: I should

18:46 it needs lots of clean up for a "release" but I did a lein install and have been using it for all the clojurebot bits that use lein ring

18:48 cespare: hiredman: where do I get the clojure jar to put on my cp if I'm using lein?

18:49 amalloy: java -cp `lein classpath` # lol

18:49 cespare: ah

18:49 hiredman: cespare: lein uberjar jars up all of a projects deps in to single jar

18:49 amalloy: well, the # lol is there because this is not really a great idea

18:49 hiredman: that includes clojure

18:49 amalloy: really you want the uberjar

18:50 cespare: separate issue, but yes we normally use uberjar.

18:51 hiredman: the uberjar includes clojure in it, including the clojure.main class

18:52 cespare: cool, got that working.

18:52 I think we'll be able to purge most of the aot.

18:52 thanks guys

18:59 bra: I'm working on tuning a clj application via visualvm and the sampler is telling me that clojure.lang.Keyword.hasheq is my most CPU-hungry hotspot.

19:00 This is a bit surprising to me, since IIUC keywords are interned and their hashes are computed at construction time.

19:00 Is there something I'm missing here?

19:00 danneu: been stuck with node for a while on client projects. found out about this a couple days ago https://github.com/koajs/koa -- finally made node bearable

19:00 hiredman: bra: are you processing json?

19:00 bra: hiredman: Nope.

19:00 hiredman: ah well

19:00 turbofail: are you doing anything else that might convert strings to keywords?

19:01 hiredman: bra: some other kind of deserialization?

19:01 bra: I don't believe I'm converting strings to keywords anywhere

19:02 The primary hot loop is taking strings and a vec of [:keyword parser-fun] pairs and generating a map of {:keyword parsed-string-bit}

19:02 amalloy: hasheq doesn't suggest to me that he's creating keywords, but that he's comparing them

19:02 or using them as keys in a large map, i guess is more like it

19:02 bra: Yep.

19:03 Each map has ~36 keys, and I'm generating a few thousand per second in test.

19:03 hiredman: ah well, that makes sense

19:04 the call to hash eq is a required part of sticking keys in the map

19:04 bra: what version of clojure?

19:04 bra: hiredman: 1.5

19:04 1.5.0

19:05 amalloy: if the main thrust of your work is building large hashmaps, then no matter how fast hashing is, it will take a large part of your computational time

19:05 hiredman: 1.6 has some hashing changes, but I think those mainly effect the performance of hashing of collections

19:06 bra: Thanks all.

19:06 amalloy: you might be able to reduce the amount of rebucketing that goes on by creating the maps all in one go rather than incrementally? i'm not sure

19:06 hiredman: 1.6 may have a better distribution of hashcodes, but I am not sure, and I forget if that would even matter for keywords, they could just use the identity hashcode I think

19:07 amalloy: like, (apply hash-map (apply concat vec-of-kvs))

19:07 bra: Would replacing my map with a record be a fruitful approach?

19:07 amalloy: not with 36 keys

19:07 bra: Ah, I'll test the all-at-once approach.

19:07 kk

19:08 Why does the key count affect the performance?

19:08 amalloy: records perform best for small numbers of keys, because they have no structural sharing

19:08 Bronsa: hiredman: IIRC in 1.6 keywords use the murmur3 hash of the internal strings rather than their .hashCode

19:08 hiredman: obviously you should partition the keys up and do the merges in parallel using fold

19:09 gfredericks: amalloy: neither do array-maps

19:09 amalloy: uh huh...?

19:09 bra: amalloy: FWIW these are never mutated after creation. It's all field accesses.

19:10 gfredericks: amalloy: I thought you were advocating for records over regular maps?

19:10 oh wait no

19:10 hiredman: bra: if it is a fixed set of keys, use a vector assign each key to a spot in the vector

19:10 gfredericks: you just meant records with a whole bunch of keys are bad?

19:10 amalloy: mhm

19:11 gfredericks: english!

19:11 hiredman: (you could even use a transient or array while building up the vector if you need too)

19:12 if you aren't generating keywords it must be a fixed set I guess

19:12 amalloy: or just use an array as the canonical store. light speed!

19:12 hiredman: *zoom*

19:13 amalloy: then of course you'll have to write (case k :foo (aget arr 0) :bar (aget arr 1)) and so on, and you'll probably pay for hasheq in the case dispatch

19:13 bra: :D

19:13 hiredman: amalloy: write a macro that translates the keywords to numbers for you

19:13 bra: Right, I was a bit concerned about the API there.

19:13 Macro might be useful. Hm.

19:14 amalloy: hiredman: ztellman/vertigo. go big or go home

19:14 hiredman: amalloy: sure

19:30 cj3kim_: Hi. I've been trying to require code in lein, but I've been having trouble. Here's a gist with the relevant description and files https://gist.github.com/anonymous/39f3a8148eeba430db14

19:31 noonian: cj3kim_: there are a few problems, firstly you should only have one require form in a ns form, and you should use the keyword :require instead of the function require

19:31 hiredman: ~namespaces

19:31 clojurebot: namespaces are (more or less, Chouser) java packages. they look like foo.bar; and corresponde to a directory foo/ containg a file bar.clj in your classpath. the namespace declaration in bar.clj would like like (ns foo.bar). Do not try to use single segment namespaces. a single segment namespace is a namespace without a period in it

19:32 noonian: i would also guess that the namespace you are trying to require is gaussian.elimination and then you want to refer to the functions gaussian and vector

19:32 oh, nvm i didn't see the other files

19:33 amalloy: noonian: you can have multiple requires in a namespace

19:33 noonian: yeah, try merging the multiple use and require statements i.e. (:use [gausian.elimination.matrix] [gausian.elimination.vector] ...)

19:33 amalloy: it's not stylistically popular, but it's equivalent

19:33 noonian: hmm, i didn't know, but surely it's not idiomatic

19:33 cj3kim_: hmmr

19:34 amalloy: the problem is not in his ns statements, but probably in where he's put the files

19:35 noonian: yeah, it cant find gaussian, that would also happen if it is failing to compile

19:36 cj3kim_: noonian: how do I know if it's failing to compile? And, what can I do to compile it?

19:37 noonian: if you have a repl open, i would try evaluating (require 'gaussian.elimination.gausian :reload) and see if you get an error or not

19:38 cj3kim_: I ran it and it returned a "FileNotFoundException"

19:38 noonian:

19:38 amalloy: why do you have a file named core.js which contains clojure code? and where is promethix.core?

19:38 noonian: what is the directory structure and file names of your source tree?

19:39 cj3kim_: A moment please. Need to type stuff out in a gist

19:40 noonian: gaussian.elimination.gaussian should be at path src/gaussian/elimination/gaussian.clj with the leiningen default src paths

19:40 cj3kim_: noonian: I am using lighttable, an editor, as well. C

19:40 noonian: also, which file is the filenotfoundexception for? if it's a different source file of yours then your should try requiring that one

19:41 cj3kim_: noonian: Copy/pasting all relevant info to a gist. :)

19:43 noonian: https://gist.github.com/cj3kim/abac1f85ce1b4cb50af8

19:44 hiredman: https://github.com/LightTable/LightTable/issues/1520 learning clojure using lighttable seems like it would be hell

19:45 cj3kim_: hiredman: what would you recommend in its stead?

19:45 amalloy: cj3kim_: whatever text editor you're already comfortable with

19:45 and lein repl

19:46 hiredman: preferably something that has some kind of mode where it will help you match up brackets, but that is not a strict requirement

19:47 nullptr: yeah, i think show-paren-mode is sufficient when you're starting -- paredit would be a bit much for a newbie

19:50 amalloy: cj3kim_: everything there seems okay (except you misspelled gaussian in your repl example)

19:50 you'd probably have had an easier time just pushing the whole git repo for someone else to repro with

19:51 noonian: cj3kim_: (require 'gaussian.elimination.gausian :reload) you mispelled gaussian gausian

19:51 i was using light table for a while but using lein repl for the repl

19:54 amalloy: noonian: that's true, but it's also breaking in his ns clause, where it *is* spelled correctly, so i'd guess his dependencies are not present somehow

19:55 like maybe you haven't restarted your repl since adding the dependency? but i have no idea what light table does automatically for you

19:56 DomKM: Anyone know why protocols are typically prefixed with `I`? Is this because of their similarity to Java interfaces?

19:57 amalloy: that is why, DomKM. but it's not a universal convention; you're free to ignore it

19:57 (just like prefixing java interfaces with I isn't universal)

19:58 DomKM: amalloy: cool, thanks.

19:58 noonian: amalloy: i agree, i asked him to require it by hand to see if one of that files deps was missing

20:07 cj3kim_: noonian: amalloy: Thanks for the help

20:15 ttasterisco: hm, prefixing java interfaces with I was never the norm. that's from .net

20:15 java interfaces were always -able

20:16 systemfault: List…able? :P

20:16 ttasterisco: Runnable

20:16 Callable

20:16 Iterable

20:16 etc

20:17 amalloy: ttasterisco: it leaked in from .net

20:17 it's not used in the jdk itself, but lots of people who write java do it

20:17 ttasterisco: damn migrants

20:17 burn them

20:17 bbloom: Bronsa: now i'm all self-conscious screwing up and force pushing on public repos :-P

20:17 amalloy: how dare they force their lambdas on us

20:18 bbloom: i usually abuse the crap out of my own fork, but now i have observers....

20:18 amalloy: bbloom: your nick is confusing to type. double-single-double? i propose you change your last name to Blloom

20:19 bbloom: amalloy: does bb<tab> not handle it?

20:19 amalloy: well, i actually do bbl<tab>

20:19 but this time i was doing a google search to see if i could guess what repo you were talking about

20:19 bbloom: so does some random guy in #ruby, who has never actually talked to me, but mentions me with some regularity

20:20 cj3kim: amalloy: noonian: pushed to git for help. https://github.com/cj3kim/promethix

20:20 Bronsa: bbloom: oh just ignore me. if it makes you feel better I screw up a lot on t.a/t.a.j and I cannot even force push because of autodoc

20:20 cj3kim: noonian: my general feeling is gaussian_elimination isn't compiling

20:21 bbloom: Bronsa: not just you, but you made me aware of the audience

20:21 amalloy: cj3kim: version 1.0.0 of gaussian_elimination chooses to call its namespaces gaussian_elimination.gaussian

20:21 rather than what's on github, which is gaussian.elimination.gaussian

20:21 cj3kim: amalloy: how do you know this?

20:22 amalloy: i opened up the jar and read it

20:22 cj3kim: and how can i check in the future?

20:22 amalloy: are you sure you want to use this library? it looks pretty slapdash

20:22 Bronsa: bbloom: then I'll pat my back for being successful in screwing you up. pushing will never feel the same

20:22 bbloom: Bronsa: i'm super careful when specifying what-to-push-where, but when i work on my own tracked branch, i view the server as a backup & push constantly

20:23 cj3kim: ah, i see. thank you

20:24 amalloy: cj3kim: it looks like https://github.com/skatenerd/gaussian_elimination/tree/358e9e9cb3c8c6f40b4684550c854874f3860173 is the code you are actually using

20:24 cj3kim: amalloy: oh my god >_>

20:24 amalloy: hm?

20:25 cj3kim: my friend had downloaded an older version of that library which used all dots instead of the underscore

20:25 i just wasted three hours!

20:25 amalloy: i don't think your friend's download is relevant? that jar is being fetched from maven

20:26 and dots are actually the "latest" code (ie, two years old), which he hasn't ever released to maven (but it's the latest git)

20:26 cj3kim: we used this code <-https://github.com/skatenerd/gaussian_elimination/blob/master/src/gaussian/elimination/gaussian.clj

20:27 thanks for your ehlp

20:27 amalloy: right. that code is newest, not older

20:27 and he just never released it

20:28 anyway, have fun. it looks like the author probably knows his math but doesn't know his clojure

20:28 bbloom: i think "meth" is my new favorite symbol

20:29 amalloy: bbloom: if you've been doing meth i need to tell you it's not just a symbol, it is an addictive and dangerous drug

20:29 see, eg, the AMC documentary Breaking Bad

20:31 bbloom: amalloy: saw that. stellar investigative journalism. i need to figure out how to get out of the meth business and in to that empire business thing

20:34 cespare: If i no longer have a :main, is there another way to specify the starting point for my lein repl?

20:34 starting namespace I mean

20:34 hiredman: there is no such thing as a starting namespace

20:35 noonian: if you have a user namespace on the classpath it will use that though

20:35 hiredman: noonian: you keep answering a question that is slightly different then the asked one

20:36 noonian: in this case i don't know the answer

20:36 cespare: hiredman: seems to me you very likely understand what I'm asking

20:36 hiredman: cespare: sure, you want lein to require and in-ins in to a given namespaces when you run lein repl

20:37 cespare: sounds about right, if that's what it does when you do :main myproj.core

20:37 is there another way to ask lein repl to do that?

20:37 ttasterisco: cespare: in there repl, there's no "main". if you mean when doing `lein run`, then you can use the -m

20:37 hiredman: cespare: I would suggest either you'll be in an editor, and evaluating the file at hand in the editor will in-ns the repl's state to the same namespace

20:38 ttasterisco: *the

20:38 cespare: hiredman: Yep, that's true 95% of the time. The other 5% it's convenient for the repl to automatically load the main namespace.

20:38 hiredman: cespare: why?

20:38 cespare: it's not a big deal, just wanted to know if there's a workaround, now that I'm removing :main from all my projects.

20:39 hiredman: cespare: how likely is it that you are going to be using stuff in the main namespace?

20:39 cespare: quite likely, if i'm just playing around a bit.

20:39 hiredman: cespare: sure you could use something like the repl-init options

20:39 cespare: i've been writing clojure for the past 9 months or so, and I know from experience that it's something I occasionally want to do.

20:40 hiredman: there we go.

20:40 I see :repl-options { :init-ns foo.bar }

20:40 * cespare tries that out.

20:40 hiredman: in my experience using lein run means I am doing performance testing of some functionality of one particular namespace on an ec2 node

20:41 so I would have in-ns to the particular namespace anyway to start fiddling with it

20:41 synkte: What's the best way to seed a database in clojure?

20:41 amalloy: cespare: try `lein help sample` next time you are looking for some lein feature

20:42 (this is the same as leiningen's sample.project.clj on github, so you can look there instead if you prefer)

20:42 cespare: hiredman: sure, understood. It's just that starting out in a commonly used namespace of my project is better than not

20:43 hiredman: cespare: I think lein doing that kind of thing encourages people to form incorrect ideas about namespaces as something that contains in some way the execution of code

20:43 TimMc: cespare: If you still need a main entrance point but don't want AOT, I wrote lein-otf a while back.

20:44 tuft_: cespare: the trick i'm using is creating a user.clj in the project that's just a bunch of requires, if we're talking about the same thing

20:44 cespare: TimMc: hey, neat!

20:46 TimMc: cespare: You can do the same trick yourself with less infrastructure (just have a tiny AOT'd main ns that dynamically requires your real entrance point and calls it) but lein-otf is a drop-in.

20:47 I actually don't know if I'd use lein-otf myself these days; it adds a potential complexity cost to the project and an explicit approach + plenty of comments might be better.

20:48 cespare: I think I'm just gonna go with the clojure.main -m ... approach for now.

20:49 Is there some PSA about AOT causing all kinds of problems that I've somehow missed since starting to use clojure?

20:50 noonian: getting burned by AOT is a clojure right of passage

20:50 TimMc: No kidding.

20:52 hiredman: https://groups.google.com/forum/#!topic/clojure/Bs70_PUj-TY is maybe the first anti aot screed, a bit dated by now I am sure

20:53 https://groups.google.com/d/msg/clojure/Bs70_PUj-TY/azR1gNleT_oJ good for a chuckle

20:58 cgag: i'm using clojurescript and trying to do the equivalent of rangy.createRange() by doing (.createRange js/rangy), but running into undefined is not a function am i doing something obviously wrong?

20:59 TimMc: hiredman: The C-in-C bit?

21:00 bbloom: Bronsa: have you found a need to differentiate let and loop bindings at all?

21:01 Bronsa: for eclj i differentiate between locals via let, jvm classnames, and of course vars... i haven't needed to differentiate let & loop at all, but i definitely need to figure something out for object fields

21:02 Bronsa: for that, i'm torn between (symbol-macrolet [x (.-x this#) ... and true fields support

21:02 ddellacosta: cgag: is rangy getting pulled in properly?

21:02 bbloom: Bronsa: but seems like loop is just a shorthand for fn really, if you have tail calls like i do

21:03 Bronsa: bbloom: in ta every local has a :local field that indicates where it comes from

21:03 bbloom: uhm, there are some differences between loop/fn locals wrt type hints & primitive support

21:03 bbloom: Bronsa: hm, interesting

21:04 Bronsa: bbloom: not sure if that is a problem at all but fn args can only be long/double primitives while loop/let locals can be whatever primitive type you want

21:04 bbloom: i was looking at :local, but noticed loop & let seemed to mostly follow the same code paths

21:05 Bronsa: bbloom: yeah I think in tej we never need to differenciate between :let/:loop locals

21:05 bbloom: Bronsa: that's good to know, thanks. doesn't affect my environments, but will affect me when i get to the compiler

21:05 Bronsa: but I'm not 100% sure, let me check

21:05 bbloom: (hints, i mean)

21:06 cgag: ddellacosta, now that I'm trying to use it with just pure js I'm not as confident as I was. The code fails in my test.js file fails even though it runs in the console, don't think it's clojurescript related anymore.

21:06 ddellacosta: cgag: ah, okay. That happens too. But it sounds to me like rangy wasn't getting pulled in properly, perhaps.

21:10 bbloom: Bronsa: luckily, i don't have to abide by the rules for eclj, so i'm going to implement symbol-macrolet & use that for fields :-)

21:10 Bronsa: bbloom: yeah I checked, I never need to differenciate between :loop and :let locals

21:10 bbloom: Bronsa: cool

21:11 Bronsa: any crazy thing about field symbols i should know? or is (intelligently) replacing foo with (.-foo this#) seem sane?

21:11 Bronsa: bbloom: I was just thinking about that.

21:11 oh yeah

21:11 bbloom: you cannot (set! (.-foo this#) bar) I believe

21:12 I might be wrong on that one though

21:13 bbloom: oh you indeed cannot but that's a compiler bug that I submitted a patch for, lol

21:13 bbloom: heh

21:13 Bronsa: nothing else comes to mind then

21:14 bbloom: ,(deftype A [x])

21:14 clojurebot: sandbox.A

21:14 bbloom: ,(.x (A. 1))

21:14 clojurebot: 1

21:14 bbloom: ,(deftype A [^:unsynchronized-mutable x])

21:14 clojurebot: sandbox.A

21:14 bbloom: ,(.x (A. 1))

21:14 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: No matching field found: x for class sandbox.A>

21:14 bbloom: ^^ interesting....

21:14 Bronsa: bbloom: yeah mutable fields are private

21:14 bbloom: makes sense, but i didn't think rich believed in encapsulation :-P

21:15 Bronsa: bbloom: mh if you use symbol-macrolet I belive shadowing will be problematic? also using the symbol in macros

21:15 bbloom: Bronsa: that would be an issue if symbol-macrolet was a macro, but i'm going to implement it in the interpreter

21:16 Bronsa: bbloom: probably a better approach would be replacing the field at macroexpansion time

21:16 bbloom: Bronsa: there really isn't a "macro expansion time" in eclj

21:16 it's interleaved with evaluation

21:16 the assumption is that macros are pure & terminate

21:17 Bronsa: I wish I could make the same assumption for clojure macros

21:17 bbloom: again, i have the benefit of not having to follow the rules :-)

21:17 Bronsa: I have to do crazy things like rebuilding the entire namespace map every macroexpansion because somebody could intern vars at macroexpansion time

21:17 and midje actually does it.

21:18 bbloom: you're trying to match jvm/clj proper, i'm aiming for rough source-level compatability for idiomatic code

21:18 lol fucking midje

21:18 Bronsa: that's exactly what I thought

21:19 bbloom: interning happens via an effect in my system, so i can intercept it

21:19 i implement the dynamic nature of namespaces, but via continuations

21:19 another luxury you don't have :-)

21:19 but then again, your stuff is actually useful

21:19 so there's that :-P

21:20 Bronsa: bbloom: me and ambrose were wishing clj namespaces were IRefs a while ago

21:20 bbloom: and setting fields with (.-whatever works fine for me. so macrolet it is!

21:20 Bronsa: for watches?

21:20 Bronsa: yep

21:20 bbloom: would be nice

22:03 akurilin: Quick prismatic schema question: is there a way of enforcing values of map keys being not nil outside of using predicates? As in, say I specify {:foo [{:bar "baz}]} as schema, {:foo nil} will validate correctly for some reason

22:17 bbloom: Bronsa: amusingly, see the "Notes:" here: http://www.lispworks.com/documentation/lw61/CLHS/Body/s_symbol.htm

22:18 "The special form symbol-macrolet is the basic mechanism that is used to implement with-slots."

22:18 with-slots is basically what i want for fields

22:18 everything old is new again :-P

22:18 trptcolin: the HyperSpec - that’s pretty intense

22:19 bbloom: if you're going to implement something, you gotta do your homework :-)

22:20 trptcolin: :) that’s why i went straight to ztellman’s github when i decided to write a little code-walking macro for this book

22:21 not that this little faux-library is a comparable effort to what you’re undertaking ;)

22:25 Jaood: trptcolin: are you writing a book about clojure?

22:25 trptcolin: Jaood: yeah, macros specifically

22:26 Jaood: oh nice

23:33 mlakewood: Hi all. I just stumbled across component https://github.com/stuartsierra/component

23:33 it feels like this might have some overlap with Protocols etc. could somebody explain the differences?

23:44 trptcolin: mlakewood: component is built on top of a protocol: https://github.com/stuartsierra/component/blob/030fe57eeb2f1ac0d0675d420db9614b78ecc857/src/com/stuartsierra/component.clj#L4-L12

23:44 mlakewood: Oh ok. thats good to know. Thanks!

23:47 Frozenlock: Oh Gooood. Less than one week away from the Canada's Anti-Spam Legislation.

23:48 Why can't these lawmakers STOP making new laws? They just screw up anyway.

23:57 boltR: is there a way to throw an exception using fnil?

23:57 (fnil inc (throw (Exception. "foo")))

23:58 or can I only use an if-else for throwing exceptions

23:59 dbasch: boltR: you can throw exceptions anywhere, but I fail to grasp why you would want to use fnil for that

Logging service provided by n01se.net