#clojure log - Apr 30 2013

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

0:00 technomancy: postgres devs should know better =\

0:00 callen: I really wish Clojure on Android didn't have such a slow startup time.

0:01 hiredman: to be fair 1.5 is pretty old

0:01 even 1.6 is supposed to be EOL any day now

0:02 j4x0n: Apparently they've done it before. It was fixed then someone must have recompiled.

0:02 technomancy: hiredman: actually it's just Oracle's JDK that is going to be EOLed

0:02 OpenJDK has no such plans

0:04 callen: OpenJDK performs just fine as well, anecdotally.

0:09 tieTYT: here's some code I converted from java. How could this be changed to be more idiomatic? https://www.refheap.com/paste/43d1ca29fe152a2cd3f80f1cb

0:11 callen: tieTYT: the manual type-checking and dorun usage is very meh.

0:11 as is the direct interaction with Swing.

0:12 tieTYT: http://daveray.github.io/seesaw/ at least use it pedagogically, if not actually in your thing.

0:12 tieTYT: callen: I don't think I can use seesaw for this

0:12 if you assume that, how could I avoid the manual type-checking?

0:13 callen: tieTYT: that is very unfortunate. learn from seesaw then.

0:13 tieTYT: learn more Clojure and you'll get your answers re: avoid manual type-checking.

0:14 tieTYT: callen: I've been reading seesaw source for days now

0:15 brehaut: tieTYT: is the purpose of the type check to ensure that its not nil or something?

0:15 and if you want real type checking, theres a library for that

0:15 tieTYT: brehaut: it's to ensure that it is a JComponent. If it's not a JComponent, it won't have a getInputMap

0:15 callen: brehaut: (instance? ...)

0:15 tieTYT: and getComponents returns Component, not JComponent

0:16 brehaut: callen: obvious its instance at the moment, but i presume theres a reson for the check if its ported from java

0:17 tieTYT: if I don't do that check, it could try to call getInputMap on an instance that doesn't have that method

0:23 brehaut: well, if you need polymorphic functions, protocols are probably a better way to go about it

0:23 you can implement protocols for nil or object if needed

0:23 for your default behaviours

0:23 this is assuming you are passing non-compliant objects into the function

0:24 tieTYT: i'm always passing a JComponent in

0:24 does that mean i shouldn't use protocols?

0:25 brehaut: if you always pass in something that supports that method then no protocols, no type checks

0:25 just dont go passing the wrong thing in

0:26 tieTYT: line 11 may pass in a Component that's not a JComponent

0:26 i thought you meant me as in what the programmer passes in

3:04 noprompt: does anyone use pre/post conditions?

3:05 i rarely see them used "in the wild" but the seem useful.

3:06 Raynes: noprompt: Not really.

3:07 murtaza52: is it possible to short circuit a `reduce`, like what `some` does

3:10 Raynes: murtaza52: In Clojure 1.5 you can return (reduced) to stop the reduce.

3:10 But only in 1.5+

3:11 noprompt: Raynes: yeah. so i take it no one uses them.

3:12 well, what's a clean way to assert arguments meet a certain criteria?

3:12 Raynes: &(doc assert)

3:12 lazybot: ⇒ "Macro ([x] [x message]); Evaluates expr and throws an exception if it does not evaluate to logical true."

3:12 Raynes: noprompt: But if you're gonna use assert, might as well use pre conditions and shit.

3:12 I mean, just because nobody uses them doesn't mean they aren't perfect for your usecase.

3:12 They were added for a reason.

3:13 Very little is in Clojure that Rich didn't think was useful.

3:14 sw2wolf: Does Rich has id in this channel ?

3:14 noprompt: the AssertionError could be a bit cryptic though for a function in a public api.

3:14 tgoossens: sw2wolf: yes

3:14 sw2wolf: Is it Rich ?

3:15 i just want to highlight it in my ERC configuration

3:15 Raynes: noprompt: Well, then throw ex-info instead.

3:15 rhickey

3:15 tgoossens: I know that rich has been on IRC in the past. But I don't know about now

3:15 Raynes: He isn't here right now. Doesn't come very often.

3:15 When he does it's rhickey.

3:16 tgoossens: whats with all the 'idiomatic'. I seriously never encountered a community that used the word 'idiomatic' so often

3:16 noprompt: Raynes: ex-info?

3:16 Raynes: &(doc ex-info)

3:16 sw2wolf: Now i have erc-pals '("Hindley" "rhickey")

3:16 lazybot: ⇒ "([msg map] [msg map cause]); Alpha - subject to change. Create an instance of ExceptionInfo, a RuntimeException subclass that carries a map of additional data."

3:16 Foxboron: tgoossens: you can't come from Python.

3:16 Raynes: You're not very good at this, are you noprompt?

3:17 :p

3:17 Foxboron: tgoossens: the Python community uses "idiomatic" all the time.

3:17 "idiomatic python! idiomatic classes! idiomatic this and that!"

3:17 noprompt: tgoossens: so does the Ruby community too.

3:17 Foxboron: http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html

3:17 noprompt: Raynes: my brain is a little fried i guess. :/

3:18 Raynes: noprompt: <3

3:18 noprompt: i've been working on porting this legacy application at work to Clojure.

3:18 Raynes: &(throw. (ex-info {:some :data :about :the :exception})

3:18 lazybot: java.lang.RuntimeException: Map literal must contain an even number of forms

3:18 Raynes: &(throw. (ex-info {:some :data :about :the :exception}))

3:18 lazybot: java.lang.RuntimeException: Map literal must contain an even number of forms

3:18 Raynes: FUUUU

3:18 &(throw. (ex-info {:some :data :about :the :exception :okay}))

3:18 lazybot: java.lang.IllegalArgumentException: Unable to resolve classname: throw

3:18 Raynes: ffffffffffuuuuuuuuuu

3:18 &(throw (ex-info {:some :data :about :the :exception :okay}))

3:18 lazybot: clojure.lang.ArityException: Wrong number of args (1) passed to: core$ex-info

3:18 noprompt: Raynes: that happened to me last week. :P

3:18 * Raynes sends an email to Geni higher ups requesting to be fired.

3:19 Raynes: &(throw (ex-info "Goddamn it." {:some :data :about :the :exception :okay}))

3:19 lazybot: clojure.lang.ExceptionInfo: Goddamn it. {:about :the, :some :data, :exception :okay}

3:19 Raynes: Thank you.

3:19 &(try (throw (ex-info "Goddamn it." {:some :data :about :the :exception :okay})) (catch ExceptionInfo e (ex-data e)))

3:19 lazybot: java.lang.SecurityException: You tripped the alarm! catch is bad!

3:19 Raynes: Oh blow me lazybot.

3:20 noprompt: but gawd. the application is a maze of 6-year-old php and javascript (interleaved of course).

3:20 murtaza52: I have a seq of vectors. I want to iterate through them. Modify only the first vector that meets a pred. Return back the coll with the modified vector.

3:21 Raynes: &(doc ex-data)

3:21 lazybot: ⇒ "([ex]); Alpha - subject to change. Returns exception data (a map) if ex is an ExceptionInfo. Otherwise returns nil."

3:21 murtaza52: How do I do the above? bcoz all methods such as for and reduce will modify all vectors that meet the pred, while I want to modify only the first that meets the criteria.

3:21 Raynes: noprompt: So my code should work. As an example.

3:21 noprompt: ExceptionInfo is basically an exception that doesn't suck and allows you to pass data out.

3:21 tgoossens: and with idiomatic i guess you mean "conventional" ?

3:22 noprompt: Raynes: that's neat-o.

3:23 gonna try it out in the repl real quick.

3:23 itemad: http://www.youtube.com/watch?v=UrMWRAaFdIc&feature=youtu.be

3:23 ops! :-P

3:26 noprompt: hmm... i'm debating whether i should add a dependency, steal code, or hand-roll a color lib for garden.

3:27 tomoj: murtaza52: https://www.refheap.com/paste/7dc0b0d3e81f5ed63c7b4d589 hmm, surely there is a better way?

3:27 noprompt: aren't those always the choices? geeze. i think i need a drink...

3:28 Foxboron: tgoossens: idiomatic is an idiom. It could be obscure code which is widely known to be the "right" way. Think of it as language idioms. "Break a leg" is an idiom.

3:28 tomoj: I would like to write it as something like (update-in vecs [map (some pred)] f)

3:29 (hypothetical)

3:29 (.. and probably confusing because the names 'map and 'some are taken. ignore me)

3:32 noprompt: Raynes: i guess what i like about the pre conditions is that it can make something like (if (meets-criteria x) do-stuff (throw ...)) a bit cleaner.

4:12 Odinodin: Given I run lein test, when a test fails, the process just hangs and I have to manually stop it. Does anyone know if there is anything to get around that?

4:13 noprompt: /quit

4:20 noidi: Odinodin, maybe you have a thread that's still alive and blocking the app from exiting

4:22 I think you can use VisualVM to see what's going on while the process hangs http://docs.oracle.com/javase/6/docs/technotes/guides/visualvm/

4:23 Odinodin: noidi: ah, thanks, that seems very probable. We have a jetty server running during the tests thats probably the culprit

4:26 nbeloglazov: What is the usage of symbols in edn format? I cannot find any real use case for them.

4:29 tomoj: datomic is an example where they are used

4:30 the rest interface accepts queries like [:find ?x :where [?x :foo]] as edn

4:33 I guess datomic shows two use cases: representing binding in edn, and referring to clojure vars

4:37 my intuition is that the space of symbols in a language encoded in edn will tend to be more closed (less open) than the space of keywords

4:38 hmm

4:39 I guess the difference is really more just that keywords are supposed to mean themselves where symbols can be assigned particular meanings

4:48 nbeloglazov: tomoj: thank you

5:09 no7hing: does anybody know of a java/clojure lib similar to https://github.com/jubos/fake-s3 ?

5:11 jaley: no7hing: are you just trying to stub out an S3 server for testing purposes?

5:11 no7hing: jClouds' blobstore abstraction has a stub provider implementation, which can be useful for that

5:12 no7hing: @jaley yes

5:12 @jaley i'll have a look at it, thanks

5:16 jaley: no7hing: if you depend on [org.jclouds/jclouds-blobstore "1.6.0"] in your project.clj

5:17 no7hing: you can then (:require [org.jclouds.blobstore2 :as blob]) and use (blobstore "transient" "" "") to get a fake instance

5:17 no7hing: all of the blob/put-blob blob/get-blob will work with it, storing entries in ram

5:18 no7hing: I believe there's also a filesystem implementation if you need it

5:18 no7hing: ram only sounds perfect for my needs

5:19 i'll just pre-populate the blobstore with my data and don't need to tamper with the application code, as it's tested from another vm

5:20 jaley: no7hing: presumably you also want your code to actually talk to S3 later?

5:20 no7hing: when you want to plug into s3, you need to add a dependency on the s3 "blobstore" provider to your project and create an instance of that with (blobstore "aws-s3" "access-key" "secret-key") instead

5:20 no7hing: already doing it

5:20 jaley: no7hing: cool

5:21 no7hing: thanks for your help!

5:21 jaley: no7hing: no problem

5:49 nbeloglazov: Is there some clojure expression that is not valid edn expression?

6:00 tomoj: nbeloglazov: ::foo

6:00 among others..

6:00 #(foo)

6:00 @foo

6:01 #'foo

6:01 nbeloglazov: :) Ok, thanks

6:01 tomoj: though

6:01 those last ones are all sort of cheats

6:01 (fn [] (foo))) and (deref foo) and (var foo) are all valid edn..

6:02 #java.net.URI["/foo"]

8:48 CookedGryphon: Hey all. So I don't much like the try/catch form in clojure. I find it always produces ugly, hard to follow, hard to re-use and hard to compose code. What i do instead is in this gist: https://gist.github.com/AdamClements/5488162 what do people think of this? I'm tempted to make it a library, but a dependency and a require feel like overkill for one/two macros!

8:51 clgv: CookedGryphon: probably, you do not know "dire" https://github.com/MichaelDrogalis/dire

8:52 CookedGryphon: that lib allows you to decouple error handlers from the functions they might appear in

8:53 CookedGryphon: as well as pre-/post-hooks

8:53 CookedGryphon: clgv: I do know dire, I find it's overkill for most of my use cases

8:53 and does var rebinding, which I don't really like

8:54 as it's all too easy to miss that your error handling is subverting your code path, making it hard to read

8:55 clgv: CookedGryphon: but you can really dcouple the handlers from code which is one step further than your macros

8:55 CookedGryphon: if you see (defn times [a b] ...) and then something which calls (times 2 3), you'd expect it to go straight into that function, which could lead to unpredictable behaviour if you've actually rebound the times var

8:56 I feel it's a step too far and has the potential to reduce readability, especially if you're reading someone else's code and aren't used to dealing with errors in that way

8:56 clgv: CookedGryphon: well, that's what documentation is for. if you have a coding guideline for error handlers of this kind in your project - you'll expect that those handlers will kick in

8:57 CookedGryphon: it is certainly a matter of personal taste. but I'd choose dire before those macros in the gist, since using them consistently also makes the code quiet complex.

8:58 CookedGryphon: my point is, someone's going to see this, think great, write a separate namespace for handlers (to keep similar things bundled together), gleefully rebind these variables. Someone else comes along and they're missing half the code but don't even realise it because there's no reference to the error stuff

8:58 clgv: CookedGryphon: but that is a documentation problem.

8:59 CookedGryphon: not really, it's an evident code problem

8:59 I don't want to have to read a manual on how this particular codebase handles errors, that sounds like the java way of doing things

9:00 Morgawr: what function can I use if I want to update all the values of a hashmap without touching the keys?

9:00 like a map but only on the values

9:00 clgv: Morgawr: there is none. you can build it via reduce-kv

9:01 Morgawr: I'll try, thanks

9:01 CookedGryphon: Morgawr: I believe there's something in the flatland/useful library which does that

9:01 Morgawr: CookedGryphon: I'm using ClojureScript so I can't really rely on external libraries

9:02 clgv: Morgawr: if you change all values you actually build a new map even if you use assoc. since there does not remain much for structural sharing

9:02 CookedGryphon: Morgawr: fair enough, you could copy the implementation though

9:04 Morgawr: clgv: the thing is, I have a hashmap that contains all filenames and I want to append a different extension at the end of said filenames (to distinguish between .mp3 and .ogg sounds depending on the browser)

9:06 clgv: Morgawr: (defn update-map-values [m f & args] (persistent! (reduce-kv (fn [r, k, v] (assoc! r k (apply f v args))) (transient {}) m)))

9:06 Morgawr: you might also add the key to the function invocation

9:06 Morgawr: oh wait

9:07 I found a much easier way

9:07 http://stackoverflow.com/questions/1676891/mapping-a-function-on-the-values-of-a-map-in-clojure this seems pretty good

9:07 and it works :)

9:07 clgv: Morgawr: yes that works. the reduce-kv is the faster approach in Clojure - dont know about ClojureScript

9:09 Morgawr: I don't really need speed at the moment though, it's a very simple function. Thanks either way :)

9:11 LiaoPengyu: Hello?

9:11 clojurebot: BUENOS DING DONG DIDDLY DIOS, fRaUline LiaoPengyu

9:11 LiaoPengyu: javadoc

9:11 ToUpperCase

9:51 xeqi: Raynes: ping; what kind of info do you scrape off clojars for lazybot?

9:57 no7hing: is there a fast way to add a virtual host to ring/jetty?

9:57 weavejester: no7hing: A virtual host is just dispatching off the Host header

9:58 In Compojure, you can write: (context "http://subdomain.example.com/&quot; [] ...)

9:59 At least in theory...

9:59 no7hing: @weavejester i didn't get them to show up in the app, but haven't gone for those context's though

9:59 weavejester: Actually, it would probably be better to write:

9:59 (ANY "http://subdomain.example.com/&quot; [] (routes …))

9:59 I know that one works

9:59 Not sure about the context

9:59 no7hing: will try that, thanks

10:00 weavejester: But you can always dispatch off the (get-in request [:headers "host"]) anyway

10:00 no7hing: i understood them to be a way to bundle up handlers;

10:00 but that's just e

10:00 me

10:00 was thinking too complicated. again.

10:00 weavejester: The context macro is a way to add a common prefix to a set of routes.

10:01 no7hing: what i thought

10:01 but couldn't express

10:08 mefesto: any know if the docs for weavejester/{hiccup,compojure} currently in a transition? Seems like the links are broken and no css

10:09 http://weavejester.github.io/hiccup

10:09 weavejester: mefesto: Looks like github.io domain shift broke the redirect

10:10 http://weavejester.github.io/hiccup/

10:10 If you add an ending / it works

10:10 mefesto: weavejester: ahh thank you

10:10 weavejester: Not sure how to fix that for a static site...

10:11 I guess I should alert github to the issue. "/foo" should redirect to "/foo/"

10:12 wink: yeah

10:13 Anderkent: technomancy: https://github.com/technomancy/leiningen/blob/master/src/leiningen/pom.clj#L234

10:13 (if (seq extra-src) (add-test-sources)) ? :(

10:13 mefesto: weavejester: it loads the index page correctly but the resources within the page are relative (js/blah.js) whereas (/hiccup/js/blah.js) would fix it

10:14 weavejester: mefesto: Yes, but that would require the docs to know where they are being deployed to.

10:14 mefesto: maybe i shouldn't say `fix it` but work-around it

10:14 weavejester: ah i see

10:15 weavejester: Ideally the docs should work as local files as well

10:15 Which means relative links

10:15 mefesto: yeah definitely wouldn't want to sacrifice that.

10:16 knowing to put a slash at the end is enough for me :)

10:19 kasterma: I just run into some confusing (for me) behaviour of equality. See https://gist.github.com/kasterma/5489015. It seems declared but unset symbols are treated specially for =.

10:20 Is it that, or am I missing something in the behaviour of '?

10:22 clgv: kasterma: thats symbol versus variable value

10:23 kasterma: Could you explain a little more?

10:23 clgv: kasterma: those list constructions are not the same: (def x 42) (list x) => (42), '(x) => (x)

10:25 kasterma: (= (list |) dd) => true

10:25 Ahh, but why did it work with a keyword?

10:25 clgv: keywords evaluate to themselves

10:26 kasterma: So in the equality test the content of the list is evaluated, and evaluating | doesn't work?

10:27 clgv: kasterma: in that expression you construct a list with a single element which is the value that is bound to |

10:27 kasterma: Which does not exist.

10:28 clgv: kasterma: | is unbound and thus returns an instance of clojure.lang.Var$Unbound which is an implementation detail

10:29 kasterma: clgv: thx, for the help.

10:30 mefesto: when using lein-ring and lein-cljsbuild is a typical workflow for generating a standalone jar something like the following or is there another way? lein cljsbuild prod && lein ring uberjar

10:32 ideally, i'd like to only have to issue `lein ring uberjar` and have cljs build with all the optimizations for production

10:35 clgv: kasterma: a simple rule to remember: only use '(1 2 3 4 5) to construct list of constants

10:35 ucb: when I eval this I get :default, where am I going wrong? (condp <= 1 0xff "yes" 0xffff "no" :default)

10:36 clgv: ,(<= 1 0xffff)

10:36 clojurebot: true

10:37 kasterma: clgv: thx

10:38 ucb: ,(<= 1 0xff)

10:38 clojurebot: true

10:38 * ucb is puzzled

10:38 clgv: &(condp >= 1 0xff "yes" 0xffff "no" :default)

10:38 lazybot: ⇒ "yes"

10:38 akells`: Is a [B not a bytearray? I'm trying to call .length on something that is a [B and its telling me 'no matching field found: length for [B'

10:38 clgv: the application of arguments is the other way round in condp

10:39 quote: " & & & & & 0 & 0 & 1 & 0 & 0 & 0 & 0 & 1 & & & & \\"

10:39 oops

10:39 nDuff: akells`: there's an alength function

10:39 clgv: quote: "For each clause, (pred test-expr expr) is evaluated."

10:39 nDuff: akells`: ...Java exposing it as a field is syntactic sugar.

10:39 ucb: clgv: ooh, nice, thanks

10:39 clgv: totally misread that

10:40 akells`: nDuff: that seems to be working. is this the length, in bytes?

10:40 thank you very much, by the way

10:40 clgv: ucb: I would have guessed for (pred expr test-expr) as well

10:40 nDuff: akells`: number of array elements, so for a byte array, yes.

10:40 ucb: *nod*

10:40 akells`: much appreciated!

11:26 Is this going to actually concatenate these two byte arrays? Or is my repl misleading me a little bit by saying it returns one? (byte-array (concat (.getBytes "edf") (.getBytes "abc")))

11:32 * gfredericks imagines a variant of let that allows side-effects in between bindings

11:33 xeqi: (let [x 3 _ (println x) y (+ 1 2) _ (println y)] y)

11:33 &(let [x 3 _ (println x) y (+ 1 2) _ (println y)] y)

11:33 lazybot: ⇒ 3 3 3

11:33 gfredericks: (let [a (b), :do (things), c (d)] ...)

11:33 xeqi: yeah, I use that for debugging. feels to awkward to use for real code

11:58 dnolen: ibdknox: congrats on the latest release!

11:59 ibdknox: dnolen: thanks :)

12:10 seangrove: ibdknox: Yes, it seemed very well received on hn, great job

12:10 n_b: I'll second that!

12:10 It's helped get a few of my friends into Clojure :)

12:43 saolsen: that js integration is great, does it work that well for clojurescript?

13:00 dnolen: saolsen: LT is written entirely in ClojureScript as far as I know and I believe ibdknox uses LT to dev LT, so I imagine it works OK. Would like to see more docs on that tho.

13:04 ibdknox: saolsen: dnolen: because of the way cljs works, you'd have to do some weird things to get the same level of eval. For one, it requires replacing the source of a file, which means you'd have to completely recompile on every eval :/

13:05 that being said, LT gets around this because of the BOT architecture - everything is late bound

13:09 dnolen: ibdknox: hmm, why do you need to re-compile the whole file if you just want to change a single def?

13:09 ibdknox: dnolen: because I need the complete output of bootstrap.js or whatever you call the cat'd source

13:10 dnolen: stuartsierra: can we do another CLJS at some point? It's been a while. Main changes would be Clojure 1.5.0 dependency and data.json 0.2.2

13:10 stuartsierra: will do

13:10 may need updating since Sonatype Nexus change — I'll look into it

13:11 dnolen: ibdknox: oh this is for dev'ing LT directly, I guess less a problem if you're using LT to dev your own CLJS stuff?

13:11 stuartsierra: 1.5.1 I meant

13:11 stuartsierra: ok

13:11 ibdknox: dnolen: nope, this is for the VM patching for any CLJS. You can always do normal eval, which is actually more than enough in most cases for CLJS

13:12 dnolen: but to do the same things I was showing in the cube video, I have to replace the original source file with a new one and they have to be relatively similar - so I would need the new result of compilation to swap it out with

13:21 dnolen: ibdknox: hmm make some sense ... is there some way you see to make that process smoother?

13:22 wink: hm, anyone ever tried to put json into mysql via korma? looks like an encoding problem, but it's weird

13:22 saolsen: I've been working on a cljs game and that level of interaction with a threejs canvas would be the greatest thing ever

13:40 ibdknox: saolsen: depending on how you write your game, you may not need that stuff

13:41 dnolen: I haven't though through it too far yet. There may be something clever to do.

13:54 akells`: clojure.java.io/copy should be able to handle any byte array, correct?

13:56 amalloy: akells`: i doubt it

13:57 well, i guess it does. it implicitly creates a Reader from it. okay

13:57 er...an InputStream

13:57 akells`: I must be doing something else wrong. It works fine with a byte array from an image file

13:57 but it doesn't seem to be working quite the same with a byte array from a text/html file

13:58 well, its actually a byte array that is a concat of two other byte arrays. but it works fine for the concat that uses an image file's byte array, but not for the concat that uses a text/html file's byte array

13:59 amalloy: well that's obviously a red herring. the jvm doesn't remember where arrays came from

14:00 akells`: I just wanted to make sure clojure.java.io/copy should work in any case. sounds like I've got an issue somewhere else. this was helpful, thanks amalloy

14:01 _francis_: I'm looking at this code https://www.refheap.com/paste/14081 and wondering why you would put a type in a function metadata - thoughts anyone?

14:05 arrdem: _francis_: one day god willing we will have optional typing able to take advantage of that data

14:05 _francis_: arrdem: thanks

14:06 arrdem: _francis_: actually no. in this case you are type-hinting the function.

14:06 _francis_: arrdem: I thought that type hints go in the arg list?

14:07 arrdem: _francis_: you can put them there too.

14:07 _francis_: I'm not clear on the details, but I understand that it type-specializes the generated code. Used for performance and for Java interop.

14:09 _francis_: arrdem: Are you certain that types in the metadata will be used for type-hinting? In this case the fn will return that type, but can accept several different types.

14:09 arrdem: _francis_: that's why I say I'm not sure. I'

14:10 ve seen argument metadata used to clamp down the function dispatch time, but I'm not sure what effect typing the return value has.

14:11 _francis_: Could you supply an example?

14:12 svedubois: In CLJS, how can I set some value inside a "doto".

14:12 For example, I have this:

14:12 (set! (.-color sphere) "red")

14:12 And I would like to have something like this:

14:12 (doto (sphere.)

14:12 (.-color "red"))

14:13 dnolen: _francis_: the compiler will use that information, it makes interop less tedious

14:14 _francis_: for example if you locally bind the result of invoking that function in let, that type hint will be propagated by the compiler

14:14 _francis_: dnolen: Awesome.

14:14 arrdem: dnolen: thanks for the save :p, didn't know (let) could use type hinting

14:15 _francis_: I can't find it ATM but I believe that the community matrix library is the last place I saw hinting in the wild.

14:16 dnolen: arrdem: most of binding forms really as they generally macro expand to let

14:16 matko: hi #clojure, I was wondering, in a multi-threaded environment, is it a bad thing to have many threads lying around that do nothing? For example, 5000 threads that mostly sleep but wake up now and then to update something? Or does this incur little cost?

14:16 dnolen: now that I think about it, I think all?

14:17 technomancy: matko: IIRC the primary cost there is creating and destroying threads; I think once they're around they're supposed to be cheap. but you might want to look into a thread pool anyway to avoid re-inventing the wheel

14:17 arrdem: dnolen: everything but def should macroexpand to a let at the end of the day

14:17 matko: technomancy: futures already use a threadpool right?

14:17 I was thinking of using futures for this

14:17 n_b: futures use the agent thread pool I believe

14:17 matko: hm.. is that bad?

14:17 I'd assume that means the send-off pool

14:18 n_b: That's my understanding

14:18 technomancy: matko: it just means you don't have a lot of control over it

14:18 may or may not be a problem in practice

14:18 matko: ok, so startup is costly, but a sleeping thread is not a bad thing

14:18 thank you :)

14:18 technomancy: well, not on a decently-sized linux system

14:19 matko: what about windows?

14:19 n_b: matko: I just did a pretty large threaded importer, and ended up using threadpools because I had tens of thousands of threads bein created when I just used futures

14:19 technomancy: matko: no idea about windows or mac

14:19 matko: ok

14:19 n_b: but it was a memory consumption issue due to my workload

14:19 matko: I'll have to test

14:19 technomancy: virtualized linux also might not be so hot

14:19 you'll have to test anyway; don't trust random advice on IRC =)

14:19 matko: hahah, that's advice I will trust

14:19 stuartsierra: Futures use the Agent send-off thread pool.

14:19 n_b: Benchmark both ways, and remember IFn implements Runnable so you can always (.new (Thread. #(some_fn))

14:20 matko: woah, I forgot about that

14:20 thanks for reminding

14:20 stuartsierra: In Clojure 1.5 you can configure the thread pools, e.g. set bounds.

14:20 n_b: matko: It makes using Executors much easier :)

14:20 matko: does clojure come with libraries for thread pools?

14:21 n_b: matko: Outside the basic concurrency constructs, not to my knowledge. Using Java interop was very easy IME

14:21 stuartsierra: matko: java.util.concurrent

14:22 n_b: Though IRC did much to help fill the gaps in my knowledge of it

14:22 matko: stuartsierra: that's not clojure :) but sure that works

14:22 stuartsierra: Clojure generally makes little effort to hide details of its host platform.

14:22 antares_: matko: agents use a thread pool and can be (ab)used very similarly to executes in j.u.c.

14:23 matko: j.u.c.?

14:23 technomancy: clojurebot: j.u.c?

14:23 clojurebot: Titim gan éirí ort.

14:23 matko: .... scary

14:23 technomancy: clojurebot: java.util.concurrent?

14:23 clojurebot: java.util.concurrent is "When I find myself in times of trouble / Prof. Doug Lea comes to me / Coding lines of wisdom / j.u.c."

14:24 matko: oh doh

14:24 nDuff: matko: RH has been pretty explicit about building Clojure's concurrency primitives to supplement, not replace, java.util.concurrent.

14:24 matko: cool, so I guess I'll prototype using futures. If it turns out to be problematic, I'll switch to a thread pool. either way should work fine for my purposes

14:24 tcrayford: man do I love that j.u.c. thing. That's cscotta or somebody like that originally?

14:24 technomancy: tcrayford: tnm

14:26 nDuff: matko: If a future isn't the right thing for the job, don't be shy about going straight to j.u.c. Clojure functions implement both Runnable and Callable; there's nothing at all difficult about using them with the Java APIs.

14:27 tcrayford: technomancy: oh, of course. I'm sad that dude deleted all his tweets, he was the best

14:27 technomancy: what; he did?!

14:27 matko: hm. I should have a good look at that library anyway. Guess I'll do so now

14:27 technomancy: weird

14:27 tcrayford: yeah :(((

14:27 technomancy: well it's immortalized in clojurebot now

14:31 matko: oh, I guess the thing I actually want is a scheduled thread pool. good thing I looked

14:47 xorola: is clojure strongly typed? i think so.

14:47 technomancy: xorola: yes

14:49 SegFaultAX: xorola: Java is strongly typed, yes.

15:01 ToBeReplaced: how can i extend the Closeable interface to an existing type i don't own? extend-type yells b/c Closeable is an interface, not protocol

15:03 for personal use, of course... i want to take a jzmq context which has a .term destructor that matches libzmq and make it usable from clojure with with-open

15:04 xeqi: you can't directly. One option is (proxy Closeable ...) and decorate the object

15:04 gfredericks: hmm

15:04 promises can't act like futures by throwing exceptions on deref can they :/

15:04 xeqi: hmm, I think I want reify there

15:04 instead of proxy

15:05 can never remember which until I try

15:05 gfredericks: oh nevermind I can combine futures and promises in a magical mystery way

15:05 ToBeReplaced: yeah reify would work, it would also muck with the type which might make reflections not happy, but i suppose that makes sense

15:05 thanks

15:25 svedubois_: I have a vector (def v ["a" "b" "c"])

15:25 And I would like to create a classname for each element in the vector in only one line.

15:25 Is it possible, how?

15:25 (def a (classname.))

15:26 SegFaultAX: svedubois_: What do you mean create a classname? Why does it have to be one line?

15:27 svedubois_: One global variable for each element in the vector

15:28 With the vector ["a" "b" "c" ... ], create (def a (classname.)), def b ..., def c ...

15:29 SegFaultAX: svedubois_: Why do you want to do this?

15:31 amalloy: yeah, that is not a thing you want to do

15:33 matko: (map #(eval `(def ~(symbol %))) v)

15:34 gdev: ,(map class [0.07 "james" :bond])

15:34 clojurebot: (java.lang.Double java.lang.String clojure.lang.Keyword)

15:40 svedubois_: ClojureScript can list all files in a given directory?

15:41 gfredericks: probably in whatever manner you would normally do that in javascript

15:41 which is "no" in a traditional browser setting

16:17 arrdem: can I add hooks to a lein command? so "ring server" triggers "lessc" in my specific case.

16:25 technomancy: arrdem: :prep-tasks ["lessc"] will cause lessc to happen before any code runs inside a project

16:25 arrdem: technomancy: thanks

16:25 technomancy: lessc needs to be fast if there's no work to do, because it'll trigger on every repl, complie, test, etc

16:26 arrdem: it's pretty fast atm since it doesn't seem to be building my CSS files -_-

16:26 technomancy: fast is good

16:26 arrdem: silent failure is bad tho

16:28 wink: hmm. (clojure.java.io/copy (clojure.java.io/input-stream "http://...x.png") (clojure.java.io "/path/to/foo")) copies one image and not another. reproducably. any ideas? :)

16:29 *add /output-stream ofc where needed

16:42 gdev: my eyes, they bleed, warning: java code https://www.refheap.com/paste/af945a051690ee85ec1d018cf

16:43 Raynes: gdev: This is beautiful code.

16:43 I strive to write this kind of code in Clojure.

16:44 arrdem: Raynes: not sure if sarcasm

16:44 Raynes: arrdem: Sarcasm.

16:44 arrdem: gud

16:44 iwo: hey, does anyone know of an example on how to create a vector of keys that is compatible with get-in/assoc-in/update-in FROM a map?

16:44 mthvedt: clojure is not type-safe and enterprise-ready, it cannot make code that beautiful

16:44 Raynes: I think amalloy wrote something to do that.

16:45 amalloy: doesn't ring a bell, sorry

16:45 iwo: so i have a nested map structure - i'm trying to decide how I could navigate this map to create all valid keys for get-in

16:45 Raynes: amalloy: You wrote a function to get all possible keyseqs from a map.

16:45 amalloy: I know you did because we discussed the implementation.

16:45 Don't screw with me, bro.

16:45 amalloy: i write a lot of functions. i don't remember this one

16:46 gdev: L.A. GUI with an Oakland back end

16:48 amalloy: it's not hard to write, though

16:48 https://www.refheap.com/paste/5823c0e842a3948b579c42cc5

16:49 modulo your decision about whether (:b) is a valid answer as well

16:49 Raynes: amalloy: I'm greping every piece of code you ever wrote until I find the one you wrote in the first place.

16:51 amalloy: it actually comes out a lot nicer if you're willing to count (:b) as a keyseq: https://www.refheap.com/paste/5885807c958f35ab9b80976c1

16:51 Raynes: I can't remember the bloody project.

16:51 Jiraph? Telemetry? BAH.

16:51 This is going to haunt me.

16:53 arrdem: Raynes: you were right, noir -> compojure wasn't that bad at all.

16:56 Raynes: arrdem: Whoa, you just now did it?

16:56 arrdem: Raynes: yeah I just got the user facing parts of my site ported in the last two hours

16:56 ppppaul: i want to output a JSON stream from my ring endpoint (using cheshire, and can't really figure out how to get an input-stream form it's generate-stream fn

16:56 any help

16:57 :)

16:57 gfredericks: ppppaul: oh there was something for this

16:58 arrdem: Raynes: once I got about 15 github documentation pages open it was dead easy

16:58 Raynes: arrdem: Worth it!

16:58 arrdem: ppppaul: someone hacked this live here a few months ago....

16:58 gfredericks: ppppaul: first find ring.util.io/piped-input-stream

16:58 ppppaul: gfredericks, i found some issues on cheshire and ring about this, but i'm looking for a hacked up solution now :)

16:59 i have the piped-input-stream src open...

16:59 gfredericks: then make your body (piped-input-stream (fn [out] (->> out (OutputStreamWriter.) (BufferedWriter.) (json/generate-stream data))))

16:59 ppppaul: i know i'm going to use it, and i know where to use it, but the cheshire stuff is what i'm tripping over

16:59 gfredericks, woooooo thanks so much :D

17:06 this is now a part of my liberator fork

17:06 woot

17:07 never has seeing a data dump from datomic felt so good

17:08 feel like watermelon

17:09 gfredericks: :)

17:09 I should pass on credit to whoever gave me that snippet in the first place

17:09 I have no idea who that was

17:09 (inc anonymous)

17:09 lazybot: ⇒ 1

17:09 arrdem: (inc clojure) ;; since gfredrics is passing

17:09 lazybot: ⇒ 11

17:10 gdev: yay, this works, but it seems hacky and amateurish which is a good description of my coding style so not surprising https://www.refheap.com/paste/cbb89e7032d2418dc20d66c84

17:11 gfredericks:) I'm still working on that database thing you helped me with; doseq on the update statement meant my update to database call was 1 to 1

17:12 gfredericks: gdev: how do you do updates without that being the case?

17:12 I've often wanted that

17:12 gdev: gfredericks:) I'll let you know when I figure it out =)

17:12 gfredericks: ha

17:13 gdev: having the data pre-staged was half the battle

17:15 gfredericks: ppppaul: ha I started that issue

17:15 ppppaul: :)

17:16 gfredericks: somebody, I think weavejester, pointed out at some point that the ring spec might need some amending to handle cases like this

17:17 not basic json, but any kind of streaming that involves an open resource

17:18 asteve: a coworker is trying to pull in a clojure project and is getting checksum errors on com/google/guava; he is using leiningen 2.1.x and we tried remove ~/.m2

17:19 26 days ago the developers for guava claimed they pushed a corrected checksum and that it would propagate over the next few hours

17:19 any ideas?

17:21 stuartsierra: dnolen: FYI, ClojureScript release build will need some changes to accommodate new Sonatype Nexus version.

17:21 I'm burnt out now but I'll try to get to it this week.

17:29 asteve: this is the exact problem a coworker was having earlier today http://stackoverflow.com/questions/15818219/failed-retrieving-guava-libs-from-maven

17:29 we tried lein clean and we tried removing ~/.m2 entirely

17:30 is there a way to download the dep manually?

17:30 arrdem: asteve: your best bet is probably gonna be to force lein to load without checks...

17:30 asteve: not sure how to do that tho.

17:31 technomancy: asteve: you can always build from source

17:31 mvn install or whatever

17:31 turning off checksum checks is pretty sketchy

17:31 arrdem: oooh yeah

17:31 technomancy: would strongly not recommend leaving checksum checks off

17:31 gdev: gfredericks:) sorry, I didn't mean ratio of database calls to update statement, im still trying to figure out how to interpret this oracle database trace file

17:31 technomancy: maybe turn it off once, download the dep, and turn it back on

17:31 asteve: sometimes bad checksums get stuck on a specific mirror

17:32 so only users from certain geographic locations see them

17:32 asteve: ah

17:32 technomancy: anyway you should definitely continue to communicate with the maintainers

17:32 asteve: ok

17:32 technomancy: until it's resolved upstream all you have are workarounds

17:38 iwo: hey, is there a neat way to do 'cons if not nil' in clojure?

17:38 arrdem: ,(cons 1 nil)

17:38 clojurebot: (1)

17:38 iwo: basically: (if x (cons x l) l)

17:39 arrdem: oh identity over list?

17:39 iwo: i suppose i could do: (keep identity (cons x l))

17:39 arrdem: ,(doc keep_

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

17:39 iwo: but that's even less neat :)

17:39 arrdem: ,(doc keep)

17:39 clojurebot: "([f coll]); Returns a lazy sequence of the non-nil results of (f item). Note, this means false return values will be included. f must be free of side-effects."

17:40 arrdem: no that's neater, it's just not gonna do what you want.

17:40 iwo: ?

17:41 this would work: (keep identity (cons x l))

17:41 i.e. cons regardless, but use keep identity to remove x if it was nil

17:42 what i'd really like is (if x (cons x l) l)

17:42 but in a single fn from clojure core :)

17:42 technomancy: iwo: useful's "fix" function might do that

17:42 nothing in core though

17:42 amalloy: iwo: (keep identity (cons x l)) doesn't do what you want at all

17:42 it will remove all the nils that were already in the list

17:43 sw2wolf: ,(doc identity)

17:43 clojurebot: "([x]); Returns its argument."

17:43 iwo: amalloy: not a problem for me, the list contains no nils

17:43 arrdem: amalloy: thanks, I didn't think it would behave but I wasn't sure what it _would_ do :p

17:44 iwo: technomancy: do you mean flatland/useful?

17:44 technomancy: iwo: yeah, but amalloy would know for sure

17:44 amalloy: fix can kinda do it, but it's awkward: (fix l x (partial cons x)) would work most of the time, or (fix l (not (nil? x)) (partial cons x)) to be careful

17:45 i don't think i'd use fix for this

17:45 technomancy: yeah, it's an awkward request =)

17:45 amalloy: (concat (keep identity [x]) l)?

17:45 but that's much harder than the simple (if x (cons x l) l)

17:46 i think test-> in 1.5 does a decent job of it, doesn't it?

17:47 (test-> l x (->> (cons x))) probably works

17:47 ,(doc test->)

17:47 clojurebot: Gabh mo leithscéal?

17:53 iwo: i guess clojurebot doesn't speak 1.5

17:54 (if x (cons x l) l) it is :)

17:57 mthvedt: is there a way to make a private defrecord, say Foo, and not have it expose ->Foo

17:58 gfredericks: mthvedt: you could muck with the var if you really wanted to

17:59 amalloy: mthvedt: this sounds like a great opportunity to use a hashmap instead of a record

17:59 gfredericks: haha

17:59 amalloy the hashmap salesman

18:00 amalloy: my hashmaps provide genuine, FDA-certified constant-time lookup time, won't you try one?

18:01 gfredericks: would "unused arguments" be a good kibit rule?

18:01 gdev: amalloy:) are they organic?

18:01 arrdem: amalloy: but can you optimize them out to structs at runtime?

18:01 amalloy: i was aiming more for the 1950s "door-to-door salesman" archetype, not the 2000s-era organic stuff

18:01 tcrayford: amalloy: I only use grass-fed, home grown vegan kosher paeleo primal hashmaps, you got any of those?

18:02 mthvedt: amalloy: can your hash maps implement protocols? :P

18:02 gdev: tcrayford:) lol at vegan paeleo

18:02 amalloy: use multimethods! technomancy is probably willing to put on an evangelism act to match my salesmanship, telling you how protocols are the devil

18:03 tcrayford: true story, I know a dude who's on something like that. Asking him "what he eats" leads to a pretty short list

18:03 technomancy: be free of their tyranny

18:03 * technomancy pens a jack chick tract

18:03 PudgePacket: Hi, I'm having some trivial problems importing jara .jars for a clojure project. I'm not sure where to keep the .jar, and how the import should refer to it, I'm used to C++ style of using a filename!

18:03 mthvedt: they are not my protocols

18:03 amalloy: technomancy: i'm afraid to google "jack chick tract"

18:03 tcrayford: technomancy: I use a protocol for this core abstraction (of data storage) in my app. Please be mad

18:03 Glenjamin: amalloy: i can't seem to find test->, did you mean cond-> ?

18:03 technomancy: tcrayford: there is still hope for you

18:03 amalloy: ~repeatability

18:03 clojurebot: repeatability is crucial for builds, see https://github.com/technomancy/leiningen/wiki/Repeatability

18:03 tcrayford: how do I teach clojurebot shit?

18:03 ~amalloy

18:04 clojurebot: amalloy is the spotlight illuminating my dumb mistakes

18:04 arrdem: loooool

18:04 amalloy: Glenjamin: i probably do. i didn't pay attention to the renaming thing

18:04 gdev: ~nDuff

18:04 clojurebot: Please don't use pastebin.com: there are lots of annoying animated ads. Instead, try http://refheap.com, an ad-free pastebin written in Clojure.

18:04 arrdem: PudgePacket: amalloy is telling you to import your jars to maven and then make them lein deps

18:04 PudgePacket: as of lein 2 lein no longer supports local non-maven jars

18:05 Glenjamin: ,(doc cond->)

18:05 clojurebot: "([expr & clauses]); Takes an expression and a set of test/form pairs. Threads expr (via ->) through each form for which the corresponding test expression is true. Note that, unlike cond branching, cond-> threading does not short circuit after the first true test expression."

18:05 PudgePacket: arrdem, can i just use maven commands in lein? I only have leiningen

18:05 arrdem: clojurebot: remember arrdem is about 85% corect

18:05 clojurebot: 'Sea, mhuise.

18:05 tcrayford: technomancy: also this app has a "util" namespace where I rewrote "keys" and "values" to be sane, also wrote get so it throws an exception if the key isn't there. Be more mad.

18:05 technomancy: tcrayford: non-nilling get is great

18:05 arrdem: PudgePacket: don't think so. you'll need maven to manipulate ~/.m2 in any reasonable way.

18:05 technomancy: but "util" is sad times

18:06 tcrayford: technomancy: I should just open up clojure.core right?

18:06 technomancy: totes

18:06 djwonk: I am using `bz2-reader` from http://www.paullegato.com/blog/reading-bzip2-files-clojure/ but I'm having a problem with it: https://gist.github.com/bluemont/8e8b717a732446fc9a8e#file-core-clj-L61

18:06 tcrayford: realtalk, I wish nil didn't exist. Clojure doesn't technically need it except for interop

18:07 Glenjamin: what is a good way to deal with "util" aka random bucket of functions i wish were in core?

18:07 also, what's so bad about Protocols?

18:08 arrdem: it's clojurebot: forget <phrase>, right?

18:09 tcrayford: clojurebot: forget forget

18:09 clojurebot: It's greek to me.

18:12 PudgePacket: arrdem, I've downloaded and got maven working, do i just perform a similar task to running a lein operation ? navigate to project directory then run the command?

18:15 arrdem: PudgePacket: http://www.pgrs.net/2011/10/30/using-local-jars-with-leiningen/

18:19 PudgePacket: arrdem, it says there is no project object model in the directory, im running from the project directory, do i need to create a POM somehow?

18:20 Glenjamin: xeqi: am i missing something, or does kerodon not handle select elements?

18:20 SegFaultAX: PudgePacket: Probably a good idea to read a tutorial on Maven.

18:21 PudgePacket: SegFaultAx, i'm just trying to use a local .jar file in my clojure code, this seems a pretty ridiculous amount of fiddling to get something so trivial working :/

18:24 technomancy: tcrayford: "except for interop" is kind of a really big thing though =(

18:24 but I would love a nil-free clojure

18:25 tcrayford: ofc ;). In a modern dynamically typed lang, with Maybe supplied by the lang, there's no need for nil (in my book)

18:26 Glenjamin: is Maybe actually an improvement over nil?

18:27 doesn't it just move the nil along to some point where you need a value?

18:29 tcrayford: it's different

18:29 Maybe as a return type says "this quite possibly will return nothing"

18:29 usually you have to dig in non-existent docs or read the code to find out if something can return nil

18:30 mthvedt: what's the point of maybe without type checking and/or pattern matching

18:30 Glenjamin: ^^ this

18:30 tcrayford: if you look at a function, and what you get out of it is a nil, then you know you have to handle the nil case

18:31 wheras if you look at a function, often you don't know if there is a nil case, then fail to handle it, then your program blows up in weird and wonderful ways

18:31 technomancy: it just forces awareness, right?

18:31 tcrayford: without pattern matching/monads/type checking, yeah

18:31 mthvedt: so, the point of maybe is to replace java annotations

18:31 got it

18:33 Glenjamin: but where do you write the Maybe return type in a dynamic language?

18:34 technomancy: docstring

18:34 the point is, you can't not handle maybe

18:34 tcrayford: also, you'd see it when you called the function at the repl

18:35 Glenjamin: right, you have to unpack it

18:35 i see

18:35 technomancy: like a reference type

18:37 SegFaultAX: "The point of maybe is to replace Java annotations" wut.

18:38 hiredman: if you fail to handle nil you aren't using mapcat enough

18:41 mthvedt: segfaultax: sarcasm

18:41 amalloy: (def easy-version-of-technomancy's-annoying-Maybe-fn (comp fromJust technomancy's-annoying-Maybe-fn)) ;; now i don't have to handle maybe anymore!

18:42 Anderkent: amalloy: fromJust throws on Nothing, surely

18:42 it wouldnt return nil

18:43 amalloy: Anderkent: of course, that's the joke. you're back to exceptions, just like you wanted

18:43 not you specifically, of course

18:45 * dnolen conceptually likes Maybe but also thinks it's damn ugly and suffers like most monads, from being poisonous

18:45 Glenjamin: xeqi: going to see if i can get dropdown support into kerodon, the enlive stuff is a bit black-magicky to me though - will send a PR if i get something reasonable

18:46 technomancy: I imagine haskell users look upon nil with the same disdain exception users look upon languages that use numeric error codes as return values

18:47 Anderkent: Sounds reasonable to me - I think nils are the source of more than half of the bugs i introduce

18:48 Oh, you forgot to initialize your map values to sets? Here, let me give you a nil so that you can conj onto it and break the code mysteriously 20 calls later :)

18:49 Glenjamin: isn't that basically what happens if you use Maybe with do notation in haskell?

18:50 the Monad composition just shuffles the Nothing along?

18:50 Anderkent: sure, but that's not what my problem is

18:50 the problem is that conj eats the nil happily

18:50 and gives you back a list :)

18:50 SegFaultAX: Glenjamin: That's the whole /point/ of Maybe.

18:50 Anderkent: nil is the empty list.

18:51 Glenjamin: is there a conj-set ?

18:51 SegFaultAX: conj-set?

18:51 Anderkent: I know, that's why this problem exists? If conj threw up on nil, I'd get errors at the failure point. But it doesn't, so I only get errors in some random other place that expects a set but sees a list

18:51 Glenjamin: a conj that always gives you a set :p

18:52 SegFaultAX: Anderkent: conj is fine. You should be correctly checking for errors in your data.

18:53 Anderkent: I should have a map type that throws on non-existing keys, instead of silently pretending there was a nil in it

18:54 Glenjamin: or better yet, a map type that gives you empty sets on new keys

18:54 Anderkent: well not quite, because it's rare you'd want an empty set for every key

18:54 it's like

18:54 Glenjamin: in this case

18:55 something like python's defaultdict, unsure if that fits the clojure model really

18:55 dnolen: And even tho the MLs got rid of null, ya still got the empty list to produce show stopping runtime errors - http://stackoverflow.com/questions/4883169/why-im-getting-exception-prelude-head-empty-list

18:55 Anderkent: you have some state, you store it as (def my-state (ref {:id-ste #{} :some-other-map {}})) and then somewhere else you have (update-in my-state [:id-set] conj new-id)

18:56 dnolen: c'est la vie

18:56 Anderkent: like what kind of idiom would prevent this from blowing up?

18:56 never conj in update-in?

18:57 SegFaultAX: Anderkent: Is it exceptional for the key to not be present?

18:57 hiredman: ,(doc fnil)

18:57 clojurebot: "([f x] [f x y] [f x y z]); Takes a function f, and returns a function that calls f, replacing a nil first argument to f with the supplied value x. Higher arity versions can replace arguments in the second and third positions (y, z). Note that the function f can take any number of arguments, not just the one(s) being nil-patched."

18:57 brehaut: dnolen: something something dependant types and total functions something *handwaves* solves that problem just fine

18:58 Anderkent: SegFaultAX: yes, the key is only not present because of the typo in original declaration

18:58 dnolen: brehaut: ;)

18:58 Glenjamin: oh, i see

18:59 if all you're worried about is typos, you're probably ok

19:00 Anderkent: I don't think "don't make typos" is a solution

19:01 Glenjamin: write some tests to express behaviour, you'll catch them soon enough

19:01 or take a typing class, i don't class typos as one of the major problems in software development

19:08 Anderkent: That was uncalled for. Whatever, I'm probably more likely to use something like (defn sget [map key] (when-not (contains? map key) (throw ...)) (map key)). I can imagine at least 2 ways in which even full test coverage wouldn't catch a similar update-in conj issue, but since it seems you never make mistakes I won't bother

19:10 SegFaultAX: Glenjamin: Humans are prone to typing errors. Some non-trivial percentage of programs are types by humans. Therefore some non-trivial percentage of programs are prone to typing errors. To categorically exclude typing errors as a source of bugs in software is utterly short-sighted.

19:10 Glenjamin: sorry, that came across as snarky, wasn't intended that way

19:11 if you're concerned that typos will be a major source of bugs, then you probably want a statically typed language?

19:11 SegFaultAX: Glenjamin: Humans are the source of bugs.

19:12 Glenjamin: which is why we write automated tests, and abstractions :)

19:12 SegFaultAX: Glenjamin: Automated tests can only capture at most a certain subset of all possible errors. Likewise with static typing. There is no silver bullet.

19:13 Glenjamin: agreed

19:14 i'm not claming i never make typos or introduce bugs

19:14 i'm claiming that I don't introduce enough bugs from typos to change my entire approach to development to attempt to avoid them

19:15 i feel like my tone isn't transferring very well though :(

19:17 brehaut: actually, you dont need static typing to catch typoes; clojure eliminates a large number of typo causing errors by requiring all symbols to be defined before they are reference lexically

19:17 SegFaultAX: Or at least declared.

19:17 brehaut: obviously whenever strings and keywords etc enter the mix, you reintroduce the potential for that type of typo

19:18 yeah sorry

19:18 SegFaultAX: As is the case in lots of languages that have forward decls.

19:18 (Dynamic or otherwise)

19:18 brehaut: (yup

19:19 tieTYT2: is there a function/library that takes a POJO and converts it into a clojure data structure?

19:19 SegFaultAX: On a related tangent, I've never really understood the justification for variable hoisting in JS.

19:19 brehaut: (clojure,set/subset? static-types static-analysis)

19:19 SegFaultAX: tieTYT2: Records are POJOs

19:19 tcrayford: dnolen: re the head of an empty list case, that's been a long complain of mine for haskell. Head should return a Maybe.

19:20 brehaut: also the bean function

19:20 tieTYT2: SegFaultAX: my java pojo already exists. Is that an issue?

19:20 ooh bean function

19:20 SegFaultAX: tieTYT2: Oh then you'll probably have to write a converter for it.

19:20 pojo->map or something.

19:20 tieTYT2: SegFaultAX: well it looks like bean would work?

19:20 brehaut: tieTYT: it creates a proxy thoguh, not a persistent structure

19:20 tieTYT2: am I wrong?

19:20 aw

19:21 it says it's read-only

19:22 SegFaultAX: Plus the bean function is probably a lot more expensive than it's worth if you're converting a lot of these objects.

19:23 I don't really know anything about how HotSpot may or may not optimize lots of reflective calls.

19:23 tieTYT2: k, i'll write my own converter

19:25 here's what I'm trying to do. I've got a list of this POJO. For shitty reasons, its equals() impl is worthless. I need to find instances in the list that are the same based off of specific fields and only keep the instance with the earliest date. Then I need to take the ones that are the same based on a DIFFERENT set of fields, copy the data (except for a primary key field) over to the

19:25 instance with a primary key... etc.

19:26 to me this sounds like a functional problem and it'd be easier to do in clojure. This is a javaee app and the class is an entity

19:27 Glenjamin: you might be as well just breaking into small functions for each step like you would in clojure, but staying on the java side

19:28 tieTYT2: Glenjamin: it's really hard to do that without a useful equals(). The collections have to be mutated along the way

19:28 and it's hard to figure out what's going on

19:28 Glenjamin: are the fields public?

19:28 tieTYT2: no, but you can get them through getters

19:28 hiredman: (->> objs (group-by identity-function) vals (map (partial sort-by date-of)) (map first) (group-by second identity) vals (map (partial apply merger)))

19:28 that should be second-identity

19:29 Glenjamin: just have your service class define it's own domain specific equals() function

19:29 tieTYT2: hiredman: yeah that's a shitload of code in java IMO

19:29 hiredman: and there is no need to make maps

19:30 Glenjamin: that certainly looks better than my idea :)

19:30 tieTYT2: hiredman: are you advocating what Glenjamin's suggesting with your comment?

19:31 hiredman: I dunno, I have Glenjamin on ignore

19:31 Glenjamin: :(

19:31 tieTYT2: sounds like a no

19:34 hiredman: why'd you mention the maps thing?

19:34 did you mean no need for a converter?

19:35 hiredman: yes

19:35 tieTYT2: ah, cool

19:35 i'll try it out, thanks

19:37 Glenjamin: i take it all back, i just got a mysterious null pointer error from deep in the stack :(

19:40 amalloy: check for typos

19:41 Glenjamin: heh, forgot to save a file :(

19:42 Raynes: I read "heh, forgot to save a life :("

19:43 tieTYT2: is this out of date? The second one looks like what I want to do

19:43 http://stackoverflow.com/questions/2181774/calling-clojure-from-java

19:43 it says: No need to call RT.init() anymore

19:43 but it only works if I do

19:44 djwonk: My bzip2 problem was that I needed to use the second constructor form. Groan: http://www.paullegato.com/blog/reading-bzip2-files-clojure/

19:44 Who knew that bzip2 files could be concatenated anyways?

19:45 tieTYT2: gives me this: java.lang.ExceptionInInitializerError at clojure.lang.Compiler.<clinit>(Compiler.java:47)

19:45 djwonk: Making the default be false, which breaks stuff when you don't expect it, is crazytown.

20:22 gdev: ,(#(* %)#_(if youre happy and you know it print a one)(*))

20:22 clojurebot: 1

20:22 ToxicFrog: MY BRAIN

20:22 gdev: your braine on drugs

20:24 tomoj: holy crap, pst takes a depth

20:26 now I can stop lein-swanking instead of jacking-in just to be able to see .printStackTrace

Logging service provided by n01se.net