#clojure log - Apr 25 2014

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

0:03 ddellacosta: kwertii: protocols explicitly do not provide implementation inheritance--this avoids a lot of the problems multi-inheritance in OO brings with it.

0:03 kwertii: If you want to use the same implementation w/protocols, define a set of functions in a hash-map and use extend-type

0:05 guns: kwertii: Multiple record types doesn't sound that bad on second thought; it's the same as your multiple subclasses implementing one interface.

0:06 using hash-maps with extend-type like ddellacosta suggests also relieves having to write a bunch of macros

0:06 ddellacosta: kwertii: or extends rather

0:06 whoops, got booted, maybe missed some messages

0:06 guns: ddellacosta: nothing from kwertii yet

0:07 ddellacosta: (extends -> extend)

0:13 kwertii: functions in a hash map + extend-type.. I like it!

0:13 Could use a little syntactic sugar, but that's easy enough to make

0:16 danlamanna: is there a naming convention for sort of internal functions? i.e. in emacs it tends to be foo--bar instead of foo-bar

0:16 ddellacosta: danlamanna: maybe -foo-bar? Depending on what you're doing

0:17 danlamanna: see that in protocol defs mostly I guess

0:17 guns: that's also the default gen-class prefix

0:18 technomancy: danlamanna: I like to attach ^:internal metadata

0:22 arrdem: ddellacosta: I've gotten crap before on PRs for using defn- and -\w+

0:23 ddellacosta: arrdem: ah okay, good to know...what were the complaints though?

0:23 arrdem: it's not like the clojure compiler _really_ lets you hide anyway..

0:23 ddellacosta: there was some other legitimate stuff.. lemme go find it

0:24 guns: Everything on the JVM can be .setAccessible. It's just metadata

0:24 arrdem: ddellacosta: https://github.com/aysylu/loom/pull/8/files#r7550133

0:25 ddellacosta: the other complaints are legitimate and fixed, but the fixes broke the PR and I haven't had time to rework it.

0:25 ddellacosta: arrdem: that just seems to be..."I don't like functions starting with -" I gotta say. Don't see much rhyme or reason to that complaint, unless the reason is that that is for protocol specifications only (convention-wise)

0:26 arrdem: ddellacosta: I would agree with that assessment. I've seen -\w+ used in core.typed and several other libraries to denote implementation methods, often together with ^:private, but it's not like anything's really private if you don't want it to be so...

0:26 (dec so)

0:26 lazybot: ⇒ -9

0:27 arrdem: ddellacosta: I know that tools.analyzer also uses the -\w+ convention for implementation detail multimethods with a bootstrap method matching the name body.

0:28 but that's just like my opinion man...

0:28 ddellacosta: arrdem: yeah. I would like to see some kind of authoritative list of those kind of conventions now that we're talking about it. Maybe there is one and I don't know about it, but most of what I know I've picked up from reading others' code, and I can imagine that would be inconsistent based on whose code one is reading.

0:28 arrdem: $google clojure style guide

0:28 lazybot: [bbatsov/clojure-style-guide · GitHub] https://github.com/bbatsov/clojure-style-guide

0:28 ddellacosta: arrdem: that doesn't have all of this stuff, does it?

0:28 arrdem: ddellacosta: so there's that... but it's not really maintained and it's totally unenforced. and yeah I don't even know if it covers this.

0:29 ddellacosta: (it is a solid guide though, agreed)

0:29 arrdem: I think it's a good one for basic formatting, based on my recollection of the last time I read it

0:29 arrdem: I just scanned it and yeah it's more of a formatting/whitespace guide.

0:30 there's some other more general advice...

0:30 ddellacosta: arrdem: yeah, I don't see anything like this; the closest it comes to is talking about earmuffs for dynamic stuff, and denoting private functions

0:30 arrdem: ,(doc io!)

0:30 clojurebot: "([& body]); If an io! block occurs in a transaction, throws an IllegalStateException, else runs body in an implicit do. If the first expression in body is a literal string, will use that as the exception message."

0:30 arrdem: what the hell... that's a thing!

0:30 TIL...

0:30 guns: what's wrong with using ^:private to signal "this is an implementation function"?

0:31 ddellacosta: guns: yeah, I definitely do that

0:31 guns: the main problem is that that is really (mostly) just informational

0:31 arrdem: nothing. just style. I don't do that because it's meaningless at runtime... but I do kinda like the -\w+ style.

0:31 I for one vote that we write a clj-epic-refactor project to autoreformat and autorename every project and symbol on GitHub...

0:31 guns: ddellacosta: that's not a problem; JVM private fields aren't private either

0:32 arrdem: PRs for everyone!

0:32 ddellacosta: it's kind of long for a convention, if you want to treat it like that, and otherwise it's kinda meaningless

0:32 I suppose

0:32 arrdem: that sounds terrifying...haha

0:32 arrdem: ddellacosta: the style guide does argue... that defn- is better than defn ^:private...

0:33 s/ue.../ue/g

0:33 guns: arrdem: ^:private isn't meaningless; it doesn't show up in (ns-publics) for one

0:33 arrdem: guns: fine, but I can still #' my way to whatever I want and routinely do..

0:33 guns: You can #'reference it at your risk

0:34 exactly. everyone's happy AFAICT

0:34 ddellacosta: gotta go, cheers folks

0:35 guns: plus, doesn't leading dash conflict with the -field notation in CLJS?

0:36 kelseygi: is there a way to sort of "reverse" functions?

0:36 like i'm calling .contains

0:36 and i want to have the first argument second & vice versa

0:36 i know there's ->

0:37 but i'm passing it to another funciton

0:39 guns: kelseygi: do you mean reverse the arguments to a function?

0:39 kelseygi: i do

0:40 guns: you could (fn [& args] (apply f (reverse args)))

0:43 programmer10101: is anyone there?

0:44 guns: everyone, shhh..... programmer10101 is here

0:44 arrdem: only bots here move along

0:44 programmer10101: you guys know of any good channels for java programming?

0:45 arrdem: Java sucks. Clojure sucks. you should go hang out in #haskell and learn a real programming language

0:45 * arrdem ducks for cover

0:45 guns: #jsoftware

0:46 try that channel

0:46 jack_rabbit: arrdem, here, here.

0:46 programmer10101: is haskell new?

0:46 arrdem: just came out last week!

0:46 programmer10101: no need for sarcasm

0:47 arrdem: touchy touchy...

0:47 http://www.arrdem.com/i/oppinion.gif

0:48 jack_rabbit: It's been around since the 80's

0:48 guns: programmer10101: I was just kidding about #jsoftware. J is an APL descedent

0:48 jack_rabbit: programmer10101^

0:48 guns: descendant

0:49 programmer10101: how do you enter another chatroom?

0:49 arrdem: ls

0:49 lazybot: bin boot dev etc lib lost+found media opt proc sbin selinux srv usr var

0:49 guns: programmer10101: /join #java

0:49 arrdem: tests passing and we've got a troll to play with! http://www.arrdem.com/i/dance.gif

0:49 guns: I think that's what you're really looking for

0:50 programmer10101: thank you guns

0:50 guns: programmer10101: also /list -re regex for searching channels

1:04 ppold: Hi, in the Python world for running backends it is common to have a process manager like Circus or Supervisor, what is the analog of those services in Clojure?

1:07 guns: ppold: Are those just process watchers like monit?

1:07 Jaood: ppold: I guess you could keep using those if you are talking about OS processes

1:09 jgmize: ppold: you might check out https://github.com/puppetlabs/trapperkeeper

1:10 ppold: Thanks guys, yes I think monit also does those tasks, like relaunching the process if it dies, etc.

1:12 guns: ppold: systemd will also do it if you're using a Linux distribution

1:14 ppold: Is it safe to use systemd in Ubuntu 14.04?'

1:16 guns: ppold: You should ask in the ubuntu channel; Canonical made their own init system, so it was never officially supported (though it will be )

1:17 ppold: Yep, last I know is that they are considering moving to systemd in version 14.10

1:18 guns: ppold: You should check out #coreos if you're interested in just systemd + your app

1:18 But anyway, monit and friends work just fine

1:21 ppold: I am using DigitalOcean though, I think it is possible to try CoreOS in Linode

1:32 egghead: is it safe to say that defmethod is a side effect?

1:32 arrdem: ooh yeah

1:34 egghead: i was just kind of confused when a defmethod wasn't listed in ns-publics

1:34 but I guess if its just modifying the defmulti fn

1:34 arrdem: yep. it's just adding another dispatch fn to the defmulti

3:45 Frozenlo`: Is gzip included/active by default in compojure nowadays?

3:45 I remember having to add a middleware for it a couple years ago.

3:45 ordnungswidrig: Frozenlock: i would off-load this to ngnix/apache

3:46 Frozenlock: ordnungswidrig: Ah! I didn't even think about that

3:46 thanks

3:46 ordnungswidrig: you're welcome

4:06 Glenjamin: Hi guys, is there a lazy equivalent of (into) - or is it lazy but i'm doing something wrong?

4:07 ,(take 10 (into [] (repeat 10)))

4:07 clojurebot: Execution Timed Out

4:08 ordnungswidrig: ,(take 10 (into '() (repeat 10)))

4:08 clojurebot: #<OutOfMemoryError java.lang.OutOfMemoryError: Java heap space>

4:13 guns: Glenjamin: concat; into is eager

4:14 into is also very fast for collections implementing IEditableCollection

4:15 henrikhodne: Hi! I'm writing a library that involves talking to an HTTP API, and the HTTP requests can sometimes "fail" (as in return 500 errors). What is the idiomatic Clojure way to handle such errors in a way that they are able to be logged by either the library or the library consumer (ie. I can't just return 'nil' or something like that)?

4:15 ordnungswidrig: henrikhodne: exceptions are not bad.

4:16 Glenjamin: possibly via (ex-info)

4:16 guns: ok - thanks

4:16 ssideris: henrikhodne: ex-info will allow you to attach clojure data to your exception to make it more useful

4:18 henrikhodne: Ah, thanks.

4:25 frankie_: Hey guys

4:25 I stumbled on a behavior that I can't fully understand

4:25 Wonder if anyone can give me some pointers

4:26 (apply str "a" ["b" "c"])

4:26 Gives "abc"

4:26 If I do

4:26 (def s [["b" "c"] ["a" "c"] ["a" "b"]])

4:26 (map #(apply str % s) "abc")

4:27 I would expect "abc" "bac" "cab"

4:27 instead I get ("a[\"b\" \"c\"][\"a\" \"c\"][\"a\" \"b\"]" "b[\"b\" \"c\"][\"a\" \"c\"][\"a\" \"b\"]" "c[\"b\" \"c\"][\"a\" \"c\"][\"a\" \"b\"]")

4:27 Glenjamin: frankie_: sounds like you want zip

4:27 ordnungswidrig: strings are sequences

4:28 ,(apply str "abc")

4:28 clojurebot: "abc"

4:28 Glenjamin: wait, no - zip in clojure is just mutli-arity map

4:28 ,(map #(apply str %1 %2) "abc" [["b" "c"] ["a" "c"] ["a" "b"]])

4:28 clojurebot: ("abc" "bac" "cab")

4:29 frankie_: Oh I see

4:29 That's quite cool :)

4:30 Thanks Glenjamin

4:30 Glenjamin: no probs

4:31 The reason I wanted a lazy (into) is for creating a large hash-map - is this possible (or even something that makes sense?)

4:32 hrm, no

4:32 it doesn't make sense

4:47 clgv: Glenjamin: there are no lazy hashmaps in clojure.core

4:47 Glenjamin: i realised that if it's actually lazy you couldn't do the O(1) lookup without realizing it

4:47 and i didn't actually need a hashmap until later in the program flow

4:58 mr-foobar: does clojurescript have the concept of classpaths ? how does it resolve :use and :require ?

5:07 Glenjamin: is there a neater way to acheive this? it seems more convoluted than it should be: https://www.refheap.com/80240

5:09 noidi: Glenjamin, http://clojuredocs.org/clojure_core/1.2.0/clojure.core/group-by

5:10 Glenjamin: bingo

5:10 thanks!

5:10 oh wait

5:10 that gives me a vector for each key

5:11 noidi: ,(group-by :id [{:id 1 :a "a"}, {:id 2 :a "b"}, {:id 3 :a "c"}])

5:11 clojurebot: {1 [{:id 1, :a "a"}], 2 [{:id 2, :a "b"}], 3 [{:id 3, :a "c"}]}

5:12 noidi: ah, right

5:12 that's because the seq may contain several values with the same key

5:13 Glenjamin: mm

5:15 the implementation looks be reduce and transients

5:15 so i guess i could do that

5:16 Bronsa: Glenjamin: (zipmap (map :id maps) maps)

5:17 Glenjamin: at the risk of overthinking it, wouldn't that iterate twice?

5:18 clgv: Glenjamin: what exactly is your problem with group-by?

5:19 Glenjamin: clgv: it gives me a different data-structure to the one i want

5:19 i'm selecting rows from a DB then putting into a hash-map by primary key

5:19 clgv: Glenjamin: you have no duplicate value for the grouping attribute and thus want no vector?

5:19 Glenjamin: correct

5:19 Bronsa: Glenjamin: if that's a performance bottleneck to you sure, use (reduce (fn [m m1] (assoc m (:id m1) m1)) {} maps) i guess

5:20 clgv: Glenjamin: yeah just make sure it's really a bottleneck. otherwise you'll waste time ;)

5:20 Glenjamin: ~600k rows

5:20 clojurebot: Cool story bro.

5:20 Glenjamin: seems like (into {} (map #(vector (key %) %) coll)) isn't too bad after all

5:21 reduce is probably clearer

5:21 clgv: Glenjamin: well than you can use the equivalent reduce with transients...

5:21 Glenjamin: mm, going to crib the implementation from group-by and remove the vector bit

5:27 yeah, that feels neater - thanks guys https://www.refheap.com/80240

5:42 pyrtsa: Glenjamin: While zipmap technically iterates over two sequences (i.e. twice), in practice it won't evaluate either more than roughly one cache line at a time (because of laziness), so you shouldn't be worrying about that.

5:44 IMO, (zipmap (map :id maps) maps) reads much much better than keyed-by in https://www.refheap.com/80240

5:45 Glenjamin: pyrtsa: ah, i see

5:45 that makes sense

5:45 i think

5:46 pyrtsa: That said, I think keyed-by is a neat function. But you could just implement it with zipmap.

5:46 Glenjamin: right

5:47 is there a transient zipmap?

5:47 pyrtsa: Ha, was just about to point out that zipmap doesn't use transients.

5:47 Glenjamin: i shall have a play about, gives me an excuse to try out criterium

5:47 Bronsa: http://dev.clojure.org/jira/browse/CLJ-1005

5:49 pyrtsa: Glenjamin: You could write just (defn keyed-by [k xs] (into {} (for [x xs] [(k x) x])))

5:49 Or (into {} (map (juxt k identity) xs))

5:51 Glenjamin: cool, will give them a spin and see if there's much in it

6:16 oskarth: When using my own library with schema defns from another project, I get a "no such var s/defn <line-in-library-code>" error. Why is that? I don't want to (have to) use schemas in the other project.

6:21 Glenjamin: here's my results if anyone is interested https://www.refheap.com/80269

6:26 oskarth: Seems like it's because I have AOT compilation enable. Using schema.macros (sm/defn) instead of schema.core for defns seems to solve it.

6:29 clgv: oskarth: sounds like some macro expands to a symbol with a namespace alias whose namespace is not required (or equally aliased) in the usage context of the macro

6:29 oskarth: yeah

6:30 clgv: oskarth: could be an error in the macro similar to 's/mysym versus `s/mysym

6:30 oskarth: I'm not sure what the right solution is though, seems a bit fragile to have that collision

6:30 clgv: the altter is correct

6:30 oskarth: oh

6:30 you mean in the schema source?

6:31 clgv: yeah maybe, if the guilty macro is from there

6:32 oskarth: https://github.com/Prismatic/schema/blob/ea6eea2392685ec6afe58046c7691c6397858e57/src/clj/schema/macros.clj#L453-L527

6:33 clgv: oskarth: thats the macro that causes the exception?

6:33 oskarth: That's the schema macro which works though, so it's the wrong one, sec

6:33 the other one was schema.core/defn, but I can't find it in the source code

6:34 clgv: oskarth: well I guess you used regular clojure.core/defn and added type information starting with "s/"?

6:34 oskarth: clgv: in the library it's s/... and in the other project it's regular defn, yes

6:35 Bronsa: oskarth: it's imported via potemkin https://github.com/Prismatic/schema/blob/ea6eea2392685ec6afe58046c7691c6397858e57/src/cljx/schema/core.cljx#L905

6:35 it might be that potemkin doesn't work with AOT

6:35 oskarth: Bronsa: oh, there it is

6:36 clgv: potemkin? is that a tool to make codebases harder to read?

6:36 oskarth: haha

6:36 "Potemkin is a collection of facades and workarounds for things that are more difficult than they should be. All functions are within the potemkin namespace."

6:37 this feels like a rabbit hole. The workaround is pretty straightforward though, as long as the ugliness is somewhere else ;)

6:37 clgv: oskarth: from the current short experience I got some doubts about that quote ;)

6:38 Glenjamin: potemkin is the one that's designed to let you expose a friendly public namespace, but remain free to arrange vars across namespaces internally however you want iirc

6:38 clgv: ah seems that the feature expression stuff is the complicating part and not potemkin ;)

6:39 Bronsa: clgv: that's cljx

6:40 clgv: (potemkin.namespaces/import-vars potemkin.namespaces/import-vars) ;; totally meta

6:40 :D^^

6:42 from a quick scan it does not seem as if import-vars might have problems with aot

6:45 oskarth: clgv: there's this issue @schema: https://github.com/Prismatic/schema/issues/21

6:46 seems to be several in one though

6:56 akazlou: hi, from proxy documentation: ...Method fns are closures and can capture the environment in which proxy is called. Each method fn takes an additional implicit first arg, which is bound to this. ...

6:56 what does it mean "capture the environment" and how I can access this implicit argument?

6:57 nightfly: I think the "which is bound to this" literally means the name "this"

6:58 And captures the environment means that any variables that were visible within the scope where you define the proxy function will be available inside of it too.

7:01 clgv: akazlou: yeah "this" is implicitely defined in contrast to protocols/defrecord/deftypes

7:59 akazlou: ok, need to experiment with it in that case, thanks

8:08 actually the question was raised because of http://www.4clojure.com/problem/113, how anyone can determine the "scope" of the return value, either string or list from the function itself, is it possible? and if, it sounds like very bad practice to return the data base on the caller's expectation

8:08 agarman: the exclusion is a pretty good hint

8:09 you can't use proxy, but are there other functions that make a type

8:09 akazlou: :) ok, I understood it the opposite way, the must to use "proxy"

8:09 thank you for clarifying this

8:10 no spoiler on the function name, will try to find it myself

8:10 agarman: enjoy

8:48 petron: How are you peeps deploying your Clojure applications to the web?

8:49 Elastic Beanstalk recently started to support Docker, so that seems like a potential avenue.

8:50 asaleh: petron, right now I used openshift ... https://www.openshift.com/blogs/how-to-host-your-clojure-app-on-openshift

8:52 petron, but 1) I wouldn't use it for production quality stuff 2) I work at RedHat, what means, that If stuff doesn't work I get to complain to developers over a coffe :)

8:56 rebcabin: is user/clojuredocs now deprecated from lein/repl?

9:43 ,(defrecord x [y])

9:43 clojurebot: sandbox.x

9:43 rebcabin: ,(x. 42)

9:43 clojurebot: #sandbox.x{:y 42}

9:43 rebcabin: ,(->x 42)

9:43 clojurebot: #sandbox.x{:y 42}

9:43 rebcabin: What is the difference between the (x. 42) and (->x 42) for defrecord constructors?

9:45 hyPiRion: ,(doc ->x)

9:45 clojurebot: "([y]); Positional factory function for class sandbox.x."

9:47 clgv: rebcabin: "->x" is a function and can be used as such which you can't with "x.", e.g. passed to map (map ->x (range 10))

9:47 ,(map ->x (range 10))

9:47 clojurebot: (#sandbox.x{:y 0} #sandbox.x{:y 1} #sandbox.x{:y 2} #sandbox.x{:y 3} #sandbox.x{:y 4} ...)

9:47 rebcabin: ty :)

9:48 (,doc x.)

9:48 ,(doc x.)

9:48 clojurebot: It's greek to me.

9:48 rebcabin: :)

9:48 clgv: unluckily primitive type hints are not passed to the function definition...

9:48 ,(doc new)

9:48 clojurebot: Titim gan éirí ort.

9:48 clgv: $(doc new)

9:49 &(doc new)

9:49 lazybot: ⇒ "Special: new; The args, if any, are evaluated from left to right, and\n passed to the constructor of the class named by Classname. The\n constructed object is returned."

9:49 clgv: ,(read-string "(x. 1)")

9:49 clojurebot: (x. 1)

9:49 turbopape: which one is better guys : (reduce conj {} (seqing a map ) or into {} (seqing a map ) ?

9:49 clgv: ,(macroexpand '(x. 1))

9:49 clojurebot: (new x 1)

9:49 clgv: ah right ^^

9:50 wagjo: turbopape: into

9:50 clgv: turbopape: if you do not want to modify the items "into" is more concise

9:50 turbopape: ok, but I am modifying the elements. If you say better, it's only for conciseness sake ?

9:50 wagjo: into is faster, sometimes

9:51 clgv: turbopape: "into" is even more efficient in terms of runtime for datatypes supporting transients

9:51 turbopape: ok, thank yo guys !

9:54 rebcabin: ,(clojuredocs defrecord)

9:54 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: clojuredocs in this context, compiling:(NO_SOURCE_PATH:0:0)>

9:54 rebcabin: ,(doc defrecord)

9:54 clojurebot: "([name [& fields] & opts+specs]); (defrecord name [fields*] options* specs*) Currently there are no options. Each spec consists of a protocol or interface name followed by zero or more method bodies: protocol-or-interface-or-Object (methodName [args*] body)* Dynamically generates compiled bytecode for class with the given name, in a package with the same name as the current namespace, the given f...

9:59 clgv: $clojuredocs defrecord

9:59 lazybot: clojure.core/defrecord: http://clojuredocs.org/v/5457 clojure.core/*verbose-defrecords*: http://clojuredocs.org/v/5313 clojure.core/defrecord: http://clojuredocs.org/v/1647

9:59 clgv: there you go ;)

10:00 rebcabin: @clgv ty :)

10:00 clgv: there are some gems hidden in lazybot ;)

10:00 rebcabin: nod — i shall have to study it. "clojuredocs" seems gone from leiningen

10:01 myguidingstar: hi all, we use "java -Duser.language=..." to change an app's default locale. Is it possible to binding a locale to just an expression body? Something like (binding [*locale* "en_US"] (my-body))

10:02 mdrogalis: myguidingstar: You can, but dynamic bindings are to be avoided when possible.

10:03 myguidingstar: mdrogalis, I know it

10:04 can you help me with that?

10:06 mdrogalis: myguidingstar: Have you considered other options first?

10:07 myguidingstar: do you suggest any other options? I can't think of any

10:08 mdrogalis: myguidingstar: What exactly are you trying to accomplish? Why does the value need to change temporarily?

10:10 myguidingstar: mdrogalis, I want my web app to allow users to set their locale

10:10 my webapp use sevaral java libraries

10:11 and it takes too much time to config each of those libs

10:11 or even impossible for my reject-java-brain ^^

10:12 mdrogalis: myguidingstar: Can you try parameterizing your calls to those libs?

10:12 Maybe a little functional layer over them.

10:13 myguidingstar: mdrogalis, it'll be a lot of painful work, I guest

10:14 mdrogalis: myguidingstar: I've used binding a few times in my Clojure life. Never once been happy with the outcome.

10:15 myguidingstar: mdrogalis, I'll take the risk. I won't use any more dynamic bindings, I promise ;>

10:16 mdrogalis: myguidingstar: ;)

10:29 gtuckerkellogg: anyone having trouble with cider v0.6.0?

10:36 mdrogalis: ,(let [x 42] (quote ~x))

10:36 clojurebot: (clojure.core/unquote x)

10:36 mdrogalis: Trying to get that to eval to "42". Any help?

10:36 Riemann's requiring me to quote a form.

10:38 Nevermind -- got it.

10:53 szymanowski: hello, in clojurescript, is there a way to "import" all vars of a ns to another? like with (ns myns (:use other-ns)) in clojure

10:56 jonasen: szymanowski: no, I don't think there is a way to do that

10:56 szymanowski: ok thank you

11:13 stompyj: whats the next big clojure conference?

11:14 clojure “east"?

11:14 and strangeloop just opened for RFP’s right?

11:17 jonasen: stompyj: euroclojure?

11:20 stompyj: jonasen: thanks!

11:38 camdenx: #join rvm

12:32 mzarella: After putting me.raynes/fs "1.4.4" into the :dependencies in my project, how do I make sure lein actually installs the dependency?

12:32 And then How would i actually use something like the cwd function? https://raynes.github.io/fs/me.raynes.fs.html#var-*cwd*

12:32 alejandro: mzarella: most lein tasks will install it for you

12:32 e.g. lein deps or lein repl

12:34 oskarth: When using nrepl in emacs, I often find myself wanting to evaluate a sub-expression that uses a variable "out of scope" (i.e. it's in a let block above) - any tips for dealing with that instead of rewriting my whole expression?

12:34 mzarella: Is there a tutorial which explains how to use modules?

12:34 oskarth: mzarella: what do you mean by modules?

12:35 mzarella: community contributed libraries

12:35 alejandro: mzarella: it's really just namespaces that you bring in from the outside. But using them is just like using your own namespace

12:35 for a good namespace intro/refresher, i'm a fan of http://www.braveclojure.com/organization/

12:35 oskarth: usually all you have to do is to add the latest version in :dependencies at project.clj (this can be found at either clojars.org or the github page)

12:36 what alejandro said

12:36 AWizzArd: About cider-nrepl: adding this as a :plugin to my :user profile is enough, right? I won’t need to add :nrepl-middleware to my :repl-options, yes?

12:37 dbasch: oskarth: in the repl, just use def

12:38 oskarth: and *1, *2, etc

12:38 oskarth: dbasch: thats what I do now, I prefer to evaluate it in my code window though

12:39 jumping around and ctrl-c spamming different expressions

12:39 dbasch: oskarth: if you need the variable outside of a scope, then increase the scope :)

12:39 oskarth: yeah sure, I guess what I was looking for what a nnrepl shortcut to use the closest let for scope, since it's kind of a common situation

12:40 rasmusto: C-x C-e hurts my delicate fingers

12:40 * rasmusto uses cpab

12:40 oskarth: what's cpab?

12:41 rasmusto: it's 'cp' as an eval prefix in vim-fireplace, then ab for the current sexpr

12:41 'ab' is just a vim text motion

12:47 justin_smith: rasmusto: there is such a world of language outside vim! while it is true that no clojure.core defs start with ab, imagine where we would be without Math/abs, absolution, the alphabet, or Abba

12:47 rasmusto: justin_smith: fabulous!

12:49 seangrove: If a message is good enough to send once to the ml, it's good enough to send 3x

12:53 AimHere: Whatever I tell you three times is true

12:54 akiel: hi

12:54 is there a build-in function doing this: (defn to-seq [xorxs]

12:54 (if (sequential? xorxs)

12:54 xorxs

12:54 (list xorxs)))

12:55 Bronsa: akiel: there's `sequence` that calls seq? rather than sequential?

12:55 akiel: but (sequence 1) returns an error

12:56 devn: im trying to hook up pulsar to play with it in the emacs cider repl. the README says to add the PATH to my quasar.jar to my jvm-opts. I've done so: "-javaagent:/Users/devn/.m2/repository/co/paralleluniverse/quasar-core/0.5.0/quasar-core-0.5.0.jar"

12:56 When I try to create a fiber it's still complaining that there's no instrumentation though

12:56 Anyone know what might be going on?

12:57 akiel: Bronsa: sequence calls seq if the args is no seq?

12:58 justin_smith: $source sequence

12:58 lazybot: sequence is http://is.gd/5eF6sb

12:58 justin_smith: akiel: see there ^

12:58 akiel: justin_smith: thanks I was already on github

12:59 justin_smith: oh, you don't want that, based on the scroll up you want your original (but that is only a proximate fix - a problem like that looks like a rough edge in a design to me)

13:00 I can't know for sure, of course, but my hunch is if you need to force 1 to be '(1) either the producer or consumer of the data has issues

13:02 cbp: Anyway i mostly linked to that atwood post because of this https://medium.com/tech-culture-briefs/a1e93d985af0

13:02 er

13:02 wrong channel

13:02 sorry

13:06 justin_smith: cbp: good link anyway

13:07 (inc cbp)

13:07 lazybot: ⇒ 3

13:12 coventry: How hard is it to get at the raw nodes in the trees making up clojure's persistent data structures? Are they clojure structures too? Also, is there a good explanation of the clojure persistent hashmap data structure?

13:13 s/persistent data structures/persistent vectors/

13:13 jcromartie: coventry: they are not also clojure data structures...

13:13 but you can examine the Java source code

13:13 justin_smith: coventry: you could probably get at the internals via interop

13:14 jcromartie: I can't imagine you can bootstrap persistent data structures with themselves… you need some primitives in the host platform

13:14 agarman: http://hypirion.com/musings/understanding-persistent-vector-pt-1

13:14 BobSchack: http://blog.higher-order.net/2009/02/01/understanding-clojures-persistentvector-implementation

13:14 agarman: http://en.wikipedia.org/wiki/Hash_array_mapped_trie

13:14 coventry: jcromartie: Yeah, definitely they can't be clojure all the way down. :-)

13:15 justin_smith: ,(do (require '[clojure.reflect :as refl]) (refl/reflect [])) ; coventry

13:15 clojurebot: {:bases #{clojure.lang.APersistentVector clojure.lang.IObj clojure.lang.IEditableCollection}, :flags #{:public}, :members #{#clojure.reflect.Method{:name empty, :return-type clojure.lang.IPersistentCollection, :declaring-class clojure.lang.PersistentVector, :parameter-types [], :exception-types [], ...} #clojure.reflect.Method{:name iterator, :return-type java.util.Iterator, :declaring-class cloju...

13:16 justin_smith: though reading source and reasoning from that may be easier

13:16 ztellman: coventry jcromartie: simple persistent objects can model most, if not all, of clojure's persistent data structures

13:16 not the transient versions, obviously

13:17 just a bunch of final fields on an object, in Java-land

13:17 coventry: Thanks, everyone. I'm developing a serializer which uses structural sharing to compress its output. I was going to do it by just walking the input structure and looking for (identical?) components, but then I realized that would be missing a lot of opportunities.

13:18 ztellman: conventry: naive serialization and compression are a reasonable proxy for that

13:18 still pay the cost on deserialization, though

13:28 devn: bah. bah! i cannot get pulsar to work.

13:30 coventry: ztellman: Thanks. Are there any compression tools which let you give hints about where you expect the repetition to be? I'm expecting repetition periods of about 1M, which gzip is not going to catch.

13:30 jcromartie: you can set the block size

13:30 right?

13:30 BobSchack: coventry why not use fressian if you're handling clojure datastructures?

13:31 coventry: BobSchack: Does it have a representation of structural sharing?

13:34 coventry`: Maybe its STRUCT opcode can be used that way.

13:35 BobSchack: I believe it has something similar, domain aware caching. You can tell the encoder the fields to be cached (https://github.com/clojure/data.fressian/blob/45b413805f746de94803f72c3bbe78d939a72a3f/src/main/clojure/clojure/data/fressian.clj#L125)

13:35 coventry`: Thanks, BobSchack.

13:36 BobSchack: I've been writing an implementation in ClojureScript and from the delve through the source it should be able to do structural sharing

13:36 NP

13:37 coventry`: Oh, that's great, it's actually the ClojureScript side I'm most interested in. Is your implementation public?

13:37 BobSchack: https://github.com/devn/longshi

13:38 coventry`: Terrific, this looks really handy.

13:38 BobSchack: I've only gotten the basic types working so far (strings, ints, etc). I working on the readme right now

13:39 It's my first non toy clojure project so if you see improvements let me know

13:42 mdeboard: Can someone tell me what I'm doing wrong here with defprotocol/defrecord? The code & traceback are in this gist: https://gist.github.com/mattdeboard/5041ce78a99064546c83

13:43 I thought you didn't define implementations in a protocol, and can use them in a record to define how to implement

13:43 llasram: mdeboard: In-line protocol implementations are implemented via JVM interfaces, in which case all bare method names must be distinct

13:43 Records already implement various Map interfaces, one of which already defines `get`

13:43 mdeboard: Ahso

13:44 llasram: You can work around this by using `extend`(`-type`/`-protocol`) to externally extend your record type to your protocol

13:45 mdeboard: No that's fine, I tihnk I'd rather not stomp on the built in

13:45 bbloom: mdeboard: yeah, you can simply use extend-protocol instead of defining the method inline... protocols respect namespaces, unlike java method names

13:45 mdeboard: you wouldn't be stomping the builtin

13:46 mdeboard: your fn is technically named courses.models.course/get

13:46 mdeboard: YeahI noticed that when using it in the repl

13:46 it threw off a warning about stomping clojure.core/get

13:46 bbloom: mdeboard: however, i suggest that you *stop making records and protocols* for this use case

13:46 mdeboard: Mmkay

13:46 Why so

13:46 bbloom: just use a normal map

13:47 defrecord is for when you need a unique named type

13:47 unless you plan to do polymorphic dispatch by type, there's not much benefit to creating one

13:48 mdeboard: bbloom: Well, I was looking at the comparison here https://github.com/Prismatic/eng-practices/blob/master/clojure/20130926-data-representation.md

13:48 and how hash maps require up to 10x the contents of the map

13:48 I'm almost certainly thinking too OO

13:49 bbloom: mdeboard: 10X contents for a small value is meaningless unless you have a large number of those small values

13:49 mdeboard: premature optimization for sure

13:49 mdeboard: you're *definitely* thinking too OO

13:49 mdeboard: Sure, I understand that, but this isn't a greenfield project I'm working on

13:50 Instead reimplementing certain parts of a production API in Clj

13:50 bbloom: mdeboard: do you have existing java code that needs you to implement specific interfaces?

13:50 i'd suggest a simple (defn get-course [conn course-id] ...) function

13:51 mdeboard: Yeah, you're right. idk what I was thinking

13:51 always takes time to change midnset

13:51 mindset*

13:52 bbloom: absolutely, learning clojure is mostly about unlearning bad habits forced on you buy crummier languages

13:52 gvickers: Truth^

13:52 mdeboard: I've written a nontrivial amount of Clojure, but there's always long periods of Python-writing between :P

13:52 egghead: lol mdeboard

13:52 justin_smith: mdeboard: each language has its vices. OO: I know, we can fix it with more classes! LISP: I know, we can fix it with more layers of macros! etc. etc.

13:52 rasmusto: python_writing()

13:53 justin_smith: PHP: oh I know, we can fix it by randomizing our function naming conventions and argument order

13:53 bbloom: justin_smith: and in OO languages the true answer is usually less classes and in lisps the answer is virtually no macros :-P

13:53 coventry`: Last time I wrote a serious amount of python code, I did it in clojure style. It was fun, and the inefficiency didn't matter in that case.

13:53 justin_smith: bbloom: I know, I had hoped to be making that point (somewhat sarcastically)

13:54 coventry`: I plan to be doing that soon, may hit you up for pointers

13:54 ambrosebs: ,(name :abc)

13:54 clojurebot: "abc"

13:55 mdeboard: coventry`: Exactly. I write functional python

13:55 technomancy: coventry`: "how horrified can you make a python programmer" sounds like a fun game

13:55 mdrogalis: bbloom: "learning clojure is mostly about unlearning bad habits" Can I quote you? I like that.

13:56 mdeboard: learning clojure is mostly about bookmarking docs because googling problems usually only yields 3-year-old how-tos :P

13:56 coventry`: justin_smith: Have you persuaded people to let you use python instead of java? That's a small victory I imagine.

13:56 bbloom: mdrogalis: sure, but only if you keep the "forced on you by crummier languages" part ;-)

13:56 mdrogalis: bbloom: You.. You want me to get beat up on Twitter. ;[

13:57 bbloom: mdrogalis: take your beating like a man

13:57 justin_smith: coventry`: the backend is highly dictated by clients, some want java, some allow clojure (yay), some prefer python, others php (omgwtf)

13:57 * mdrogalis ducks.

13:58 llasram: mdrogalis takes his beating like a duck

13:59 mdrogalis: llasram: :)

14:18 gfredericks: I think it'd be cool to combine the strint macro to make an ex-info macro that lets you reference keys from the data map inside the msg string

14:30 mdeboard: Hm, is there any particular reason why Emacs would hang (using cider + cider-nrepl) when editing a clojure buffer? It's like it's trying to do something in the background; I mash C-g enough and it returns control to me.

14:31 gfredericks: it might be pinging the server for arglists and stuff

14:31 not sure why that would hang it

14:31 mdeboard: what server?

14:31 gfredericks: the nrepl server

14:32 is your nrepl server on a distant planet?

14:32 arrdem: gfredericks: rover on mars, why do you ask?

14:32 gfredericks: made with alien technology :D

14:32 jcromartie: arrdem: seriously?

14:32 gfredericks: arrdem: irrc mars is a laggy connection

14:32 iirc*

14:32 * jcromartie is writing Clojure at NASA, but not in space

14:32 Frozenlo`: mdeboard: I had a similar experience with Cider... I decided to go back to nrepl.el

14:33 mdeboard: Frozenlo`: Well, damn.

14:33 arrdem: jcromartie: oh for real?

14:33 technomancy: jcromartie: JPL?

14:33 Frozenlo`: Good ol' nrepl, works perfectly well :-p

14:33 arrdem: jcromartie: I've got a chance to write C++/Rust at UT's satellite lab and was kinda laughing about being able to run Clojure on a nanosat

14:33 mdeboard: https://github.com/clojure-emacs/cider-nrepl/issues/37 probably

14:33 ystael: mdeboard: Try disabling autocomplation?

14:34 *autocompletion

14:34 technomancy: I once emailed Ron Garrett to try to get his CL HTTP server working in clisp.

14:34 I don't remember if that was after he left the JPL or not

14:34 arrdem: gfredericks: if you can deal with a few minutes of lag and potentially screwing a multi million dollar rover, sure!

14:34 mdeboard: ystael: Not sure how to in cider, do you know off the top of your head?

14:34 technomancy: http://www.flownet.com/gat/jpl-lisp.html

14:34 stuartsierra: mdeboard: Maybe autocomplete

14:35 justin_smith: mdeboard: M-x (global-autocomplete-mode) will toggle it

14:35 mdeboard: I toggled auto-complete-mode, still hung

14:35 ystael: mdeboard: as I fuzzily recall, I removed the ac-nrepl and clojure-complete packages. this was a while ago though, i definitely do not have recent builds

14:36 coventry`: mdeboard: M-x toggle-debug-on-quit <RET>, then mash C-g next time it happens. Should give you a backtrace which may tell you what's causing it.

14:36 mdeboard: coventry`: nice, it did

14:37 What it means, idk https://gist.github.com/mattdeboard/89e9ed61a091b8bbddfa

14:37 coventry`: Try turning off eldoc.

14:38 mdeboard: Giving that a whirl

14:38 Seems to be aok

14:39 coventry`: No idea how to get at what's happening on the server to figure out why that's slow, though. I guess you could try running jstack while emacs is hung.

14:39 technomancy: "Also in 1993 I used MCL to help generate a code patch for the Gallileo magnetometer. The magnetometer had an RCA1802 processor, 2k each of RAM and ROM, and was programmed in Forth using a development system that ran on a long-since-decommissioned Apple II. The instrument had developed a bad memory byte right in the middle of the code. The code needed to be patched to not use this bad byte."

14:40 "The magnetometer team had originally estimated that resurrecting the development environment and generating the code patch would take so long that they were not even going to attempt it. Using Lisp I wrote from scratch a Forth development environment for the instrument (including a simulator for the hardware) and used it to generate the patch. The whole project took just under 3 months of part-time work."

14:40 dang

14:40 mdeboard: coventry`: I just added that gist to the issue on github

14:40 justin_smith: technomancy: alien tech at its best

14:41 mdeboard: wow.

14:42 arrdem: jcromartie: you can't just say that to a room full of nerds and fade into the shadows. WE DEMAND DETAILS.

14:42 technomancy: heh, "My best hope at this point is that the dotcom crash will do to Java what AI winter did to Lisp, and we may eventually emerge from "dotcom winter" into a saner world. But I wouldn't bet on it."

14:42 justin_smith: nice

14:43 coventry`: At least we got an AI spring.

14:43 Frozenlock: technomancy: we have JS now. hurray.

14:43 technomancy: Frozenlock: so what we need is a "web winter" I guess

14:44 arrdem: http://arrdem.com/i/alien.png

14:44 technomancy: or clojurescript...

14:45 Frozenlock: New top domain names ----> new world war ----> web winter

14:45 'logic' :-p

14:45 arrdem: have you seen the things you can get for a TLD these days? :P

14:45 justin_smith: technomancy: I think the problem is that the partial gains of AI never made the CEO chuckle at the antics of a fluffy animal or supplied him with pornographic material. So they never saw the baby that was being thrown out with the bath water when AI was defunded.

14:45 turbofail: didn't ron garret have some followup article about how he met people at google who kicked his ass in productivity using whatever language?

14:45 Frozenlock: arrdem: I have. I also have very mixed feelings about it.

14:45 coventry`: I was hanging out on #javascript recently. People there seemed quite certain that no one's going to be manually programming javascript for much longer.

14:46 arrdem: Frozenlock: I'll just wait for DNS to be found fatally flawed so we can get on with namecoin adoption

14:46 mdeboard: coventry`: Oh good, so we'll have machine-generated javascript built by generators built by humans who love javascript

14:46 What could possibly go wrong

14:46 abstraction porn

14:47 arrdem: (inc mdeboard) ;; why do you think I like compilers..

14:47 lazybot: ⇒ 5

14:47 llasram: You know, just like how know one writes anything in assembly, for any reason

14:47 s,know,no,

14:47 coventry`: I don't think the people who wrote clojurescript and elm are particularly in love with javascript. :-)

14:47 Frozenlock: arrdem: I'd like that. (I think)

14:48 aditya-a: technomancy: the jpl-lisp article is so cool... among my permanent lisp bookmarks :)

14:48 arrdem: Frozenlock: it's all fun and games until you have to debug the emitter..

14:49 llasram: Argh. Did that that GSoC proposal to do persistent probabilistic data structures for Clojure get accepted?

14:49 Trying to very hard to avoid shaving too many yaks right now, but these Java HyperLogLog implementations are making it hard

14:49 arrdem: llasram: not that I know of.

14:49 llasram: Bah

14:50 And humbug to boot

14:50 arrdem: llasram: Bronsa and I got in... another Sweedish guy got accepted to do a variant of my project.. there's a guy on Light Table, and there's one more I think.

14:53 llasram: arrdem: Well, congrats to you and Bronsa at least :-)

14:53 ystael: mdeboard: don't worry, idris will fix all our javascript problems :)

14:53 arrdem: llasram: is there a paper you can shoot me? I'm curious what you mean by probabalistic datastructures.

14:54 coventry`: arrdem: persistent probabilistic

14:54 data structures

14:54 Oops.

14:54 llasram: arrdem: the (rejected?) GSoC proposal has pretty much all of the links you'd want: http://www.google-melange.com/gsoc/proposal/public/google/gsoc2014/matteo_ceccarello/5778586438991872

14:55 coventry`: I meant to send that, but cutting-and-pasting is broken in this emacs.

14:55 llasram: Basic idea is you have a data structure which lets you trade something (usually space) for certainty. Bloom filters are probably the most famous

14:56 And of course all the existing Java implementations are mutable to the max, and mark their backing data as `private` so you can't sanely serialize them

14:57 coventry`: I can see why it wasn't accepted. The proposal doesn't cohere around an interesting problem.

14:57 llasram: coventry`: That's fair. I was just saw the original post and thought "man, I could really use those" :-0

14:58 Instead -- I either get mutability or yak-shaving, and ATM am sadly going for mutability

15:03 pjstadig: llasram: don't you know should should always err on the side of yak-shaving?

15:03 * pjstadig sadly revokes llasram's programmer credentials

15:07 llasram: pjstadig: What if I know / tell myself that I'm really just putting the yak-shaving off until later? Do I get them back?

15:08 In a sense I'm both yak-shaving *and* procrastinating

15:14 mdeboard: Question about clojure.java.jdb.c If I'm using insert! with multiple records, I have to use apply, e.g. `(apply sql/insert! db :table records)` ... does this mean that a query is being made per insert?

15:15 justin_smith: mdeboard: best way to answer that is check the source

15:15 mdeboard: justin_smith: Yeah I've got it open but it's kind of bonkers.

15:15 pjstadig: llasram: i've spoken to the council and you are temporarily reinstated for a probationary period. if you meet your yak shaving quota, you'll have no problem getting fully reinstated.

15:15 justin_smith: weird, my version of jdbc doesn't even seem to have insert!

15:16 mdeboard: Based on the fact there's this line, I assume it's a single query per: `(map (fn [row] (insert-single-row-sql table row entities)) rows)`

15:16 Nevermind

15:16 justin_smith: mdeboard: not neccessarily - where is the transaction bound?

15:16 or the connection even

15:17 mdeboard: I see here

15:17 justin_smith: mdeboard: another approach could be to turn on verbose logging on the sql server side

15:18 may or may not be easier

15:18 mdeboard: even better.

15:19 justin_smith: ?

15:19 harovali: hi! , I'm really impressed at clojure, I'd like to embrace it. My first newbie question; why it hasn't the + fuction to be escaped in an expression like this: (reduce + [ 1 2 3 4] ) ?

15:20 agarman: + is a symbol

15:20 so it's escaped already

15:20 when you put it at the head of a list

15:20 Anderkent: or rather, + 'the symbol' evaluates to + 'the fucction

15:20 ,+

15:20 clojurebot: #<core$_PLUS_ clojure.core$_PLUS_@1775cce>

15:20 harovali: agarman: aha!, not like in CL that you have to type #'+ IIRC ?

15:20 Anderkent: and then that function is applied in reduce

15:20 agarman: like (+ 1 2 3) it is looked up like a function

15:20 and evaled as a function

15:21 harovali: sure, but there it's clearer since it's in first form position

15:21 Anderkent: eh, i don't think that's the right explanation

15:21 llasram: harovali: Yeah, Clojure is a "Lisp-1", with only one way of resolving symbols to things

15:21 harovali: llasram: aha! like elisp , say ?

15:21 llasram: Yep, or Scheme, at least in that regard

15:21 mdeboard: justin_smith: even better wrt tailing the pg log

15:21 harovali: llasram: thanks

15:21 justin_smith: harovali: clojure is a lisp-1, which means that functions and variables are in one "namespace"

15:22 mdeboard: ahh, cool, so it was in one query?

15:22 harovali: justin_smith: thanks too

15:22 justin_smith: np

15:23 llasram: well, we have multiple ways of looking symbols up (local vs. ns bi ndings etc.) but they are the same for functions and not-functions

15:23 johnjelinek: hihi all, how's it goin'?

15:23 llasram: justin_smith: Yeah -- I just was groping around for a way to avoid saying that Clojure "only has one namespace"

15:23 Since it, you know, has an arbitrary number of first-class namespaces :-)

15:23 harovali: a rather obnoxious question, aren't people worried at tha oracle's policies regarding jvm , when embracing clojure (or when designing it in the first place, although possible it started befor oracle's buy of java IIRC)

15:24 agarman: I use clojure because I have to work on the JVM

15:24 justin_smith: llasram: in retrospect, maybe "functions and non functions are looked up in the same way" would be more clear

15:25 agarman: if I weren't restricted to the JVM, I'd consider Clojure, but along with Ocaml, F# or elixir

15:25 harovali: agarman: thanks

15:25 johnjelinek: is it better to add data to an atom like a collection of records (ie: '({:resource "data" :val 1} {:resource "data" :val 2})) or like a collection of documents (ie: '({:resource "data" :vals '[1 2]})?

15:25 justin_smith: harovali: clojure has versions (of various maturity) on various target languages / platforms. I trust that if Oracle got onerous to clojure clojure would move on.

15:25 johnjelinek: which is more idiomatic?

15:25 harovali: justin_smith: thanks

15:25 bbloom: johnjelinek: niether

15:26 johnjelinek: bbloom: what do you suggest?

15:26 bbloom: johnjelinek: also you don't need that ' on your vector, numbers are self evaluating

15:26 johnjelinek: noted

15:26 bbloom: johnjelinek: i probably should have said *either*

15:26 johnjelinek: lol

15:26 agarman: johnjelinek: depends upon your use case

15:26 bbloom: johnjelinek: represent your value how you need it

15:27 johnjelinek: if you have a map, you're using some key to look up some value. build up data that match your algorithms

15:27 harovali: I have to supose that the java standard library and the enterprise java beans, and such stuff , are really useful when one progams in clojure. Is that better thatn say the satandard library of perl or python or .. ?

15:27 johnjelinek: here's the case: I have different routes, and I want to collect http responses so I can broadcast data to them all over http chunked encoding, but I want to filter out data to broadcast based on who is listening on a route

15:28 agarman: harovali: the JVM libraries vary in usefulness...some are terrible...such as Date and text formatting...some are excellent like concurrent libs

15:28 bbloom: johnjelinek: i'm not quite sure what that means, but all you need to do is figure out what data you have, what questions you want to ask of your data set, and then encode data to best answer those questions

15:28 johnjelinek: I think maybe I'll keep things super flat, it sounds like it'd be easier to query

15:29 rather than nesting arrays

15:29 bbloom: flatter is generally easier to query and, if your data set is small, linear performance is probably just fine

15:30 harovali: agarman: aha!, I'd previously thing that precisely, the Date library was excellent

15:30 s/thing/think/

15:30 bbloom: you can always add extra indexes and such later, since you've got immutable data it's easy to create consistent alternate views of data either incrementally or in a batch. start w/ the simplest information model & optimize later

15:30 johnjelinek: thanks :)

15:30 bbloom: good thought :)

15:30 agarman: harovali: like with Ruby, Python etc. learning the stdlib and it's gotchas is a rather large part of learning the language. The functions provided by Clojure are almost universally excellent. When I need to use Java libs, they're there, but it's often depressing.

15:30 johnjelinek: lol, filter and remove always get me confused on the predicate

15:31 bbloom: johnjelinek: me too.

15:31 filter-out vs filter-for

15:31 argh.

15:31 johnjelinek: right

15:31 justin_smith: looking at the real world, a filter catches things, but the mental model of whether you are interested in the things that pass through the filter or the things filtered out can be confusing

15:32 so perhaps a filter should have two outputs :)

15:32 bbloom: justin_smith: i like the name "where"

15:32 justin_smith: really clojure's filter may be clearer as "net" or "trap"

15:33 agarman: harovali: Java's date lib was so pathologically bad that no one used it for years. Everyone used Joda. And now JSR 310 is a brand new implementation of same functionality for Java 8 and beyond.

15:33 justin_smith: bbloom: where sounds like a logical condition though (a where f(a) < x)

15:34 stuartsierra: (for [x (range 10) :when (even? x)] x)

15:35 bbloom: ,(for [x (range 10) :when (even? x)] x)

15:35 clojurebot: (0 2 4 6 8)

15:35 bbloom: stuartsierra: what are bots for if we don't make them do any work?

15:36 stuartsierra: bbloom: I always forget to include the bot syntax.

15:36 bbloom: stuartsierra: in the spirit of making the bots do extra work, they should speculatively evaluate anything that resembles code you may want to evaluate in irc

15:36 dbasch: why is that more useful than

15:36 ,(range 0 10 2)

15:36 clojurebot: (0 2 4 6 8)

15:36 justin_smith: bbloom: though I guess that logical condition is exactly what filter is doing, so...

15:37 bbloom: dbasch: b/c (for [x some-result-from-earlier :when (even? x)] x)

15:37 stuartsierra: dbasch: It's not. Just an example of `for :when` syntax.

15:37 dbasch: stuartsierra: gotcha :)

15:38 turbofail: hm. filter always seemed intuitive to me, perhaps because i'm used to thinking of filters by what they pass

15:39 coventry: Yeah, filter is great, but for / :when is very useful when you want to iterate over and filter a cartesian product.

15:40 justin_smith: turbofail: well, in natural language it is ambiguous - "high frequency filter" "water filter" "carbon monoxide filter" - totally inconsistent

15:41 szymanowski: hello, when I try (declare foo) at the clojurescript repl it throws an error is it normal?

15:41 dbasch: there used to be a separate function in clojure contrib, don’t know if it’s still around

15:41 but it was like (juxt filter remove)

15:42 justin_smith: ,(group-by even? (range 4)) ; dbasch

15:42 clojurebot: {true [0 2], false [1 3]}

15:42 justin_smith: that's all that's needed for that

15:43 dbasch: ,((juxt filter remove) even? (range 4))

15:43 clojurebot: [(0 2) (1 3)]

15:43 rhg135: ,(doc group-by)

15:43 clojurebot: "([f coll]); Returns a map of the elements of coll keyed by the result of f on each element. The value at each key will be a vector of the corresponding elements, in the order they appeared in coll."

15:43 rhg135: hmm

15:44 dbasch: justin_smith: depends on what you want

15:47 justin_smith: group-by is not lazy, for one

15:47 justin_smith: fair point, yeah

15:59 amalloy: (juxt filter remove) is only half-lazy, really

15:59 justin_smith: half-lazy?

16:00 amalloy: try: (let [[evens odds] ((juxt filter remove) even? (range 1e8))] (list (last odds) (first evens)))

16:00 it has to walk over the list twice, so it has to hold onto the head of the list for the second traversal

16:07 teslanick: Is this a totally nutty idea? https://gist.github.com/nhusher/11301237

16:08 Putting data to the redis-ch posts it to a redis pubsub, taking from awaits data on the pubsub.

16:15 alejandr_: teslanick: that's a cool idea. Can you explain how the readPort portion works?

16:16 teslanick: core.async channels are just a small box of protocols. I'm implementing the same protocols with different behavior.

16:16 I borrowed the idea from https://github.com/james-henderson/chord

16:18 But it's just calling the protocol function against the read-ch. So when you do (<! redis-ch) you're actually doing (<! read-ch), which is a channel fed by the redis-listener.

16:19 alejandr_: Ah got it, had missed that the redis subscriber was filling a separate channel

16:19 thanks

16:19 teslanick: It's the only way I could think of to stitch together the (weird) way that carmine handles pubsub and a core.async channel

16:20 justin_smith: arrdem: regarding out convo the other day about using log on units, one way to clarify it may be to say that currently your usage of numbers for the units is an implicit multiplying factor, and you need some other datum to represent curvature, which is something not represented currently (you are using math such that all is implicitly linear, log is not linear)

16:21 *our convo...

16:30 sveri: Hi, I am still on my way through om, right now I am trying om-sync. I am running this function: (om/transact! data edit-key (fn [_] (.-date e)) :update) where data is a map like this: {:id 2394 :foo "foo" :bar "bar"}, edit-key is :bar and the fn just returns sime text for :bar. It works at altering the state and om-sync also calls the server side. However, it only provides the edit-key :bar map like this: {:bar "new_val"} instead of the whol

16:32 justin_smith: e..

16:38 AWizzArd: About cider-nrepl: adding this as a :plugin to my :user profile is enough, right? I won’t need to add :nrepl-middleware to my :repl-options, yes?

16:53 ticking: has anyone found a local maxima for a simple clojure editor yet?

16:54 mikerod: ticking: does that mean emacs?

16:54 ticking: mikerod: simple ;p

16:55 justinho1: vim?

16:55 clojurebot: Gesundheit!

16:55 mikerod: ticking: (not= simple easy)

16:55 :P

16:55 amalloy: well, emacs is neither, mikerod

16:55 ticking: mikerod: emacs is neither

16:55 amalloy: i mean, i love emacs

16:55 mikerod: amalloy: I was waiting on a response like that :P

16:55 fair enough, but yes I do love emacs

16:56 justinholguin: Seriously though, LightTable is probably it

16:56 ticking: justinholguin: nope, LT is probably easy but BOT is the opposite of simple, even the emacs internals are cleaner compared to that hairball ^^

16:56 hrathod: ticking: Nightcode, perhaps?

16:57 justinholguin: BOT?

16:57 ticking: justinholguin: the object model LT

16:57 LT employs, Behaviours Objects Tags

16:58 justinholguin: Ok, thanks.

16:59 I started with LT and it served me well while I was still experimenting with basics, but I use vim now and I can't really go back.

16:59 ticking: hrathod: good idea but seems very IDE focused

16:59 mikerod: when going for simple

16:59 in an editor

16:59 that is tricky I suppose

16:59 ticking: yeah, I was thinking about Sublime :/

17:00 Github atom looks promising but feels alpha

17:00 mikerod: Eclipse + counter clockwise :)

17:00 ticking: justinholguin: yeah, LT is awesome on paper but flawed in reality

17:00 mikerod: oh you ;)

17:03 hrathod: What is the definition of "simple" in this case? Just syntax highlighting? ability to connect to nrepl?

17:04 mikerod: is a "notepad" style editor simple?

17:04 ticking: mikerod: yeah

17:05 mikerod: then notepad

17:05 ticking: hrathod: connect to nrepl should be the most advanced feature

17:06 mikerod: I'm on a mac, also notepad might be a bit tooo simple

17:06 but I'd lean more forward to something like it than say lighttable

17:07 mikerod: I know people coming from Java-land tend to use Counterclockwise since they are already using Eclipse

17:07 hrathod: ticking: I don't know what the status of Clooj is, but I believe it was fairly simple

17:07 ticking: hrathod: yeah commited a fix to it once, but it is also very IDE like

17:08 I'll just conclude that no local maxima has been found yet ^^

17:09 justinholguin: Where's the appeal in an editor that's basically notepad with nREPL support? I don't think I get it.

17:09 ticking: justinholguin: simple things have less points of failure

17:09 egghead: LOCAL MAXIMA

17:09 llasram: Also, where's the appeal of an editor that isn't Emacs? I don't get it :-)

17:10 ticking: llasram: same answer ;) less points of failure

17:10 egghead: light table?

17:10 emacs?

17:10 clojurebot: emacs is a nice operating system if it only had a decent editor

17:10 technomancy: I point people to inferior-lisp if they're having a hard time getting nrepl working

17:10 justin_smith: justinholguin: I have a hack to add atom:link to clj-rss, which is something that validators seem to think should be there

17:10 technomancy: it's good to have a fallback

17:10 justin_smith: justinholguin: with a bit of work it could maybe be made a feature of clj-rss even

17:11 justinholguin: justin_smith: did you read my mind or my GitHub profile?

17:11 justin_smith: justinholguin: I was looking at the clj-rss code on gh and saw you were the last to commit

17:11 figured the nick carried over

17:12 though I guess I could actually make what I have into a proper PR

17:12 justinholguin: Yeah, so I figured

17:12 Cool, that library needs work.

17:12 I saw an open issue for that

17:12 But that's not really something I care about

17:12 justin_smith: justinholguin: https://www.refheap.com/80485

17:13 of course you probably don't want "localhost:33333" in the real outptut :)

17:13 and I don't know what kind of mess my brain was making of reality when I typed "clojure.edn" in the comment, hah

17:14 justinholguin: justin_smith: yes, that is a safe assumption. I would definitely recommend sending yogthos a PR

17:14 justin_smith: cool, will clean it up

17:14 justinholguin: I'm working on some unrelated issues I've been having with clj-rss, which incidentally appears to be the only library out there for generating RSS feeds with Clojure.

17:15 justin_smith: I figured that out :)

17:15 justinholguin: I keep forgetting that RSS is "dying" because I've used it every day for like 12 years

17:15 justin_smith: (also I found out the clojure web framework I help maintain totally fails to allow rss content type of non-static data at the moment :()

17:16 justinholguin: Which framework is that?

17:16 justin_smith: caribou

17:16 and yes I know frameworks are terrible, it's my job though :)

17:16 ticking: justinholguin: a edn based replacement would be nice though ^^

17:16 akurilin: Quick question, what do you guys use for storing slightly more involved external configuration than what can be handled with just env vars? e.g. I want to be able to read in a list of strings in my ring app at boot, should I use some sort of yaml/edn/json thingy?

17:16 gworley3: here's a simple enough question I could use some advice on: what's the best way to store a shared connection in a ring app? a ref? atom?

17:16 justinholguin: I use yaml, but I'm kind of a heretic.

17:17 justin_smith: akurilin: I use a set of edn files, and a boot time var to decide which one is loaded

17:17 bbloom: yaml is the worst thing ever.

17:18 akurilin: justin_smith: edn comes for free with 1.6, right?

17:18 justin_smith: gworley3: will the shared connection need a coordinated change alongside some other shared mutable value?

17:18 justinholguin: YAML is terrible, but it's easy to read and edit by hand. For me, that makes it a decent way to handle config files

17:18 justin_smith: akurilin: well even before that, given that all you need to do is call read on the bufferedstream (it's just safer in 1.6)

17:19 gworley3: justin_smith: nope. just need to come into existence once per jetty process and then be shared by all the threads (may eventually expand to pooling, but shouldn't be necessary since in this particular case i'm using rabbitmq)

17:19 justin_smith: akurilin: edn is just a json-like subset of clojure data literals

17:19 akurilin: justin_smith: yeah I guess since technically this isn't an unsafe file, I can just eval it?

17:19 justin_smith: gworley3: if it never changes, consider using delay or even a declare and a later def

17:19 gworley3: akurilin: edn is great

17:19 akurilin: bbloom: I hate anything that uses whitespace for formatting

17:19 justin_smith: akurilin: well read is fine, no need for eval even

17:20 bbloom: akurilin: whitespace is the least of yaml's problems

17:20 irb(main):004:0> YAML.load("foo: 1\nyes: two\n3: :four\n'5': null")

17:20 => {"foo"=>1, true=>"two", 3=>:four, "5"=>nil}

17:20 justin_smith: akurilin: 1.6 just adds some extra reading safety, but it's your file so no need to be too worried

17:21 akurilin: justin_smith: fair enough, I'll play around with read then

17:21 bbloom: although this highlights one of my complaints about clojure's syntax too... true/false/nil *look* like symbols but aren't

17:21 justin_smith: akurilin: (-> "caribou/plugin/rss/dummy-input.edn" io/resource io/reader PushbackReader. edn/read))

17:21 akurilin: that is from the same project I was just quoting to justinholguin

17:21 akurilin: ah neat

17:21 gworley3: justin_smith: ah, delay looks like just the thing. thanks!

17:21 akurilin: thx

17:21 lemonodor: i like the google approach to app configuration: everything is a command line flag. if you want, you store them in a file and read them from there. everything that can be configured can be set in a file, or from the command line.

17:21 justin_smith: gworley3: np

17:22 lemonodor: it’s consistent between languages, and it’s consistent between deploying to 10K machines or running on your desktop

17:22 justin_smith: lemonodor: yes, it would be nice to have a lib that made that work with clojure (maybe it exists and I don't know it)

17:23 lemonodor: justin_smith: https://github.com/wiseman/clj-gflags (i’m new to clojure, it’s not done, etc.)

17:23 gworley3: on a related question, once i have this shared connection, rabbitmq has a concept of channels (it takes care of multiplexing requests across a single tcp connection using them) that i should create once per thread

17:23 justin_smith: lemonodor: cool!

17:24 gworley3: weird. I wonder if piggybacking on :dynamic vars (which by clojure definition have different bindings per thread) would be a win or lose there

17:24 gworley3: right now i have this set using (def ^:dynamic channel) that i later bring into existence when i need it, but is this actually thread local in this case? I'm using ring and compojure and it's not 100% clear to me when the threads get created

17:24 justin_smith: maybe someone with deeper expertise than me can weigh in on that

17:24 amalloy maybe

17:25 justinholguin: gworley3: just a note, dynamic vars should have earmuffs (*channel*). Their ears get cold.

17:25 justin_smith: gworley3: I think :dynamic means it can be different per thread, but in no way tells you it will be

17:25 gworley3: justinholguin: oh, they do; i just forgot them here

17:26 justin_smith: gworley3: mainly what I know about :dynamic is that it correlates highly with bugs in my code. That could be my fault, could be the feature's fault, I will need more learning before I know which.

17:28 gworley3: justin_smith: from the docs it mentions needing to use binding to set a thread local value, but in the case of using compojure it's not clear to me where i would need to stick this in

17:28 justin_smith: akurilin: that PushbackReader is java.io.PushbackReader btw (oddly, not covered by clojure.java.io)

17:28 gworley3: I don't think compojure has anything to do with that, or even ring, it has to do with the way the individual ring backend uses threads

17:29 gworley3: we had bugs with dynamic vars get exposed when trying to get http-kit compatibility

17:29 because http-kit does not use threads the same way jetty does

17:29 gworley3: hmm

17:30 justin_smith: at this point I consider "breaking bad code which misuses :dynamic" as a positive feature of http-kit

17:30 gworley3: justin_smith: yeah, i'm trying to make sure these vars end up doing what i want in a multithreaded environment using jetty, but right now it's a little fuzzy to me

17:30 akurilin: justin_smith: any particular reason for that specific class?

17:31 justin_smith: akurilin: edn/read needs it (as does the normal read iirc)

17:31 akurilin: a regular Reader does not suffice

17:31 amalloy: there are many ways to get a different value for a var per thread, but like justin_smith says, is that really what you want? if you do part of a job on one thread and want to spin some of the gruntwork for that job off to another thread, you may want them to share the resource, for example

17:33 if you really truly want a fresh instance of something per thread, useful has a good tool for that: https://github.com/flatland/useful/blob/develop/src/flatland/useful/utils.clj#L201 lets you write (def channel (thread-local (make-a-channel)))

17:33 justin_smith: akurilin: you can more concisely do (edn/read-string (slurp (io/resource "file/path.edn"))) and punt on efficiency

17:34 amalloy: then each thread evaluates (make-a-channel) at most once, and @channel gets you the channel for that thread

17:34 gworley3: amalloy: i came across thread-local but was trying to see if i could do it with clojure primitives before i dug into that

17:35 amalloy: i actually just found this while i've been on here and it suggests a way of using bound-fn: http://blog.steveolsen.us/dynamic-vars-in-ring-handlers/

17:47 bbloom: what causes files to get copied to target/classes ?

17:49 amalloy: bbloom: that's where lein puts them when you do aot, no?

17:49 bbloom: amalloy: i haven't done any aot compilation & these aren't .clj files

17:49 dbasch: bbloom: compilation

17:49 amalloy: bbloom: then i'd say it's some bad lein plugin?

17:49 but it'd be .class files, not .clj files

17:50 (if you were doing aot)

17:50 bbloom: they are files be loaded as resources out of src

18:02 technomancy: bbloom: maybe cljx or something

18:03 bbloom: technomancy: i'm not using any plugins for this project

18:03 technomancy: mysterious

18:03 bbloom: indeed

18:05 Bronsa: bbloom: using swank and compiling a file puts the .clj files in target/classes

18:05 bbloom: Bronsa: i use vim

18:05 Bronsa: maybe something similar happens with the vim plugin?

18:05 bbloom: i don't think so

18:05 Bronsa: bbloom: rm -rf target, connect via vim and compile the file & see if it gets populated

18:12 AWizzArd: About cider-nrepl: adding this as a :plugin to my :user profile is enough, right? I won’t need to add :nrepl-middleware to my :repl-options, yes?

18:13 gtrak: AWizzArd: correct

18:14 that's basically the point of the plugin

18:14 AWizzArd: gtrak: k, thx

18:14 gtrak: btw, does this plugin have anything to do with piggieback or cljs repls?

18:14 gtrak: yes

18:14 rather, not the plugin bit

18:14 but the middlewares do

18:15 should *just work* when piggieback is active.

18:21 akurilin: justin_smith: good to know, thank you sir.

18:22 On an unrelated note, what's a simple way of breaking lein ring unberjar?

18:22 I need to make sure the script is handling the failure correctly

18:23 justin_smith: akurilin: having an invalid :handler in your project.clj :ring config?

18:23 or an invalid ring option maybe?

18:23 akurilin: hm let me try that in a bit, good call

18:23 justin_smith: depends where you want it to break I guess

18:25 amalloy: set your computer on fire

18:25 that should break lein ring uberjar

18:25 justin_smith: lol

18:44 l1x: hi, has anybody seen this problem? https://gist.github.com/l1x/11305543

18:45 justin_smith: l1x: try (io/write (io/file file)), or just (io/writer file)

18:45 *io/writer of course

18:45 l1x: same results

18:46 justin_smith: what is "file" in that context

18:46 the name of a file?

18:46 an io/file?

18:46 and why are you calling str on it?

18:48 l1x: file is (io/file "string" "anotherstring")

18:48 i have tried both using it as it is and calling str on it

18:48 both fails

18:48 justin_smith: then yeah, calling string on the file is the wrong thing

18:50 l1x: fyi it works

18:50 justin_smith: which works?

18:50 l1x: both, using it as it is or calling str on it, both is supported for io/write

18:51 penthief: llx: data needs to be a String for the write method to be found.

18:51 l1x: and it works in repl, but not when i am calling it in the real code

18:51 justin_smith: calling str on the file object?

18:51 l1x: yes

18:51 penthief: thanks, that might be it

18:51 justin_smith: that's weird

18:52 yeah, I guess io/writer coerces strings to files

18:52 l1x: but you are right, it should be a File object it is better that way

18:53 amalloy: calling (str) on a file object gets you useless garbage

18:53 ,(str (java.io.File. "/tmp/foo"))

18:53 clojurebot: "/tmp/foo"

18:53 amalloy: huh. it doesn't? i didn't know that

18:53 justin_smith: amalloy: surprised me too :)

18:54 amalloy: i'm so used to its pr-str, i guess

18:54 cbp: :-P

18:54 l1x: and the winner is penthief

18:54 thanks bro, (str data) fixed the problem

18:54 it was a hashmap and i thought it is just a string

18:54 justin_smith: also, there is spit

18:54 l1x: now it works

18:55 amalloy: what are you talking about? calling str on a File returns you the operating system specific string that is your path to the file

18:55 eg on windows it is going to be \ on unix it is /

19:14 hyPiRion: ,(str (java.io.File. "I'm not so sure\\"))

19:14 clojurebot: "I'm not so sure\\"

19:15 hyPiRion: Granted, a *real* file will give you a valid file name

19:15 TravisD: Is there a function that returns the first element of a seq satisfying some predicate? Something like (defn first-satisfying [p xs] (first (filter p xs)))

19:16 hyPiRion: TravisD: no, that's your best bet. Can define it as (def ffilter (comp first filter)) though

19:16 TravisD: ah, I like the name and definition :)

19:17 justin_smith: bonus points if you use metadata so ffilter has a doc string :)

19:17 justinholguin: ,(doc some)

19:17 clojurebot: "([pred coll]); Returns the first logical true value of (pred x) for any x in coll, else nil. One common idiom is to use a set as pred, for example this will return :fred if :fred is in the sequence, otherwise nil: (some #{:fred} coll)"

19:17 justinholguin: TravisD: ^^^

19:17 justin_smith: (some even? (range)) justinholguin: not quite

19:17 ,(some even? (range)) justinholguin: not quite

19:17 clojurebot: true

19:18 justin_smith: (oops)

19:18 TravisD: :(

19:18 justinholguin: Ah, I see

19:19 justin_smith: of course (some (apply set (all-even-numbers)) (range)) would work, but that set is expensive to construct :)

19:19 akurilin: So if want to cache some resources in memory when starting my ring app, is a promise delievered from ring's init handler pretty much my best bet?

19:20 I basically just need to run a "def" that one time when init is run, but actually calling def is frowned upon afaik

19:20 justin_smith: akurilin: you could use an actual caching function, or even better use varnish in front of your app and let varnish do the caching

19:20 if the thing cached is the response to the client, that is

19:21 akurilin: justin_smith: in my case it's more of a large .json payload that I need to parse into memory and that is then used by a lot of the internal business logic. It's basically 100% like a totally static db.

19:21 TravisD: justinholguin: Wouldn't that still just return true?

19:21 akurilin: I just need to load it once.

19:21 TravisD: er, justin_smith ^^^

19:21 l1x: is there a way to convert a hashmap to a string without escaping quotes?

19:21 justin_smith: akurilin: fair enough

19:21 TravisD: sorry about that. Didn't realize you were both justins

19:21 justin_smith: TravisD: that was my point

19:21 justinholguin: We forgive you.

19:21 akurilin: justin_smith: so would a promise be a goot match there in your view?

19:22 justin_smith: heh, yeah, trickiness

19:22 I am one of 5 justins in my office

19:22 you could also do declare / def in init

19:22 but yeah, I think a promise is cleaner

19:22 TravisD: Hehe, Travis' are considerably rarer

19:22 guns: "Heather? Not me, Heather."

19:23 justin_smith: guns: yeah, it's pretty bad

19:23 the fun part is seeing all the emails meant for the other justins

19:23 and getting invited to meet with clients (one of the justins is a partner)

19:23 akurilin: justin_smith: fair enough. Do people ever try to bypass having to use @ to access promises to clean up the syntax by wrapping them in some kind of accessor or is it not worth it?

19:24 justin_smith: akurilin: that seems silly to me

19:24 I mean @ is an accessor (short for (deref ...))

19:24 akurilin: hey man, I save ONE entire character worth of typing, think about it!

19:24 :P

19:24 justin_smith: a let binding, to keep things concise, maybe

19:25 akurilin: ok fair enough, I'll buy that

19:25 justin_smith: I go for the philosophy that the closer a binding is to usage, the shorter a name you can get away with

19:25 so ns + var should form something totally unambiguous when combined

19:26 guns: re variable length: https://news.ycombinator.com/item?id=840331

19:26 justin_smith: and then for things bound right before usage, go super small, sure

19:26 akurilin: justin_smith: were you the one who recommended the init startegy to me many months ago? As in, you have Ring's init, and from there you call all of the other various inits in different namespaces?

19:27 justin_smith: probably, that is how I do it (when namespaces need state of course)

19:27 but I am working on more and more having state be returned from an ns, rather than being in it

19:28 (big plan is a plugin system where features are returned by a constructor function in each plugin ns)

19:29 akurilin: I also wonder if maybe it's a good idea to have a separate namespace for all the state that gets accumulated at init

19:29 justin_smith: html / enlive question: what is my best bet when I have some html and I want to get a truncated plain text out of it - or is there even some sane way to handle that?

19:30 akurilin: ns app.state or some such?

19:30 akurilin: yeah, cause right now I have "model.foo" with its own state, and "model.bar" with its own state

19:30 I guess we'll see on the long term

19:31 it's like with routers, splitting them up in different files is fun until you get to about 3 routes, after that you re-write it all in one place :P

19:42 guns: I'm thinking about symmetrically encrypting runtime passwords to keep them out of stacktraces (so just obfuscation); is this too heavy handed? Is there a reliable way of filtering stacktraces?

19:44 hiredman: what do you mean "keep them out of stacktraces" ?

19:44 justin_smith: how would the string end up in the stack trace - an exception handler that leaks info in constructing its message?

19:45 *exception thrower that is

19:45 technomancy: you mean core dumps?

19:45 guns: The record with password field gets pr-strd

19:46 justin_smith: by some tracing code, or in a stack trace?


19:46 guns: just stack trace to a log file

19:46 technomancy: I won't bother with local attackers

19:46 a local user can just get root and use gdb

19:56 justin_smith: guns: in that case, what about making sure the stacktrace never leaves the server?

19:56 then you only have local to worry about

19:57 guns: justin_smith: I won't be controlling the infrastructure

19:57 It's actually an IMAP client

19:57 justin_smith: ahh

19:58 so you can't be sure the client doesn't see a server stack trace

19:58 guns: I'm pretty sure they would see it :) and they're the sort of folks that would storm the gates

19:59 justin_smith: what about a redesign such that the actual password is never in a record? shouldn't you be comparing to a salted hash anyway?

20:00 guns: justin_smith: No, the actual IMAP password is needed to connect to the server; this is different from typical auth scenarios

20:00 justin_smith: ahh

20:01 I mean I would call that an infrastructural flaw that the password needs to be passed around like the village bicycle, but that's out of your control if you want to use that protocol

20:01 guns: It's up to the user. they can always use 2-factor auth with gmail etc

20:01 justin_smith: you could put the password inside a Byte[]

20:01 it is still readable by applying str, but won't get printed

20:02 ,(.getBytes "hello")

20:02 clojurebot: #<byte[] [B@aeddb5>

20:02 justin_smith: ,(apply str (.getBytes "hello"))

20:02 clojurebot: "104101108108111"

20:03 justin_smith: that at least prevents any legible printing, with a low overhead

20:03 dbasch: guns: keep passwords in memory only while you need them, don’t pass them around

20:03 justin_smith: oh oops!

20:03 fortruce_: when using clojure.lang.RT/loadLibrary, where does the Classloader attempt to find my library at, i'm getting UnsatisfiedLinkErrors trying to use OpenCV

20:03 guns: that's true; I might opt for that. I'll think a little harder about keeping the password in memory

20:03 dbasch: guns: passwords should be very short-lived in memory anyway

20:03 justin_smith: ,(String. (.getBytes "hello"))

20:03 clojurebot: "hello"

20:03 guns: dbasch: I think that's right. It's convenient for me; but the user should just be using gpg-agent or whatever anyway

20:05 amalloy: huh. i thought java had a SecureString or something like in C#

20:06 justin_smith: amalloy: maybe, but byte[] does what you want from it in terms of printing at least

20:07 or char[] I guess

20:07 guns: justin_smith: if you're going to do that; it's not that much harder to XOR, and not much harder to use AES

20:08 As long as it's understood that it's just obfuscation, no encryption

20:08 justin_smith: guns: the printed rep of byte[] reveals nothing of hte content

20:08 that's what you wanted, right?

20:08 guns: justin_smith: yes, it was.

20:08 and it's a good point

20:09 justin_smith: or am I missing something?

20:09 If you already punt on local attacks, an xor or aes or whatever don't get you anything the untrintable representation didn't

20:09 guns: no, not at all; I concede the point

20:09 dbasch is right in the end

20:10 justin_smith: hah, that was my first tack too

20:11 err not my first, but on of

20:12 another consideration regarding byte[] - since string is immutible you can't zero it out or obfuscate it when done, so it is hanging around until garbage collected

20:13 guns: I can just unload the responsibility of password storage to gpg-agent, and whatever's built into OS X; my only concern was efficiency, but it's really nothing in comparison to the IO

20:13 thanks everyone!

20:18 dbasch: justin_smith: that’s probably the case regardless, unless you control all layers of communication between the client and your app

20:20 justin_smith: dbasch: the various caching spots?

20:21 dbasch: justin_smith: no, your server. nginx, jetty, etc.

20:21 justin_smith: right, I mean caching abstractly, each of those has places where things stick around in memory

20:22 dbasch: yes

20:22 gworley3: back again with another question and possibly free SO points. anyone know how to do what i'm trying to do: http://stackoverflow.com/questions/23305042/automatically-require-dependent-namespace-in-clojure-macro

20:23 justin_smith: though ideally one could transfer and use credentials in such a way that the password is only plaintext in one specific place, and then one has the power to clear out the thing once done with if it is mutible

20:23 amalloy: gworley3: your problem is imaginary. they don't need to refer to env

20:23 dbasch: justin_smith: that’s really what oauth is for

20:24 gworley3: amalloy: oh?

20:24 amalloy: try macroexpanding that. you'll see that it expands to environ.core/env

20:24 justin_smith: yeah, that way you don't even need to pass the password around (what I was referring to with my talk about treating the password like a community bicycle above)

20:24 guns: I bet memset(p,0,n) isn't even guaranteed on cheapo RAM

20:24 gworley3: amalloy: yep, i've already seen that it does that

20:25 amalloy: syntax-quote fully-qualifies all symbols within it, for just this reason

20:25 okay, so what's the problem? clearly there's no :refer needed in the caller's namespace

20:25 justin_smith: gworley3: once required, the ns exists throughout the clojure process, loading the ns is not a per-parent thing

20:25 gworley3: amalloy: but when it include in a namespace without requiring environ.core, i get "unable to resolve symbol"

20:26 amalloy: gworley3: you must be misunderstanding either what you're doing or what the error message means, because that isn't what happens

20:26 you still have to require gworley3.utils, of course, but the reference to environ.core is unnecessary

20:27 gworley3: "Exception in thread "main" java.lang.RuntimeException: Unable to resolve symbol: env in this context"

20:28 justin_smith: but env won't end up in that code - it will be fully qualified, that is what ` does

20:28 something else is called env

20:28 gworley3: oh, you know what, you're right; i'm dumb

20:28 justin_smith: did you have an arg called env nearby?

20:28 gworley3: yeah, it was part of some other new code i had been writing and forgot about while i was doing the refactor to add the macro

20:28 justin_smith: err I mean code that referred to something called env

20:29 gworley3: welp, guess i learned the lesson that i actually know more about how macros work than i thought and should have looked for a more mundane explanation

20:29 justin_smith: also, read stack traces carefully

20:30 (pst) is your friend

20:30 arrdem: As is (e)

20:31 justin_smith: arrdem: *e ?

20:31 amalloy: gworley3: on the other hand, why is this a macro? write a function (defn env* [name default] (fn ([] (or (env name) default)) ([x] x))), (def username (env :username "mike"))

20:31 er, (def username (env* :username "mike"))

20:32 gworley3: amalloy: so i only have to write username once instead of twice

20:33 justin_smith: at a certain point DRY has deminishing returns I think

20:33 amalloy: i think that's a questionable economy, but if you're set on it, you should still define a function that does the actual work, and then a macro that wraps the little bit of sugar around it

20:34 gworley3: amalloy: that makes sense. this is actually the first time i've done something i could only dry up by writing a macro

20:34 normally i try to stick to functions

20:37 amalloy: really you can even write this as a function, by using intern instead of def. but again i'm not convinced that that's super-amazing

21:28 dnolen_: DataScript + Om example just so people can start experimenting https://gist.github.com/swannodette/11308901

21:29 that said, lots of potential here

21:29 ToxicFrog: Oh my god death to Java sockets

21:34 bbloom: dnolen_: pretty cool. coupled with the use of equiv, you'll be passing around tuples of [entity-id transaction-id] to all your react components in no time ;-)

21:34 dnolen_: bbloom: actually I think most people will just pass entities

21:34 bbloom: you just need to add entity caching over DataScript

21:35 get all the flexibilty of Datomic for the data model

21:35 w/o changing how components work and w/o losing fast rendering

21:35 bbloom: dnolen_: that definitely will be nice

21:36 irctc: hello

21:36 llasram: hello

21:37 bbloom: dnolen_: what would be cool would be if you could somehow hook the server side transaction log & stream "relevant" datoms down to the browser

21:38 not at all clear how you'd enable that w/o lots of custom work, but it would certainly be nicer than some half baked backbone/socket.io clusterfuck

21:38 tomjack: seems like maybe a can of worms though?

21:38 akhudek: bbloom: we just recently did this for sql, worked out really well. Planning on doing a source release at some point.

21:38 bbloom: akhudek: cool

21:39 dnolen_: bbloom: yes that's the next step

21:39 akhudek: bbloom: basically we have materialized views sitting in the browser, then any changes to the server database cause deltas to be sent to efficiently update any relevent client views

21:40 dnolen_: bbloom: DataScript's making me rethink some assumptions about how Om works (a good thing). It's much a better M story than what you see in most JS MVCs

21:40 definitely something I thought about when I was working on Om, but too lazy to implement the Datomic API, glad somebody else picked it up

21:41 tomjack: do you set up filtered server txlog to auto-transact into client's db?

21:42 and not transact into that db at all from the client otherwise?

21:43 s/db/conn/

21:44 I guess my confusion is where the boundaries are between the client and server databases

21:44 dnolen_: tomjack: that needs sorting out

21:44 tomjack: I'm mostly interested in the repercussions for data modeling on the client side as well as repercussions for app structure

21:45 bbloom: akhudek: that's neat. i'm curious to see how it came out

21:46 dnolen_: yeah, the cursor stuff seems to make sense for view-level state, but i was never sold on it for the M layer

21:46 dnolen_: bbloom: def, that's where it's kinda busted

21:47 bbloom: but widgets will want to update an entity, so you need some kind of reference back to the original data, but cursors may very well be overkill for this

21:47 bbloom: dnolen_: i think you can do much better for view state than the cursor approach too, but it's a pretty reasonable approximation of the "right" solution for both, so rather than dissuad you from going that route i wanted to see how far you could push it

21:47 answer: pretty far :-)

21:47 dnolen_: well, entities have a db ident in them, right?

21:48 dnolen_: bbloom: yep, the cursor idea was separate from the real goal anyway - efficient time travel

21:48 the end is more important than the particular means

21:48 bbloom: yes

21:49 re: db ident

21:49 bbloom: dnolen_: i'd be interested to see if you can decouple the om design from the cursor such that you can ship om.cursor as a separate library for compat sake as you move towards supporting/encouraging various ad-hoc external state mechanisms

21:50 dnolen_: actually, i'd imagine such a cursor library could have zero dependencies on om entirely & still work w/ virtually the same api

21:50 dnolen_: bbloom: yeah, cursors are completely protocolized

21:50 so I think we're OK for a transition to something better if need be.

21:52 bbloom: dnolen_: you might want to re-read some of the crazy ramblings on awelonblue about ad-hoc external state

21:52 dnolen_: bbloom: will do

21:52 bbloom: dnolen_: also, here's the awelonblue/plan9/datomic inspired external state tree thing i was talking talking about: https://github.com/brandonbloom/exstate/blob/master/src/exstate/core.clj

21:53 TerranceWarrior: there a way to get upscroll in the Clojure REPL?

21:54 bbloom: dnolen_: i'm not sold on the tree shape, but i'm quite happy with the division of labor of the 5 protocols in there

21:54 zspencer: I'm sure there's a canonical blog post about looping until a predicate is met

21:54 Anyone want to point me there?

21:54 I'm doing loop recur, but the function may have side effects (callback prints things to screen)

21:54 bbloom: dnolen_: the snapshotting model would work quite nicely with a render loop

21:54 dnolen_: bbloom: yeah I think I'm finally coming around to the fact that trees are good for components, not good for the application - you want a real data model for that

21:55 guns: TerranceWarrior: That depends on the REPL, terminal, etc

21:56 zspencer: If you're not accumulating a value, then there's `while`

21:56 dbasch: zspencer: you mean while ?

21:56 zspencer: dbasch: guns: derp I am truly an idiot

22:01 TerranceWarrior: guns: java -cp clojure-1.6.0.jar clojure.main

22:02 guns: TerranceWarrior: Then it's up to the terminal to provide scrollback

22:02 TerranceWarrior: try tmux if your terminal doesn't have it

22:05 technomancy: TerranceWarrior: the repl that ships with clojure is kinda junk

22:05 TerranceWarrior: guns: ok

22:05 technomancy: well, not just kinda.

22:05 guns: :) rlwrap to the rescue

22:05 jcromartie: Exception in thread "main" java.lang.NoSuchMethodError: com.google.common.io.ByteStreams.limit(Ljava/io/InputStream;J)Ljava/io/InputStream;

22:05 when compiling ClojureScript code :(

22:05 danneu: Is there way to make it so that byte-arrays print out like `#<byte[] [00 aa bb cc dd]>` instead of `#<byte[] [B@170eca98>`? (To see the hex of its contents).

22:05 johnrx: Any pointers on getting a better "out of the box REPL" technomancy ?

22:05 I never envisaged to change it...

22:06 jcromartie: this is pretty mysterious to me https://gist.github.com/jcromartie/6571f07675cd4768a308

22:07 technomancy: johnrx: depends on what box you're talking about

22:08 guns: danneu: I believe you can do this by extending print-method

22:09 johnrx: To be honest, I never thought of improving the REPL. It's still a little foreign for me.

22:09 I don't really know where to start exploring. I'm still using it in a very Pythonic way...

22:09 danneu: no limit on that byte stream. your compiler is open to heartbleed

22:10 TerranceWarrior: guns: invalid.

22:11 technomancy: johnrx: leiningen ships with a much better repl, including a readline port

22:11 but I don't know if it's worth trying to improve the one that ships with clojure

22:11 johnrx: technomancy: you mean the one when you "lein repl" ?

22:12 guns: jline2 is in the uncanny valley for me; so close

22:12 TerranceWarrior: ?

22:13 technomancy: johnrx: yeah

22:13 jcromartie: it's my dependency on clojurewerkz/urly

22:14 johnrx: technomancy: This is what I use :) I thought this was the standard REPL for Clojure, since it's (for me) the easiest and quickest way to get running.

22:17 jcromartie: I should jettison that dependency just for being called "clojurewerkz/urly"

22:18 guns: danneu: (defmethod print-method (Class/forName "[B") [v w] (.write w (str (mapv #(symbol (format "%02x" %)) v))))

22:19 ,(byte-array [0 127 255])

22:19 clojurebot: #<byte[] [B@1f782b8>

22:19 guns: I guess that's not allowed

22:20 by the bot I mean; works in the REPL

22:22 llasram: guns: Well, you didn't have clojurebot eval the print-method definition

22:22 guns: llasram: oh, I guess I don't know much about the bot

22:22 oh I forgot the ,

22:22 ,(defmethod print-method (Class/forName "[B") [v w] (.write w (str (mapv #(symbol (format "%02x" %)) v))))

22:22 clojurebot: #<MultiFn clojure.lang.MultiFn@1952e89>

22:22 guns: ,(byte-array [0 127 255])

22:22 clojurebot: [00 7f ff]

22:27 jcromartie: in ClojureScript, how can I access the results of document.getElementsByTagName(…) as a seq?

22:27 the result is not seqable

22:27 and I can't coerce it to a vector

22:28 i.e. what's wrong with this? (def body (-> js/document (.getElementsByTagName "body") first))

22:31 guns: jcromartie: IIRC that's a NodeList; I'm not sure why that doesn't implement ISeq, but there's probably a good reason for it

22:31 you can use the native methods to iterate, or maybe implement the seq protocols yourself

22:39 j201: jcromartie: (def body (-> js/document (.getElementsByTagName "body") array-seq first))

22:43 or (def body (.-body js/document))

22:54 fortruce_: how do I call into a java method that modifies one of the args as the return value

22:57 nvm, I got it

23:05 TerranceWarrior: anyone else us eclipse with clojure?

23:06 ivan: I wanted to SSH into a Clojure REPL a week ago: https://gist.github.com/candera/11310395

23:06 * ivan learns the "just wait a week for someone else to do it" methodology

23:08 TerranceWarrior: i installed the plugin for eclipse. but i get a an empty memory window for a new clojure project.

23:16 Frozenlock: ivan: What's the benefit?

23:16 Versus using the usual SSH on your machine that is

23:20 ivan: Frozenlock: nREPL as everyone uses it allows anyone on the machine to connect to your REPL

23:24 xhh: any knows is there a way to access ENV variables in project.clj?

23:26 bbloom: xhh: i think the whole project.clj file is in a syntax-quote, so you can just ~(some code here) and get env vars the normal way

23:26 xhh: bbloom: thanks, will try

23:30 bbloom: you are right, System/getenv works in project.clj, thanks again

23:51 johnjelinek: hihi all

23:51 is anyone available to review my code to see if it's idiomatic or if it sucks?

23:52 TerranceWarrior: i think after I get a Doctorial in computer configuration I'll be able to upgrade the REPL under Eclipse.

Logging service provided by n01se.net