#clojure log - Sep 18 2013

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

0:53 glosoli: got very silly question here, I have read about deftype and defrecord and it was marked that it compiles down to Java classes, so it got me wondering, what to does clojure code compiles by default?

0:54 callen: fucking netsplits.

0:54 rplaca: clojure compiles to Ja classes all over the place, but not so explicitly as with defrecord and deftype

0:55 s/Ja/Java

0:55 glosoli: rplaca: so that's what got me wondering, what's does explicit stand for in such context ?

0:55 TEttinger: glosoli, yeah, if AOT isn't on, you can take a look at the compiled bytecode and what names it gave it in... classes/ , was it?

0:55 rplaca: well, you get a class with a defined set of fields and methods and a name that is "your" name

0:56 TEttinger: stuff like core$_main$iter__18__22$fn__23$fn__24.class

0:56 rplaca: otherwise, things like functions compile to classes, but Clojure picks the names and interfaces that they implement

0:57 and the "standard" datatype are predefined classes

0:57 that you just use without having to think about it much

0:58 glosoli: interesting thanks!

0:58 rplaca: glosoli: np. enjoy!

2:12 callen: rplaca: if at all

2:21 indigo: Hm, apparently Windows thinks clj files are "Windows Shell Common Dll"s :P

2:23 R_Macy: Silly question, is the dash in front of a function symbol a convention (to show it's private) or language feature? how about a * following a function symbol.

2:23 (I don't mean *my-thing*, but rather my-thing*)

2:28 In other words, (defn- foo []) is analogues to (defn -foo [])?

2:29 heath: cross-posting we are

2:29 ban him! ;)

2:29 R_Macy: ha

2:33 got an answer to foo* thanks heath (http://www.cliki.net/naming%20conventions)

2:33 still trying to figure out -foo

2:34 heath: https://groups.google.com/forum/#!topic/clojure/rzvMp44ZN0I

2:34 R_Macy: ah so - signifies an entry point

3:19 hhenkel_: Is there a good way (other then multiple if clauses) to check for multiple values in a datastructure and fail if one is missing?

3:20 ambrosebs: hhenkel_: what kind of datastructure?

3:21 hhenkel_: usually (every? pred coll) works well

3:22 hhenkel_: ambrosebs: a simple map...i'll check "every".

3:23 ambrosebs: hhenkel_: clojure.set has lots of tools that are probably useful too.

3:23 hhenkel_: ambrosebs: how would I notify a user what explicit value is missing there?

3:23 ambrosebs: hhenkel_: (set/difference (set expected) (set actual))

3:24 \

3:25 hhenkel_: ambrosebs: Ah, that looks exactly like what I've been looking for. Thanks!

3:26 aaelony_: trying to understand the monoid function and why (clojure.core.reducers/fold (clojure.core.reducers/monoid max #(Double/NEGATIVE_INFINITY)) (clojure.core.reducers/map inc (range 10))) works but (clojure.core.reducers/fold (clojure.core.reducers/monoid (juxt min max) #(Double/NEGATIVE_INFINITY)) (clojure.core.reducers/map inc (range 10))) does not....

3:26 ambrosebs: hhenkel_: keep in mind the set ops don't do input validation, it's up to you to ensure you only pass sets.

3:29 hhenkel_: ambrosebs: Yes, thanks, that's a good hint.

3:49 ambrosebs: What is a MetaExpr in the Compiler.java?

3:54 borkdude: yay, my Emacs.app is finally working from brew, using the same live pack as from my other machine :) thanks for the help yesterday evening

3:54 chord: what projects are you guys working on?

3:57 anyone there?

3:59 ucb: hey chord

4:00 chord: we should work on starcraft clone written in clojure

4:00 you gonna help?

4:01 ucb: nah, no time

4:01 thanks for the offer though

4:02 chord: no time what?

4:02 wtf you wasting your time on

4:02 ucb: heh

4:02 nice try

4:03 chord: tell me what you're using your time on?

4:04 so you're doing nothing

4:04 tons of free time?

4:05 borkdude: spending time on nothing can be very nice, meditation

4:05 it's actually very difficult to do it

4:25 * yogurt_truck can never do that

4:29 chord: someone talk

4:29 channel is totaly dead

4:32 muhoo: in nrepl.el, is there some way to be able to hit RET on a line in an nrepl error stack trace and go to that line in the file?

4:32 cause i'm sure tired of doing it manually :-/

5:14 zzzzzz http://www.youtube.com/watch?v=ypKP1BvRZaM

5:25 hhenkel: Why do I get an "IllegalArgumentException Duplicated Key" if I alter the example from http://clojuredocs.org/clojure_core/clojure.core/merge to have to keys "b" ?

5:26 The text states that this case would be handlet, doesn't it?

5:27 fredyr: the example already has two :b keys doesn't it?

5:27 did you add two inside of the map literal perhaps?

5:28 clgv: ,(merge {:a 1 :b 2 :c 3} {:b 9 :d 4 :b 20})

5:28 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Duplicate key: :b>

5:28 clgv: that?

5:28 clojurebot: that is dumb

5:28 clgv: lol

5:28 ucb: heh

5:28 fredyr: hah

5:28 clgv: yeah, that's what i meant

5:28 clgv: ,{:b 9 :d 4 :b 20}

5:28 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Duplicate key: :b>

5:28 clgv: &{:b 9 :d 4 :b 20}

5:29 oh that one is lazy again

5:29 fredyr: hhenkel: there was a discussion about modifications concerning that behavior on the ML - but I do not recall what they decided finally

5:30 hhenkel: fredyr: You're right my fault....I have to be more attentive...

5:30 fredyr: :)

5:30 easy thing to miss

5:32 clgv: hhenkel: fredyr: https://github.com/clojure/clojure/blob/master/changes.md#210-set-and-map-constructor-functions-allow-duplicates

5:32 fredyr: clgv: at least python does allow it -- prolly more of the dynamic languages

5:33 clgv: fredyr: the above notes describe the distinction between literal and constructor functions

5:36 fredyr: ,(hash-map :b 1 :a 9 :b 9)

5:36 clojurebot: {:a 9, :b 9}

5:37 fredyr: seems like a pretty good choice

5:38 djcoin: Anyone know how to have the doc of some functiosn in lighttable ? (is it possible to have a nice dialog box somewhere to show the doc when hitting some keys ?)

6:33 hashcat: I wrote ((fn [x y] '(+ x y)) 10 20) and expect it return '(+ 10 20), but it give me '(+ x y)

6:34 How can I replace symbols in list?

6:34 llasram: &((fn [x y] `(+ ~x ~y)) 10 20)

6:34 Oh, no lazybot

6:34 ,((fn [x y] `(+ ~x ~y)) 10 20)

6:34 clojurebot: (clojure.core/+ 10 20)

6:35 hashcat: Thanks

6:35 llasram: hashcat: OOC, what's the higher-level thing you're trying to achieve?

6:36 hashcat: llasram, play with genetic programming

6:37 llasram: Interesting

6:37 hashcat: I'm planning to implement it on distributed system

6:39 I'm reading avout and swarmiji for that

6:50 wei_: compojure's (response/file-response "index.html" {:root "resources/public"}) doesn't seem to work inside an uberjar. is there a workaround?

7:04 to answer my question above: (response/file-response (.getPath (clojure.java.io/resource "public/index.html"))) works inside an uberjar

7:04 muhoo: hmm this seems a stupid name for this function. and doesn't it already exist somehwere under a better name? (defn munge-map-vals [f m] (zipmap (keys m) (->> m vals (map f))))

7:05 ambrosebs: muhoo: probably should be called update-vals

7:06 muhoo: it's probably around in some utility libs.

7:06 clgv: muhoo: yeah update-vals would be better and using reduce-kv to build the new map faster

7:10 wei_: ^ oh wait, actually it doesn't work inside an uberjar :(

7:12 llasram: muhoo: I've seen a similar function named `map-vals` in a few places, including prismatic's plumbing

7:14 muhoo: thanks

7:16 ah https://github.com/bendlas/plumbing/blob/master/src/plumbing/core.clj#L32

7:17 mrchance: hi! how do I read all forms from a file? Do I really have to create a PushbackReader, read from it in a loop and wait for exceptions?

7:17 muhoo: i wonder how many clojure utility libraries there are out there. one for every clojure programmer, maybe?

7:17 (hell, i have one)

7:17 llasram: mrchance: You can provide a value to return on EOF vs exception, but otherwise -- yes

7:18 mrchance: wow, that is pretty bad. Better than nothing though. Thanks!

7:19 @muhoo: I have one too, and every other clj programmer I know does as well

7:19 llasram: mrchance: Well, but your loop can be just (->> (repeatedly ...) (take-while ...))

7:19 mrchance: :)

7:19 muhoo: ooh neat (fn-> foo bar) instead of #(-> % foo bar)

7:19 clgv: mrchance: you could only have one clojure form in that file though - vector or map, containing everything

7:19 mrchance: @llasram: yeah, it's not that bad

7:19 TEttinger: couldn't you just eval?

7:19 mrchance: @clgv: I want to analyse cljs files to autoextract externs

7:20 So no single form per file

7:20 llasram: mrchance: BTW, on IRC one generally doesn't prefix people's handles with `@` -- the convention is to just refer to their name by itself

7:20 clgv: ah ok^^

7:20 might have been a config file scenario ;)

7:20 mrchance: good to know ^^ pretty new to it

7:21 muhoo: a lot of people are used to the twitter machine instead

7:22 mrchance: Hehe, I actually don't use that, don't know what part of my brain produces the @s

7:22 Maybe subconcious twitter influence

7:22 clgv: hmm the for-map of plumbing seems pretty non idiomatic using the atom

7:23 mrchance: ah, speaking of non-idiomatic: I want to use clojure.walk to extract the symbols

7:24 clgv: mrchance: maybe the macro expansion walking from zach tellmann or the one of tools.reader is a better fit

7:24 mrchance: hm, yeah

7:24 the clojure.walk only seems to have rewrite capabilities

7:24 little strange to rewrite the datastructure itself to extract something

7:24 clgv: but it will delete emtadata

7:25 mrchance: thats no problem for me

7:25 clgv: ok.

7:25 oh, you just want to walk the code unexpanded?

7:26 mrchance: hm, maybe expanded would be nicer, but I see that could be problematic with cljs

7:27 Guess interfacing to verbose js libs would be a common usecase for macros

7:28 well, I just need a list of all extern functions and members, so I guess I could just process the macro definitions as well

7:30 it's really ugly that we have to do the externs by hand

7:30 Does anyone know of a project to address this?

7:32 hashcat: llasram: I found a better solution

7:33 (cons 'fn (cons '[x y] '((+ x y)) ))

7:34 mrchance: hi ejlo ^^

7:35 clgv: hashcat: you can just build lists normally. no need to use lowlevel cons. equivalent to your above expression: (list 'fn '[x y] '(+ x y))

7:35 hashcat: then I can manipulate the list and eval it during run-time

7:35 clgv: Thanks

7:36 `(+ ~x ~y) is not going well during run-time

7:37 clgv: hashcat: for fixed templates it should be suitable

7:37 hashcat: clgv: I agree

7:38 clgv: ,(let [x 'a, y 'b] `(+ ~x ~y))

7:38 clojurebot: (clojure.core/+ a b)

7:41 tgoossens: Is there a clean way (in existing library) to do this (completely conceptual): (map [:name :country] persons)

7:41 instead of (map #(vector (:name %) (:country %)) persons)

7:42 (i'm just searching a more concise notation for doing the described concept)

7:43 AimHere: If there's no pressing reason to call your function 'map', you could knock up a tiny little macro or function to do it

7:43 andrewmcveigh|wo: tgoossens: (map (juxt :name :country) persons)

7:43 tgoossens: interesting

7:43 AimHere: Or what he said

7:43 tgoossens: fantastic

7:44 i need to google that (juxtaposition)

7:44 andrewmcveigh|wo: yep, can be very usefull ;)

7:44 tgoossens: amazing

7:44 thanks a lot

7:45 andrewmcveigh|wo: np

7:50 seangrov`: I'm thinking about a cljs helper function for error reporting, maybe extending errbit to support this:

7:51 hashcat: is there any alternative to default clojure intepreter?

7:51 direction keys behave silly

7:52 seangrov`: Catch the error, send it to your error-reporting service, along with some metadata about what version of your code you're using - then the error-reporting service looks up the source map for the given version (that you've uploaded as part of your deploy process), and all errors are reported in original line numbers/symbols

7:52 It's got to be the obvious next evolution of airbrake/rollbar/errbit and friends, but I don't think any support this properly right now

7:53 Proxino was going to do it, but I don't know what their status is

7:57 I guess rollbar does support it, actually

7:57 Should check it out

8:51 ciphergoth: When using lein repl :connect to a URL, you can authenticate by putting the username and password in the URL. Is there any other way to provide the username and password?

8:59 emil0r: does anyone know how to make the lobos library correctly migrate migrations defined in another project that is in one of your dependencies? i've already tried to redefine lobos.migration/*migration-namespace* and it's not working when it's from a dependancy. works fine as long as it's inside the project itself

9:38 borkdude: yep, juxt

9:46 clgv: hashcat: what do you mean? the repl? there is leiningen which offers a pretty decent repl via `lein repl`

10:07 mikerod: where could I find the performance properties of doing something like (conj (sorted-set :e :d :c) :a) ?

10:08 I haven't came across much information on how "insertions" work on these sorted data structures

10:09 ambrosebs: mikerod: I don't know, but conj is supposed to be the fastest way to do it.

10:11 mikerod: ambrosebs: Hmm I see. I could analyze the source for a while I suppose. I guess I'd assume it is a "fairly" efficient mechanism, as opposed to just resorting a whole new collection.

10:11 That much is obvious after a quick glance.

10:11 ambrosebs: mikerod: all of Clojure's data structures use structural sharing to some degree.

10:11 hyPiRion: sorted-sets are just persistent rb-trees afaik, they have O(log n) time complexity for insertion

10:12 mikerod: ambrosebs: yeah that is a good point.

10:12 hyPiRion: thanks, it does look like the are rb-trees

10:18 ciphergoth: I'm trying to use "lein repl :connect https://..." to connect to a Heroku instance. It prints "Connecting to nREPL at https://..." and then hangs. When I ^Z and kill it, it prints "Welcome back!" before it dies. How can I diagnose what's going on?

10:20 aatifh: Hi, has anyone ever tried django xadmin(https://github.com/sshwsfc/django-xadmin) and managed to run it successfully? I really liked the themes and plugins but facing some issues. Thanks in advance.

10:21 Humble apology. Wrong channel!

10:33 ambrosebs: Bronsa: should jvm.tools.analyzer reset the current namespace to clojure.core or user (or similar) before analyzing a file?

10:33 Bronsa: how does CinC handle it?

10:34 dnolen: ambrosebs: fwiw in CLJS we reset to cljs.user

10:35 ambrosebs: dnolen: ok. That's good enough for me.

10:35 Bronsa: ambrosebs: Compiler.java only relies on the current value of *ns* and so does CinC

10:35 ambrosebs: Bronsa: hmm ok :)

10:35 clj_newb_2345: if I have 1 quad-core Xenon, the JVM can use all 4 cores. If I have 2 Quad-Core Xenon on Ubnutu Linux, does the JVM use all 8 cores, or is each "linux process" limited to just 1 CPU?

10:36 ambrosebs: Bronsa: I find the ns form is usually in some random namespace after I analyze a file.

10:36 dnolen: ambrosebs: CLJS is a bit odd if we ever intend to support (load-file ...)

10:36 ambrosebs: dnolen: yes, I just considered that.

10:37 Bronsa: ambrosebs: what do you mean?

10:38 ambrosebs: fwiw clojure special-cases the resolution of `ns` to clojure.core/ns

10:38 ambrosebs: Bronsa: I mean the :env of the first form that's analyzed claims it's from the current namespace.

10:38 Bronsa: which is a bit odd.

10:40 Bronsa: well, if *ns* is user and you encounter (ns foo), the form (ns foo) is effectively in the user namespace

10:42 ambrosebs: Bronsa: yes. Is that how load works in Clojure?

10:42 Bronsa: ambrosebs: yeah, it just evals all the form of the file in the current ns

10:43 ambrosebs: it doesn't sound like something I need to worry about then.

10:43 clgv: clj_newb_2345: you can use all cores

10:43 clj_newb_2345: even across different CPUS?

10:43 linux + java just handles this for me behind the scenes?

10:43 jtoy: how does one redeploy with ring and not have the site hang while its deploying? on rails for example you can let teh old process contineu to run until the new one is fully up

10:43 clgv: your operating system linux does it

10:43 jtoy: with ring I kill the old process, then start the new process, that is at least 30 seconds on my box

10:48 clgv: jtoy: the technical problem is the exclusive use of the port right?

10:50 jtoy: you could have a "facade process" on the actual port that forwards to your application. when you make the target application configurable you can let the old one running, start the new one, switch and kill the old one

11:01 TimMc: It's called a reverse proxy.

11:03 clgv: TimMc: ah thx ^^

11:04 jtoy: clgv: is there any library that does this already?

11:05 clgv: jtoy: no idea.

11:05 arrdem: jtoy: what are you proxying? http?

11:06 TimMc: You can even see some repeat prefixes: Kingmaxj1w6 Kingmaxm3o8 Helloxaod97 Hellodgjm30

11:06 Bah, wrong channel.

11:06 jtoy: arrdem: yes htttp, I do have nginx in front currently

11:06 arrdem: jtoy: nginx can do some selective proxying, but I've also used clj-proxy

11:08 jtoy: arrdem: ist caleld selective proxying?

11:08 arrdem: jtoy: I don't remember, but it's in the sample configs site

11:08 jtoy: ok, thanks

11:11 arrdem: I dont see anything called clj proxy, is it a different library?

11:13 arrdem: jtoy: sorry I always get the name wrong. it's ring-proxy.

11:13 $google ring-proxy

11:13 * arrdem glares at the bots

11:14 arrdem: jtoy: this https://github.com/tailrecursion/ring-proxy

11:15 jtoy: I'm sure that nginx is impericaly faster, but that's really easy to get running.

11:20 jtoy: arrdem: yeah, i will probably use nginx, i just wanted to see how it would work through pure clojure

11:20 silasdavis: how do you test if a value is callable?

11:21 arrdem: silasdavis: &(fn? #(:foo %1))

11:21 mdrogalis: ,(doc ifn?)

11:21 clojurebot: "([x]); Returns true if x implements IFn. Note that many data structures (e.g. sets and maps) implement IFn"

11:21 silasdavis: thanks

11:21 mdrogalis: I *think* IFn <-> Callable ?

11:21 arrdem: ,(doc fn?)

11:21 clojurebot: "([x]); Returns true if x implements Fn, i.e. is an object created via fn."

11:22 silasdavis: mdrogalis, so all methods are nil-returning IFns?

11:23 uhm 'pure methods' I mean

11:26 mdrogalis: silasdavis: Eh?

11:26 Confused :)

11:26 arrdem: ,(cannuc? 'mdrogalis)

11:26 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: cannuc? in this context, compiling:(NO_SOURCE_PATH:0:0)>

11:27 silasdavis: I'm wondering about whether a void java method would implement IFn in clojure

11:27 mdrogalis: arrdem: No sir. :)

11:27 silasdavis: or whether only explicit implementers of IFn would

11:27 mdrogalis: silasdavis: No, I'm afraid not.

11:27 Yeah, the latter.

11:28 silasdavis: in which cast callable != IFn

11:28 mdrogalis: Must be the latter then.

11:29 silasdavis: (I was only actually after ifn? in this case anyway)

11:29 mdrogalis: Ah, try this.

11:30 ,(instance? java.util.concurrent.Callable inc)

11:30 clojurebot: true

11:30 mdrogalis: That should do it.

11:38 manutter: Are there any libs that let you set up arbitrary events, register handlers, and then trigger the events? I'm thinking server-side, not anything javascripty

11:45 egghead: manutter: you wight want to check out rxjava for clj, or core.async

11:46 manutter: Thanks, I've looked at core.async but not rxjava, I'll check it out.

11:47 I'm working on something similar, I'm just checking for other libs that might overlap with what I'm doing.

11:48 egghead: ah, then you might want to also look at lamina

12:04 BlankVerse: how do I reload a clojure android app in repl(using lein droid)

12:07 manutter: egghead: cool, thanks much. Gonna look at lamina some more in any case. :)

12:07 clgv: if I have a long running process in a thread that prints to stdout which is sent from nrepl server to my nrepl client. after the client disconnects, does the nrepl server still attempt to send the output to the client?

12:09 ok the answer is, it dies with socket closed exception...

12:23 BlankVerse: (use 'foo.bar :reload-all) should reload and display changes made to foo.bar..

12:24 (use 'org.stuff.clojuroid.main :reload-all)

12:24 nil

12:24 should it return nil?

12:25 (load-file "src/org/stuff/clojuroid/mail.clj")

12:25 ErrnoException open failed: ENOENT (No such file or directory) libcore.io.Posix.open (Posix.java:-2)

12:33 clgv: BlankVerse: yes, it should return nil

12:45 BlankVerse: clgv: it means the module is reloaded?

12:45 clgv: BlankVerse: there will be exceptions if something went wrong

12:45 BlankVerse: clgv: on the repl?

12:46 or logcat

12:46 clgv: BlankVerse: tools.namespace is a library that tries to do proper reloading

12:46 I dont know what logcat is

12:47 ,(let [f (fn [] (throw (Exception.)))] (f))

12:47 clojurebot: #<Exception java.lang.Exception>

12:47 BlankVerse: its android logger , my clojure repl is running on android and I am trying to reload my clojure app from repl

12:47 clgv: looks similar to this ^^ in the repl ;)

12:47 BlankVerse: clgv: ok, this comes when i do (load-file "src/org/stuff/clojuroid/mail.clj")

12:48 clgv: BlankVerse: oh, I never used clojure on android. in normal clojure you'd usually see the exception reported in the repl

12:49 moquist: lein says "Could not reserve enough space for object heap / Could not create the Java virtual machine." googling gave me "-d64 -XX:MaxHeapSize=256m" opts for java, and that works if I already have a .jar. But now 'lein uberjar' gives me the same message, and adding ':jvm-opts ["-d64" "-XX:MaxHeapSize=256m"]' to my project.clj didn't help... I'm not sure what to try next.

12:49 coventry2: BlankVerse: I notice that you have "(use 'org.stuff.clojuroid.main)" in your first form, but are loading mail.clj in the second one. (Might be behind; I was reading from the IRC log.)

12:51 moquist: Try running "DEBUG=true lein uberjar" to make sure the options are getting passed through.

12:51 moquist:

12:51 oops, wrong window focused...

12:52 coventry2: that just told me "Leiningen's classpath: :/home/moquist/.lein/self-installs/leiningen-2.1.2-standalone.jar", in addition to the same message

12:53 BlankVerse: coventry2: ah thanks a lot!

12:53 moquist: coventry2: I'm assuming lein doesn't get as far as reading project.clj, since the JVM never starts.

12:54 coventry2: Yeah, I guess so.

12:54 BlankVerse: now , it give java.lang.ClassNotFoundException: complete.core

12:54 moquist: coventry2: FWIW: http://pastebin.com/qS0VE3f6

12:55 coventry2: moquist: Try passing the opts in the env var LEIN_JVM_OPTS.

12:55 moquist: coventry2: YAY! That's what I was looking for.

12:55 I was looking around for java env vars, but didn't look for lein env vars.

12:56 coventry2: many thanks.

12:56 coventry2: lein is just a bash script. Easy to read.

12:56 * moquist nods

13:09 `cbp: If I have a defprotocol on namespace A, a defrecord + extend-type on namespace B, and I wanna use those methods on namespace C what do I have to import/require?

13:09 This is confusing me so much :P

13:14 maleghast: Anyone know how to set up a Clojure / Compojure web app to treat all strings as UTF-8..?

13:14 mdrogalis: `cbp: I believe you need to require the protocol from A, and important the defrecord from B.

13:14 mtp: maleghast: what are the defaults?

13:15 maleghast: I am unsure, but the app in question is receiving UTF-8 text and mis-rendering it

13:17 `cbp: I am requiring the protocol + method from A, requiring B, importing the defrecord from B and it's not working :P

13:17 justin_smith: `cbp: I think it is import a, require b

13:18 since a definies the java thing (the protocol), and all you need from b are functions that create the records (so require suffices)

13:19 `cbp: extend-type puts the record methods on the namespace that created has the defprotocol though

13:23 maleghast: mtp: I have to log off in a couple of minutes… Thanks anyway, I'll do some Googling ;-)

13:23 slpsys_: part

13:23 amalloy: maleghast: utf-8 is the default character encoding when java converts bytes to chars/strings

13:24 your app is probably receiving text encoded in some other way, not utf-8

13:24 or serving it right and your browser is mis-rendering it

13:24 maleghast: amalloy: ok, the payload I'm getting is serialised with MessagePack - I will look there...

13:26 justin_smith: `cbp: http://sprunge.us/iHZH?clojure minimal example I just cranked out of how to do it

13:26 you use ns.protocol in the defstruct ns/protocol-method to invoke it

13:30 mheld: is there an analogous command for lein/compojure to 'rake routes' in the ruby/rails world?

13:31 weavejester: mheld: Remind us what that does :)

13:32 mheld: weavejester: tells us what routes are defined

13:32 weavejester: mheld: In that case, no, at least not in Compojure's case. The routing mechanism for Compojure is very flexible, but essentially opaque.

13:33 indigo: mheld: Ah, using Clojure for web as well? ;)

13:34 weavejester: I think there is room for a routing library that's data-based. One that could be queried, but one that's less flexible than Compojure.

13:34 Pedestal has something like that, but I don't think it's a separate library.

13:35 mheld: indigo: yeah!

13:35 weavejester: over time, I do wish to contribute to the web-ness of clojure but for now I just need to finish this project ;-)

13:39 `cbp: justin_smith: thanks I have something wrong but I dont know what :P

13:41 justin_smith: `cbp: was the example I pasted unclear?

13:41 I guess I didn't have the requires and imports

13:42 `cbp: justin_smith: I tried it on a repl adding the requires and imports as I have them and it works so that's why I don't know what's wrong :P

13:42 indigo: mheld: Yeah I'm just getting started in it... it's such a relief after what I do at work

13:42 justin_smith: a.Foo would be imported, a/bar and b/->baz would be required

13:43 dobry-den: rasmusto: Dude this is great. ~/dotfiles with a `make link`.

13:43 rasmusto: dobry-den: <3

13:44 `cbp: justin_smith: import doesnt work on defprotocol

13:44 rasmusto: dobry-den: glad it worked for you :)

13:49 mheld: why is it so hard to figure out how to accept JSON with my clojure app!?

13:50 god damn it

13:50 Apage43: accept json?

13:50 konr`: what framework are you using?

13:50 augustl: mheld: cheshire.core/parse-string? :)

13:50 Apage43: ^^

13:51 justin_smith: mheld: there is also a ring middleware for incoming json

13:51 augustl: or parse-stream

13:51 mheld: justin_smith: I've been trying to use it but alas, none of the json gets parsed

13:51 augustl: mheld: what exactly is the problem?

13:51 mheld: I'll poke around with cheshire

13:51 augustl: note that most servlet containers expose the :body as a read once stream

13:51 mheld: ^^

13:52 dobry-den: why use chesire instead of just clojure.data.json/read-str

13:52 justin_smith: `cbp: user> (import (a Foo)) => a.Foo

13:52

13:52 Apage43: if you're using the middleware, it'll only take effect if you send stuff as Content-Type: application/json (or similar)

13:52 justin_smith: dobry-den: clojure.data.json is terrible

13:52 dobry-den: justin_smith: in what way?

13:52 seangrove: Seems like a complicated way to tokenize + parse https://github.com/AdamBrodzinski/RedScript/blob/master/lib/compile.js

13:52 ro_st: justin_smith: are you sure? stuartsierra has worked on it recently

13:52 justin_smith: dobry-den: the api is unstable

13:52 konr`: clojure.data.json can't serialize dates, uuids etc

13:53 ro_st: konr`: isn't that true of JSON generally?

13:53 mheld: curl -X POST localhost:3000/pingbacks -d{hi:'marc'} -> (POST "/pingbacks" {body :body} (create-pingback body)) doesn't return anything (create-pingback is just an identity function right now)

13:53 Apage43: curl -X POST -H "Content-Type: application/json"

13:53 technomancy: ro_st: there's no standard way to do it, but that shouldn't mean it's impossible

13:54 mheld: Apage43: that did it

13:54 ro_st: what i mean is, JSON doesn't support like edn does

13:54 mheld: Apage43: gracias

13:54 justin_smith: ro_st: I have seen cheshire be much more sensible with data coercions than data.json

13:54 konr`: ro_st: yes, but cheshire can transform an UUID into its string without much hassle

13:54 ro_st: you have to roll your own

13:54 Apage43: and whatever other doodads you hit that API with should have ways to set the request body content type as well

13:55 justin_smith: ro_st: roll your own, or just use cheshire who rolled it for you

13:55 `cbp: justin_smith: it tells me "interface a.Foo is not a protocol" when I try to import

13:55 technomancy: of course the idea of keeping a UUID around as a separate type distinct from strings in your codebase itself is fairly suspect anyway unless you're concerned about memory usage

13:55 ro_st: wasn't aware chesire added that

13:56 augustl: stringly typed programs ftw :)

13:56 ro_st: heh

13:56 Apage43: the nice thing about cheshire is you can extend it

13:56 ro_st: we're lucky enough to use EDN everywhere

13:56 Apage43: so if you have some wacky type buried in a big nested map, you can just teach cheshire about the type rather than try to fix it on the way in

13:57 jtoy: can anyone tell me why when I run this code, it never prints out and results is always an empty list: https://www.refheap.com/18767

13:57 ro_st: that's handy

13:57 jtoy: I know it has to do with laziness, but im not sure how to fix it

13:57 `cbp: curse clojure error messages :(

13:57 ro_st: jtoy: wrap (for) in (doall)

13:57 nothing consumes the result of the for and so the laziness is never realised

13:58 or do thing (for ..)] (println thing) ...

13:58 konr`: ro_st: what do you use on the front-end?

13:59 ro_st: cljs :-)

13:59 jtoy: ro_st later on in my code I do run (/ (reduce + (map :precision results) ) k) which should realize it?

13:59 dobry-den: in a real app youd consume `results`. so id just wrap (doall results) temporarily to see it

13:59 konr`: any specific library/framework?

13:59 amalloy: ro_st: if results is empty, wrapping it in doall won't make a difference

13:59 ro_st: konr`: a shoreleave-pubsub + enfocus lashup

14:00 dobry-den: yeah that's a good point, wouldnt it be LazySeq if that was so

14:00 ro_st: next iteration will be a pedestal app

14:00 amalloy: true

14:00 konr`: cool! I've been trying to push cljs here as well :)

14:00 ro_st: konr`: the awesome bit is really reusing code server/client

14:01 the same code that produces the data on the client also consumes it on the server

14:02 justin_smith: `cbp: can you paste a simple repl session that creates the error you are getting?

14:02 konr`: using shoreleave, right?

14:02 any specific reason you are trying pedestal-app?

14:04 augustl: angular and ember has shown that separating generating data to represent UI state and updating DOM elements is awesomesauce. Pedestal works similarly, except clojure, and with great architecture, and functional :)

14:05 ro_st: konr`: pedestal-app is a slam dunk for our app

14:06 it does properly the things that i ended up doing (very) naively in our current app

14:06 event sourcing user data, using queues to ship data back and forth, etc

14:07 i just did it badly because i used loads of atoms and pubsub and essentially made some clojure spaghetti :-)

14:08 still, it's only 2k loc of spaghetti instead of the 11k of google closure spaghetti i had written before finding clojure

14:09 noncom: if i do (spit "some-file.file" (str "hello\nhow\nare\nyou?)), the resulting file contains the string like it is here, with the \n characters in it. how do I make them into real newlines?

14:09 `cbp: justin_smith: ... lol

14:10 AimHere: noncom > You sure? It works the way you intend it to, for me

14:11 konr`: noncom: strange, (spit "/tmp/foo" (str "hello\nhow\nare\nyou?")) did create a file with newlines here, too

14:11 `cbp: justin_smith: Apparently I had an error somewhere else and the protocol cache (didn't know about that) never updated so it never found the methods I defined. I did lein clean after fixing that other error and everything starts working -_-

14:11 noncom: hmmm, maybe it's because you're on linux and i am on windows?

14:11 AimHere: How are you reading the file?

14:11 noncom: windows uses \n\r

14:12 i am not reading, i want to write a string to a new file

14:12 AimHere: I think it's \r\n, but it's been a while

14:12 Yeah, but it might be that the way you're reading the file is turning the 'newlines back into '\n's

14:12 The windows thing is more likely though

14:13 `cbp: justin_smith: thanks for your help :P

14:13 noncom: oh i just open it with an editor..

14:13 justin_smith: `cbp: I think maybe some stuff technomancy has been doing with trying to reduce startup time has been making lein clean more neccissary. That's just speculation on my part though. Maybe I am doing more protocol and macro changes than usual lately.

14:14 callen: `cbp: stop using protocols unnecessarily :P

14:14 justin_smith: `cbp: no prob

14:59 mdeboard: Anyone else in this datomic deal at strangeloop

14:59 please stand up and announce yourself

15:01 konr`: what datomic deal?

15:01 mdeboard: datomic intro session

15:02 callen: so. jealous.

15:02 not only is Rich talking about core.async, but there's a datomic session? :(

15:11 That sad, sad moment when you realize you're going to have to write a manual loop/recur instead of using clojure.walk/walk for your problem. http://i.imgur.com/wQPAsdN.gif

15:24 bracki_: How do I look up docs on thing like # or @?

15:25 mdrogalis: bracki_: Those symbols are sugar for dispatch-macro and deref.

15:26 bracki_: Also, the dispatch macro, being a reader macro, is a little special. It doesn't have a ClojureDoc bit associated with it.

15:26 Bracki: So what is the dispatch-macro useful for?

15:27 coventry: Bracki: You can get the nomenclature for them out of tools.reader: https://github.com/clojure/tools.reader/blob/master/src/main/clojure/clojure/tools/reader.clj#L543

15:27 mdrogalis: Bracki: Utilizing the Lisp Reader.

15:27 Bracki: mdrogalis: what?

15:27 mdrogalis: Control+f for Dispatch (#) http://clojure.org/reader

15:29 Bracki: So take #'f for example. All it does is expand to (var f). Why is that useful?

15:31 mdrogalis: Bracki: That's really just sugar. It becomes useful when you want to extend Clojure itself.

15:31 The quote after the hash is meaningful.

15:31 I can put another character after the hash and make it mean whatever I want.

15:31 #(inc %) <- The ( after the # is significant, in the same manner.

15:31 coventry: mdrogalis: I thought clojure doesn't really have reader macros.

15:32 mdrogalis: coventry: It has one, but it doesn't support user defined reader macros.

15:32 Just one extensible one.

15:33 coventry: Can you give an example of giving whatever character follows # an arbitrary meaning?

15:33 TimMc: data-readers

15:33 But it doesn't have the kind of control you're thinking of.

15:33 mdrogalis: ,#uuid "803e1294-c4bd-4c89-bbbf-501f992caffb"

15:33 clojurebot: #uuid "803e1294-c4bd-4c89-bbbf-501f992caffb"

15:34 mdrogalis: #xxxxuuid "803e1294-c4bd-4c89-bbbf-501f992caffb"

15:34 UUID is defined too.

15:34 The xxx one failed because thats not defined.

15:34 coventry: Oh, OK, I thought you meant something more general than that.

15:34 TimMc: No, it failed because you forgot the comma. :-P

15:34 mdrogalis: TimMc: lolol *Facepalm* Nice.

15:34 TimMc: ,#xxxxuuid "803e1294-c4bd-4c89-bbbf-501f992caffb"

15:34 clojurebot: #<RuntimeException java.lang.RuntimeException: No reader function for tag xxxxuuid>

15:34 mdrogalis: Thanks

15:34 Warning: Fatigue has indeed set in.

15:35 seangrov`: ,#{1 1 1 1 1 1 3 3 3 3 2}

15:35 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Duplicate key: 1>

15:37 Bracki: ,#'

15:37 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

15:37 Bracki: ,#'partial

15:37 clojurebot: #'clojure.core/partial

15:38 * Bracki confused

15:38 mdrogalis: #' is sugar, no meaning on its own.

15:38 `var`, on the other hand, does.

15:39 seangrov`: ,(var partial)

15:39 clojurebot: #'clojure.core/partial

15:39 Bracki: ,(doc var)

15:39 clojurebot: I don't understand.

15:39 seangrov`: It's just common(-ish) to want to grab vars, hence there's a built-in reader macros to make the syntax more terse

15:40 bja: is there a way to determine what namespace I'm running in for my clojurescript code?

15:40 seangrov`: bja: Namespaces aren't available at runtime in cljs, sadly

15:40 Bracki: When do I need vars?

15:40 seangrov`: I'm not totally clear why not, if it's just an implementation detail or it's fundamentally not possible

15:41 bja: is there a way I could find out where I'm running (or what required me) from google closure library?

15:41 Bracki: http://clojure.org/special_forms#Special Forms--(var symbol) is not very helpful.

15:42 seangrov`: bja: What are you trying to do?

15:42 bja: figure out the namespace my function is in for logging purposes

15:42 seangrov`: Ah, well, there's *ns* in clojure, but not clojurescript, I believe

15:44 coventry: I wonder if you could just persuade the cljs ns macro to drop a *ns* var in the specified namespace.

15:45 seangrov`: coventry: Interesting idea!

15:48 I don't know what *ns* offers in clj-jvm though, I suppose it may have some special properties that js objects don't have

15:51 timsg: anyone use org-babel much? the documentation's a bit weird, I'm trying to figure out how to eval source blocks that contain noweb refs

15:52 dnolen: timsg: probably more responses to that question in #emacs

15:54 timsg: dnolen: yeah, I'll look there

16:00 AimHere: Hmm. Being a good little functional programmer, I want to send a function as a parameter to a method in a class declared using gen-class, but apparently I have to declare the arguments beforehand; Since (class <function name>) returns just the name of the function, that's not really useful. Is there a way of doing this that I've missed, or will I have to use some clunky workaround?

16:01 coventry: seangrov`: People might expect (binding [*ns* ns] foo) to execute foo in ns, which might be bad.

16:01 `cbp: Is there a way to clear the protocol method cache? :(

16:04 freaking protocols just lead to madness and despair

16:05 TimMc: AimHere: The function will be called from Clojure?

16:05 AimHere: Yeah

16:05 TimMc: You could describe it as a Fn, or even just an Object.

16:06 Apage43: ,(supers (fn []))

16:06 clojurebot: #<ClassCastException java.lang.ClassCastException: sandbox$eval29$fn__30 cannot be cast to java.lang.Class>

16:06 muhoo: `cbp: it seems less janky on cljs

16:06 Apage43: ,(supers (class (fn [])))

16:06 clojurebot: #{clojure.lang.Fn clojure.lang.AFn java.util.Comparator java.util.concurrent.Callable clojure.lang.AFunction ...}

16:07 muhoo: not sure why. maybe because then you're not fighting the jvm, i guess

16:07 AimHere: Phew, I was worried I might have to dig up some boneheaded java pattern to wrap the function in!

16:11 `cbp: Apparently I was requiring/importing in the wrong order or heck i don't know :P

16:11 I should write this down somewhere

16:38 squidz: would there be an easy way to export a csv file with clojurescript?

16:38 I dont' really want to add an additional library if I can keep it simple

16:41 nDuff: squidz: there's more to CSV than just comma separation -- there are quoting and escaping rules and such.

16:42 squidz: ...if you want something that really does it right, a third-party library is probably the right approach. If you just want to split lines by commas, well, that's trivial. :)

16:43 squidz: nDuff, it doesnt have to be fancy i will only have number values along with a header

16:43 dnolen: squidz: http://stackoverflow.com/questions/14964035/how-to-export-javascript-array-info-to-csv-on-client-side ?

16:43 squidz: and the first column will be text(kind of like a vertical header), but other than that everything will be numeric

16:44 thanks dnolen that is exactly what I was looking for.

16:46 rasmusto: is there a consensus on whether to keep example code in source clj files? I'd like to have good documentation in docstrings, but runnable snippets make sense too

16:47 Should I put (comment) blocks after the code I want examples for or use separate namespace (or something else)?

16:49 coventry: rasmusto: It's nice if you can make tests out of the examples.

16:51 hyPiRion: rasmusto: http://stevelosh.com/blog/2013/09/teach-dont-tell/

16:53 lpetit: hello

16:53 I have weird behaviors while using zippers

16:54 I don't know exactly how, but I've managed to get a loc whose node is nil, that's weird

16:56 dnolen: rasmusto: I think people generally try to avoid the clutter. I like it in the early stages of development.

16:57 rasmusto: coventry: Okay, I like the idea of unit tests that double as documentation

16:58 hyPiRion: will give it a read, I saw it a while back but didn't finish :)

16:58 amalloy: lpetit: what's weird about a nil node? depending on what kind of zipper you've defined, that's perfectly reasonable, right?

16:58 coventry: FWIW, it says that relying on tests for documentation is a terrible idea. :-)

16:59 rasmusto: dnolen: I have a bunch of namespaces that I gitignore that have fragments of my runnable code in them, I tried to keep them out of controlled files, but now I want to be able to share

17:00 dnolen: I also had the "benefit" of being the only one writing code in its early stages, so those snippets didn't need to be shared until now

17:00 dnolen: rasmusto: I don't see the point most people won't look at your source

17:01 lpetit: amalloy: well, yes, with my zipper, my guess is that it's not: https://gist.github.com/laurentpetit/6615228

17:01 rasmusto: dnolen: true, I think I'll go the teachable unit test route, which should benefit me personally in the long run

17:02 lpetit: amalloy: I think I should only get nodes which are Strings, or maps, a-la zip.xml map

17:02 Contemplating creating a t-shirt named "Zippers: you're doing it completely wrong", at least addressed to me ;-)

17:03 tbaldridge: lpetit: it doesn't help that zippers need to be re-written (using protocols). I said I'd do it once, never did.

17:03 lpetit: tbaldridge: never too late ;-)

17:20 crocket: Is there a good way to handle modularity in clojure?

17:21 tbaldridge: crocket: namespaces?

17:22 crocket: tbaldridge, namespaces don't solve modularity problem.

17:22 namespaces solve name collision problem only.

17:22 tbaldridge: please explain the problem you are trying to solve

17:22 "handle modularity" is too broad

17:22 hyPiRion: explaining what you mean by modularity would help

17:24 bja: fwiw, I figured out how to find my current namespace in clojurescript: https://gist.github.com/emidln/bd33d9c0b40d20f60508

17:25 crocket: I have OSGi in mind when it comes to modularity.

17:29 tbaldridge: crocket: perhaps look into using queues with multiple servers/JVMs. Allows you to start/restart/update nodes on the fly without taking down other parts of the system

17:30 crocket: tbaldridge, queues?

17:30 Do you mean network queues?

17:32 tbaldridge: crocket: yes, kafka, ZeroMQ, RabbitMQ, etc.

17:32 crocket: tbaldridge, ZeroMQ is my bet.

17:32 tbaldridge: if you don't need reliable/durable message passing

17:32 crocket: However, using OSGi would be easier to work with than ZeroMQ in general.

17:33 tbaldridge: crocket: but it also is a slightly outdated model in which it is cheaper to put everything on one server. If that JVM/server dies, you loose everything and what good is modularity then?

17:33 crocket: tbaldridge, modularity still holds.

17:34 fault tolerance isn't the only benefit.

17:34 Being able to swap a module on the fly is good.

17:34 Being able to mix and match is good, too.

17:34 tbaldridge: crocket: not as good as being able to swap an entire server on the fly.

17:35 crocket: tbaldridge, I think OSGi and Message queue can be used together for maximal modularity.

17:35 What about akka?

17:36 tbaldridge: actor systems are like the system I described, but it attaches the queues to the processes. So if the process dies, you loose the queue.

17:37 crocket: tbaldridge, Why is OSGi a slightly outdated model?

17:38 tbaldridge: The old model assumed that you would run monolithic servers in-house. These days with AWS and other cloud services, it's not uncommon to run many small VMs. With smaller VMs you can start/stop the entire machine at will.

17:38 no need for all the overhead/complexity of a module system.

17:39 Even then, some companies these days will kill the entire VM (even delete the disk) on a software upgrade.

17:39 crocket: tbaldridge, You're talking in terms of administrator.

17:39 That's valid case.

17:40 However, in developers' point of view, code modularity can be harder with ZeroMQ.

17:40 tbaldridge: or even on a hour by hour basis, see Elastic Bean Stalk, the load balancer has the power to kill/start nodes as the load on the cluster changes

17:40 *Beanstalk

17:40 crocket: why do you need code modularity?

17:41 crocket: tbaldridge, coders need code modularity.

17:41 tbaldridge: why?

17:41 clojurebot: http://clojure.org/rationale

17:41 tbaldridge: thanks clojurebot

17:41 crocket: non-modular code is difficult.

17:42 tbaldridge: Right, that's where namespaces come in, imo. Or even in-process queues like core.async. Functional programming also helps as each function is isolated from the state of the system.

17:42 It's also very common in Clojure to split out your system into many smaller libraries, that helps as well. No need for a complicated module management system.

17:42 crocket: tbaldridge, namespaces don't solve modularity problem.

17:43 tbaldridge, namespaces solve a part of it, name collisions.

17:43 name collision is a symptom of non-modularity.

17:43 tbaldridge: crocket: they also allow you to logically split out your code into smaller parts

17:44 TimMc: UUIDs solve all name collisions.

17:44 * TimMc runs

17:44 crocket: tbaldridge, I'll have to experiment with ZeroMQ and OSGi and see which works.

17:45 tbaldridge, a complicated module management system helps you deal with managing library dependencies. But I'm not aware of tradeoffs yet.

17:45 jstew: /

17:45 crocket: To get a hand in tradeoffs, I have to use it.

17:46 tbaldridge: crocket: take a look at lein, library dependencies is what it was designed to handle.

17:46 crocket: tbaldridge, Do you use message queues a lot for modularity?

17:47 tbaldridge: crocket: yes, both for inter-process/VM communication, as well as inner-process. See http://github.com/clojure/core.async for the latter

17:48 crocket: tbaldridge, What do you use for IPC?

17:48 tbaldridge: core.async

17:48 ah sorry, wrong thing

17:49 ZeroMQ if I don't need reliable message passing, RabbitMQ if I do.

17:49 or even just plain old REST if I don't need a queue

17:49 crocket: meh

17:49 tbaldridge, What do you mean by REST?

17:50 tbaldridge: as in I structure my code as a collection of services that serve up HTTP, with EDN as the transport.

17:52 crocket: also think about what it would be like to build Systems the way NetFlix does it: any node should be able to fail at any time.

17:52 So they actually have a script called Chaos Monkey that randomly kills servers, if problems occur, you have issues with your design: http://techblog.netflix.com/2012/07/chaos-monkey-released-into-wild.html

17:53 crocket: tbaldridge, How do they manage processes?

17:53 tbaldridge: they don't, they manage servers. They run on AWS, and have many, many VMs. The script kills the entire VM.

17:54 crocket: oh jesus

17:54 I don't have a luxury of many VMs.

17:55 I'm a poor man left with a single server.

17:55 tbaldridge: So back to your original question, everyone builds their Clojure systems differently, that's my preferred approach.

17:56 crocket: tbaldridge, Do they use OSGi with clojure?

17:57 tbaldridge: no. also see https://groups.google.com/forum/#!topic/clojure/Ro9WO0USGTM

17:57 rasmusto: lazybot: wb

17:58 crocket: tbaldridge, REPL?

17:58 tbaldridge: http://tryclj.com/

17:58 that's a repl

17:59 crocket: How is REPL related to OSGi?

17:59 lazybot: rasmusto: Thanks.

18:00 tbaldridge: crocket: Clojure is a dynamic language, so they're stating in that mailing list thread that OGSi is somewhat hindered by the fact that Clojure programmers can re-define functions at a whim

18:00 It's even possible to to fire up a REPL on a remote box and dig around in the service while it's running

18:02 bja: exceptions to my system get flagged in sentry with information that makes it possible for me to repl in and recreate the scenario on the fly

18:02 I'm pretty sure I can't go back to doing it another way

18:07 crocket: tbaldridge, If you need to build a big program from modules, OSGi is still an answer.

18:14 tbaldridge: crocket: I'm just saying, I've seen Clojure used in some really massive systems. I have yet to hear of anyone using OSGi in production

18:19 jtoy: is this the recommended way to serialize clojure objects? http://stackoverflow.com/questions/1288877/what-would-be-the-correct-way-to-serialize-this-java-object-in-clojure i see it is 4 years old

18:23 Apage43: jtoy: I wouldn't. Use pr-str and clojure.edn/read-string

18:24 jtoy: Apage43: cool, I will try that, the object is maps of maps, i think that should be fine ,the other issue is it is about a gig in size

18:24 Apage43: http://clojure.github.io/clojure/branch-master/clojure.edn-api.html http://clojure.github.io/clojure/branch-master/clojure.core-api.html#clojure.core/pr-str

18:48 TimMc: brehaut: I have been infected with a taste for dubstep. D-:

18:49 brehaut: TimMc: that sounds unhealthy!

18:49 jave: hello

18:50 TimMc: It's all technomancy's fault. He pointed me to a chiptune-ish album that had some dubstep hiding in it.

18:50 wink: which one? :P

18:51 brehaut: lol

18:51 wink: more for the chiptune part actually

18:51 brehaut: TimMc: you sure it wasnt just a malfunctioning hard disk?

18:51 Raynes: TimMc: http://www.youtube.com/watch?v=xjx1PVdsVvk Take one of these twice a day.

18:51 callen: brehaut: if 20-somethings are stomping the floor, it's dubstep. If a greybeard is stomping the floor, a server's hard drive is failing.

18:52 The More You Know ☆彡

18:52 wink: lol

18:53 jave: if I'm going to expose a number of clojure methods to java with :gen-class, what is the convention? Do I wrap functions with new functions with - in front of the name?

18:59 mlb-: why is my test-atom not "Hello {:msg \"hello world\", :type \"log\"}" ? https://gist.github.com/mlb-/6616629

19:01 danielszmulewi-1: howdy

19:02 amalloy: mlb-: `for` is lazy. it is never correct to see (for ... (doseq ...))

19:03 noonian: hi danielszmulewi-1

19:03 mlb-: amalloy: so I'd want nested `doseq`s?

19:04 TimMc: brehaut: No, I haven't moved on to the really hard stuff yet.

19:04 I mean, I did experiment with catting /dev/hda to /dev/snd back in college, but never again.

19:05 brehaut: TimMc: you need to run it throguh an envelop filter and a beat synced parametric EQ and it'll be bang on

19:05 noonian: mlb-: yes that should fix it. because you don't do anything with the return value of publish (which is a lazy seq) after you call it, its evaluation is never forced

19:07 mlb-: noonian: your explanation helps, thanks =]

19:08 dbasch: what's a better way to do this? (map #(map read-string %) [["1", "2"] ["3", "4"]])

19:08 trying to convert a list of pairs of numeric strings to pairs of numbers

19:10 callen: dbasch: golf or "better"?

19:10 dbasch: "better" as in less ugly

19:12 callen: dbasch: write a mmap function that doesn't map memory but maps a twice-nested list :)

19:13 `cbp: and hide it in the closet

19:13 rasmusto: dbasch: ,(map (partial map read-string) [["1" "2"] ["3" "4"]])

19:13 heh

19:13 dbasch: rasmusto: that's marginally better I suppose

19:14 btw, the output of that goes into this ugly function, which could really use improvement: https://www.refheap.com/18775

19:14 callen: recursion without loop/recur?

19:14 brave.

19:15 AimHere: ,(walk #(mapv read-string %) identity [["1" "2"] ["3" "4"]])

19:15 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: walk in this context, compiling:(NO_SOURCE_PATH:0:0)>

19:15 AimHere: ,(clojure.walk/walk #(mapv read-string %) identity [["1" "2"] ["3" "4"]])

19:15 clojurebot: #<ClassNotFoundException java.lang.ClassNotFoundException: clojure.walk>

19:15 callen: AimHere: good idea!

19:15 rasmusto: I've got a new way to walk.walk/walk

19:16 callen: dbasch: walk is a more general solution, but I don't know how much pretty you'll get?

19:16 prettier*

19:28 dbasch: I want to believe this is a bit better, thoughts? https://www.refheap.com/18779

19:42 `cbp: dbasch: maybe this: https://www.refheap.com/18780 :P

19:42 jmonetta: hey guys! is it possible to shadow a special form with a macro in clojure?

19:42 `cbp: jk

19:42 dbasch: `cbp: thanks

20:02 rasmusto: jmonetta: I think that's what most of the special forms become, so yes

20:02 jmonetta: rasmusto: thx for your answer

20:03 I was trying to do some code walk with replacements

20:03 with our clojure macrolet definitions

20:03 rasmusto: jmonetta: ex: https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L4083

20:04 jmonetta: and I think it's specially avoiding macrolets to shadow special forms

20:06 like (macrolet [(if [test then-form else-form] `(if ~test (do (print "then") ~then-form) (do (print "else") ~else-form))))] (if 1 5 6))

20:06 that doesn't work

20:06 the macrolet doesn't expand the if special form

20:07 looking at the source it's supposed to protect the users

20:07 but I think this doesn't allows you to do some code walking/replacing using macrolets as in common lisp

20:11 rasmusto: jmonetta: interesting, that's beyond what I know

20:12 coventry: fn is not a special form, strictly speaking. That redefinition is over an earlier clojure definition https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L42

20:12 jmonetta: hmm I was pretty sure that was allowed in CL, but now it's giving me an error :(

20:12 coventry: The special form is fn*

20:14 jmonetta: http://letoverlambda.com/index.cl/guest/chap5.html

20:14 "Code-Walking with Macrolet"

20:15 that's what I'm trying to accomplish

20:16 cespare: If you wanted to do a loop over squares how would you do that?

20:16 I can construct a lazy seq of squares, but it's more typing than just squaring the number inside a (while true ...) loop.

20:16 Apage43: where is this macrolet from? is it the clojure.tools.macro macrolet?

20:17 (the one you're using, not the CL one)

20:18 coventry: Clojure doesn't macroexpand forms which start with one of its special forms: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Compiler.java#L6475

20:18 cespare: ah, iterate is what I want, I think.

20:19 jmonetta: I'm using clojure tools macrolet

20:19 [org.clojure/tools.macro "0.1.2"]

20:19 that one

20:20 Apage43: ah, but the problem as coventry points out is in clojure.core/macroexpand-1

20:23 but, the way I read clojure.tools.macro it should not be using that to expand the macrolets

20:23 only to expand regular macros

20:23 (that is, you *should* be hitting this branch https://github.com/clojure/tools.macro/blob/master/src/main/clojure/clojure/tools/macro.clj#L75-L76 )

20:25 jmonetta: let me check

20:25 thx

20:26 cespare: Why does (newline) cause flushing but printf with a newline at the end does not?

20:27 mtp: because (newline) causes flushing

20:27 pretty much

20:27 cespare: java's dumb, got it

20:28 mtp: uhhh, no

20:28 the definition of the function "newline" includes "flush the output buffer"

20:28 cmatheson: does (println) also flush? i always have to (println (format)) but i would rather printf

20:28 mtp: afaik

20:28 cespare: mtp: where is this definition?

20:28 mtp: I'm reading the docs and it just says that it prints a newline, and notes that it's equivalent to System.out.println()

20:29 mtp: huh, i could be wrong

20:29 cespare: cmatheson: that's exactly the annoyance i'm having

20:29 i was excited to discover printf, then sad to discover that i need to revert to (println (format )) after all

20:29 mtp: not sure how you can derive "java is dumb" from "these two functions do different things", though

20:31 cespare: well, it's directly exposing the java behavior afaict, which apparently doesn't flush even if the input ends with a newline.

20:39 * noprompt was using loop/recur when mapcat would've sufficed

20:40 noprompt: ;_;

20:40 * noprompt was sitting in the lobby once again wondering where everyone was.

20:43 AimHere: That's what loop/recur is for - there would be no need for it if you could only remember what the rotten sequence function you really need is called...

20:44 callen: noprompt: not even mapcat's actual implementation in core uses loop recur :P

20:44 you guys know there's a way to query the bot for functions that produce the desired output given example input, right?

20:45 AimHere: How clever is it?

20:45 noprompt: callen: fuck that i'll just query "lessons learned from writing horrible clj code"

20:45 callen: it's like a runtime Hoogle for Clojure.

20:45 AimHere: it works fine but it's sometimes more inclusive than you want if you don't give a specific enough example.

20:45 noprompt: callen: haha, it should be called "Cooger"

20:46 AimHere: Well does it do that Byrd/Friedman thing of spitting out the first 50 functions that evaluate to 6?

20:46 noprompt: i'll say it again, recognizing you've written some bad code is the first step on the road to recovery.

20:46 AimHere: Or does it just look for named clojure functions!

20:46 cespare: how would I reload a library inside lein repl? (If i just lein installed a new version)

20:47 noprompt: cespare: are you using emacs with nrepl?

20:47 cespare: noprompt: nope

20:47 noprompt: errm... load-file?

20:47 load?

20:48 callen: cespare: (require '[clojure.tools.namespace.repl :refer [refresh]]) (refresh)

20:48 * noprompt looks around for someone to provide the correct answer.

20:49 callen: noprompt: done.

20:49 noprompt: cespare: he/she may not be using clojure.tools.namespace

20:49 callen: use clojure.tools.namespace.

20:49 noprompt: callen: like this (use 'clojure.tools.namespace)?

20:49 lol

20:49 callen: if you need to go spear fishing you'd better have a fucking stick.

20:49 noprompt: callen: dude, i'll choke a fish out with my bear hands.

20:50 callen: bare hands?

20:50 noprompt: that's right *bear* hands

20:50 callen: bear hands seems to work too.

20:50 cespare: callen: ok, i can use clojure.tools.namespace, but I wasn't before

20:50 callen: change your lein profiles for :user :dependencies to include c.t.n

20:50 * noprompt should use clojure.tools.namespace

20:50 cespare: callen: is that something I should put in my user project thingy

20:50 callen: cespare: profiles.

20:50 * noprompt is not in the "loop"

20:50 callen: cespare: ~/.lein/profiles.clj

20:50 cespare: callen: yes that.

20:50 callen: noprompt: I can loop you into the loop.

20:50 cespare: yes. do that.

20:50 * noprompt scrambles to github for the relevant details...

20:51 callen: noprompt: http://thinkrelevance.com/blog/2013/06/04/clojure-workflow-reloaded

20:51 I hate that he's decided to claim this as his own, but whatever. Do it anyway.

20:51 noprompt: callen: yeah, i've read that.

20:51 callen: well...do it.

20:51 c.t.n.r is amazing.

20:52 noprompt: i don't like putting my name on stuff or taking ownership. i don't even like licenses or copyrights.

20:52 callen: it's great for re-running tests with too

20:52 noprompt: it feels icky.

20:52 rasmusto: callen: would it be better to have it as a per-project thing? (in terms of sharing code or w/e)

20:52 noprompt: still i've done these things.

20:52 callen: noprompt: I think Sierra got tired of being the Stuart the Lesser. Needed to put his name on something.

20:52 rasmusto: no.

20:52 rasmusto: it's a local dev tool.

20:52 you shouldn't be writing code that uses c.t.n.r

20:52 rasmusto: callen: kk

20:53 callen: it's just repl dev.

20:53 it's an Emacs macro for me.

20:53 I use terminal REPL for running tests (up arrow, hit enter)

20:53 and Emacs REPL for experimentation/dev

20:53 noprompt: stuart sierra's talks trick me in to thinking i actually understand them.

20:53 but i like them anyway.

20:54 cespare: callen: so how do i figure out the version of c.t.n.r that I should use? When I search clojars for that, nothing comes up. It's also not in the readme.

20:54 callen: hg commit -m "primary keys that aren't really primary."

20:54 noprompt: callen: that's how i run tests too.

20:55 rasmusto: cespare: it says 0.2.4 on github

20:55 cespare: rasmusto: that's for c.t.namespace

20:55 callen: clojars is...not how you should be finding packages :P

20:55 cespare: callen: ok, please enlighten me

20:55 callen: there's a lot of proxy packages on there from forks.

20:55 cespare: i'm new to this

20:55 callen: official github repo -> lein line

20:55 noprompt: callen: it's a nice sanity check to make sure you don't have anything weird going on after long Emacs sessions.

20:55 callen: [c.t.n "0.2.4"] line from the README.md

20:55 justin_smith: I checkout out my clojure app in jvisualvm, and saw 600k+ instances of class character

20:56 cespare: callen: i did that. That didn't give me c.t.n.r

20:56 justin_smith: is this normal? is it something weird about my app?

20:56 cespare: I assume that's a different package?

20:56 callen: noprompt: I bounce between the two REPLs.

20:56 rasmusto: cespare: https://github.com/clojure/tools.namespace#releases-and-dependency-information

20:56 callen: justin_smith: I've only done runtime profiling in YourKit, can't say.

20:56 doesn't sound right though :)

20:56 noprompt: callen: term repl/emacs nrepl?

20:56 callen: yeah.

20:56 justin_smith: yeah, that represents quite a bit of ram

20:56 cespare: ok, i must just be requiring it incorrectly.

20:57 noprompt: callen: usually that's what i have going on but i seldom use the term repl.

20:57 rasmusto: cespare: oh, maybe I'm the one out of the loop, just read your last comment

20:57 callen: noprompt: I experiment in emacs nrepl, start firming up the implementation in the buffer for my actual code file, test from emacs nrepl until it seems to work. Then I write a test and start hammering the terminal REPL.

20:57 cespare: callen: I get a filenotfoundexception when I do your require line, even though I clearly have the package (lein repl printed stuff abouting downloading c.t.n from central)

20:57 callen: it's like a meta-loop of development behavior.

20:57 noprompt: callen: i don't like using nrepl-jack-in because sometimes i want to connect to another repl session

20:57 callen: cespare: reload the repl

20:57 rasmusto: cespare: er, nm, maybe that's the right thing

20:57 callen: noprompt: I don't do nji

20:57 cespare: callen: I did

20:58 noprompt: callen: it's alla 'bout strait M-x nrepl

20:58 callen: [org.clojure/tools.namespace "0.2.4"]

20:58 cespare: callen: yes that's what I have.

20:58 callen: I had 0.2.3

20:58 try 0.2.3

20:58 cespare: callen: I'm in a project though, and the project doesn't have it.

20:58 callen: doesn't matter

20:58 cespare: callen: maybe i need to switch namespaces or something?

20:58 callen: I only have it in profiles.

20:58 ...no

20:58 cespare: k, no idea then.

20:58 callen: try 0.2.3

20:59 check your ~/.m2

20:59 noprompt: I do the testing -> terminal REPL flow because it's faster than checking multiple assertions manually

20:59 cespare: 0.2.3 doesn't work, looking in ~/.m2

20:59 callen: it lets me set up a batch of assumptions.

20:59 muhoo: i asked this earlier, not sure if there was an answer: how does one in nrepl.el hit RET on a line in an nrepl error stacktrace and go to that file and line?

21:00 because, it doesn't do that, and i'm thinking it probably should.

21:00 callen: muhoo: mouse-click definitely does it to me sometimes.

21:00 cespare: callen: how is this organized? find ~/.m2 -name namespace doesn't come up with anything

21:00 callen: let me throw an error and find out.

21:00 noprompt: callen: one thing i do like about testing in emacs vs the term is that failing tests get highlighted. that's always nice. especially with is.

21:01 callen: i've got a lot of tests that use are too but i almost wanna switch them back to let/is so i can get see precisely the failing test.

21:02 callen: muhoo: goes to the top of the file if I give it a file for me. Not directly.

21:02 muhoo: mouse click does squat for me, RET does squat too.

21:02 callen: oh it definitely prompts me.

21:02 it just isn't very helpful.

21:03 noprompt: my workflow is 50% experimental, 50% test driven.

21:03 I don't really write tests first, they happen after I've formulated assumptions about what should and shouldn't happen based on the earlier experimental stage.

21:03 I don't like baking my assumptions into tests until I understand the data and the code I'm interacting with.

21:04 I don't write that many tests either.

21:05 I've got 16 tests for 400 LOC on what I'm working on right now.

21:05 16 assertions, 7 tests, sorry.

21:06 cespare: callen: ok, i found 0.2.3 and 0.2.4 in my .m2

21:07 callen: I've also verified that inside there, tools/namespace/repl.clj exists (in the jar), which is exactly the file that shows up with a FileNotFoundException when I require

21:07 noprompt: is there an fn that's equivalent to [(filter pred coll) (remove pred coll)]?

21:07 rasmusto: callen: how do I get it to use the :user profile when I launch a repl? cespare: yeah, I'm getting something similar

21:07 callen: my code also tends to form a push-down stack of helper/component fns push down the root fn that forms a more proper part of the API

21:08 hyPiRion: noprompt: split-with I think

21:08 noprompt: i'm not looking for split-at or split-with

21:08 callen: rasmusto: I don't know what's going on with you guys.

21:08 noprompt: wat

21:08 noprompt: hyPiRion: split-with is take-while/drop-while

21:08 rasmusto: noprompt: #(juxt filter remove) ?

21:08 noprompt: rasmusto: bam! nice.

21:08 :)

21:09 callen: yeah, no, that couldn't possibly be sane right

21:09 callen: oh I see.

21:09 noprompt: :P

21:09 callen: wow, a good excuse to use juxt.

21:09 bravo rasmusto.

21:09 noprompt: juxt is the shit legends are made of.

21:09 callen: that was today's juxt quota.

21:09 rasmusto: callen: I slurped it over from yesterday's quota

21:10 callen: I used juxt, however inappropriately, yesterday.

21:10 turned it into destruct :(

21:10 I used a group-by and a projection function today.

21:12 cespare: callen: rasmusto works if it's in the project.clj, btw

21:13 noprompt: rasmusto: that was the highlight of my day.

21:14 * noprompt frantically edits source laughing like a mad man.

21:14 callen: well wtf happened to Leiningen profiles?

21:15 rasmusto: callen: yeah, I was trying to do a `lein with-profile user repl` or somesuch

21:15 noprompt: (def divide (juxt filter remove))

21:16 rasmusto: hahaha, I actually used (juxt filter remove) in my code today without thinking about it

21:16 irc is a powerful influence

21:18 * noprompt is so excited to replace some bat shit crazy, ultra perf code, with elegant less perf code.

21:19 muhoo: oh, that was exciting, and stupid. i upgaded to nrepl 1.8 and now i get no stacktrace at all :-/

21:19 rasmusto: hrm, I'll give c.t.n.r a shot tomorrow

21:19 noprompt: i wanna make async regex patterns

21:20 callen: rasmusto: if I really wanted to, I could use "juxt filter remove" instead of my group-by :P

21:20 noprompt: wtfffff are you doing?

21:20 async...regex...what?

21:20 muhoo: ah, there's a nrepl-popup-stacktraces variable

21:20 noprompt: callen: yeah, lol

21:21 muhoo: and... RET does something, it says "No error here". so that's an improvement.

21:21 * muhoo imagines spending his evening hacking nrepl.el *sigh*

21:21 noprompt: callen: think about checking m1|m2|m3 blah blah concurrently

21:22 cespare: rasmusto: callen it happens with any library, not just c.t.n.r. Maybe I'm not using lein profiles correctly?

21:22 noprompt: callen: i saw this it kinda inspired me to mess around https://github.com/coreperf/rejit

21:23 callen: normally i have no clue what i'm doing. i just go in to rabbit holes for the hell of it.

21:23 callen: hrm. using apply and flatten in the same line. I have something horribly wrong.

21:23 have done*

21:23 muhoo: yak-shaving advanced mode?

21:24 I...am going to replace my flatten with mapcat identity and pretend it's somehow better. k? k.

21:24 amalloy: ITYM "using flatten", callen. nothing wrong with apply

21:24 uh, yes, that is generally ~100x better

21:25 * muhoo creates a function called flatcat

21:25 callen: where's the 100x coming from? (serious question)

21:25 amalloy: although (apply concat xs) is more popular than (mapcat identity xs)

21:25 oh, just that about 1% of the time flatten is a good choice, and 100% of the time concat is

21:25 noprompt: (apply concat xs) is nice.

21:26 <3 concat

21:26 <3 mapcat

21:26 callen: Simplified example: (apply hash-map (flatten [[:a 1]])) -> (apply hash-map (mapcat identity [[:a 1]]))

21:26 second one is what it got replaced with.

21:26 amalloy: callen: those both make me want to throw up

21:26 (into {} [[:a 1]])

21:26 callen: amalloy: it's the result of group-by.

21:26 oh SON OF A BITCH

21:26 noprompt: yeah i was just about to say into

21:26 * callen changes it to into

21:26 amalloy: well, have fun. i'm off

21:27 callen: should've known to use into from your goddamn 4clojure answers.

21:27 * callen slaps forehead

21:27 muhoo: into is the shiznit

21:27 almost as cool as juxt

21:27 * muhoo ducks

21:27 noprompt: "red elf needs food badly"

21:27 callen: muhoo: almost.

21:27 noprompt: well that's my queue to go eat.

21:28 cespare: cue?

21:28 muhoo: no, he's using core.async to eat

21:28 cespare: or did you see a line of people walk by, who are all going to go eat, and you're about to join them

21:28 noprompt: cespare: i tend to Ms. pell stuff because it's funny to me.

21:29 callen: cespare: maybe he lives in Soviet Russia and must queue for potatoes.

21:29 hahahaha. who I kidding. no afford potatoes.

21:29 noprompt: muhoo: that's a funny thought.

21:29 muhoo: (def food (java.util.concurrent.SynchronousQueue.))

21:29 noprompt: (put my-mouth (<! food))

21:29 muhoo: noprompt: yeah, much nicer

21:30 callen: BWAHAHAHAHA. Passing tests.

21:30 * callen does a happy dance

21:30 muhoo: i really should get on the core.async bandwagon. the syntax sugar is so nice

21:30 noprompt: muhoo: you could probably model the whole eating process if you took the time to wire it up.

21:30 callen: muhoo: I use it for testing RabbitMQ in my unit tests cleanly.

21:30 noprompt: that'd be funny.

21:30 callen: muhoo: core.async propagates the state cleanly (without globals) from the callbacks to the unit test fns.

21:31 muhoo: though lamina does the job, core.async seems so much slicker.

21:31 it has that rhickey simplicity thing baked in

21:31 callen: Lamina is very good at what it does, but I think core.async is better suited for "lightweight" uses like mine.

21:31 noprompt: muhoo: i've only recently be using it on the client side.

21:31 callen: I think core.async is going to be my go-to (ha ah!) library for marshalling callback state and behavior.

21:32 noprompt: cyallater

21:32 callen: without, you know, smacking global state around.

21:32 noprompt: latah.

21:33 cespare: how can I see my classpath?

21:33 inside lein repl

21:35 ok...so the things in my ~/.lein/profiles.clj just aren't in my classpath.

21:36 callen: bizarre.

21:36 cespare: which profile are you using?

21:36 are you overriding the profile in your project.clj?

21:36 cespare: The one in my profiles.clj is called :user, but I don't see anything about profiles in my project.clj

21:37 how do I see the current profile?

21:37 ok, trying out lein-pprint for teh debugz

21:38 oooooooooooooooh, nvm

21:38 i see what I done

21:38 everyone carry on

21:39 callen: cespare: ...what'd you do?

21:39 cespare: callen: added the library to :plugins, not :dependencies ><

21:40 * callen polite golf clap

21:40 callen: cespare: happens to the best of us :)

21:41 cespare: ok, pop the stack, back to the previous problem now that I can reload my library

21:54 callen: btw, that refresh thing doesn't actually reload the library that I reinstalled with lein repl

21:54 still gotta restart lein repl

21:55 coventry: cespare: Check out pomegranate. I hear good things about alembic for this, too.

22:01 callen: alembic is more "whole" than pomegranate in the sense that it's less hassle to use and can synchronize with the project.clj

22:01 alembic is what I use.

22:01 cespare: refresh is for reloading existing code, not fucking with your classpath :)

22:02 cespare: callen: i don't need my classpath to change

22:02 i'm debugging a library. I make a change and lein install it. Then in my test project's repl, i want to reload

22:06 coventry: cespare: You need a lein checkout dependency. https://github.com/technomancy/leiningen/blob/master/doc/TUTORIAL.md#checkout-dependencies

22:10 cespare: coventry: ah perfect, thanks

22:20 What's this about? #<FileNotFoundException java.io.FileNotFoundException: Could not locate clojure/tools/macro__init.class or clojure/tools/macro.clj on classpath: >

22:21 callen: cespare: you've now exceeded your free IRC support plan limit, please enter credit card number to continue at a rate of $15 per question.

22:21 SegFaultAX: So I finally have a case where I need to introduce a concrete type (well multiple, for different implementations of a protocol). What's the current accepted standard? deftype, defrecord, gen-class?

22:21 coventry: You can get your classpath by running "DEBUG=true lein repl" or with pomegranate.

22:22 callen: SegFaultAX: I'm dubious you needed a protocol to begin with. >:)

22:22 SegFaultAX: callen: Why?

22:23 callen: almost nobody ever does and would be better served with multimethods.

22:23 SegFaultAX: Well in this case it's more like an interface. multimethod isn't a good fit.

22:23 callen: that's what multimethods are for too.

22:24 SegFaultAX: Cool

22:24 Anyway, what's the current best practice. I seem to recall defrecord not being popular anymore or something...

22:25 callen: structs are deprecated, not records.

22:25 SegFaultAX: Ah ok, that's right.

22:25 callen: records aren't maps and don't share structure.

22:26 SegFaultAX: I thought the whole point of records is that they are persistent maps.

22:26 `cbp: defrecord if you wanna have map compatibility, deftype otherwise i guess

22:26 callen: defrecord is preferred in the "general" case.

22:26 `cbp: the map compatibility is superficial, they do not share structure the way maps do.

22:26 deftype is more barebones than defrecord. If it looks and smells like a map, you want defrecord.

22:27 SegFaultAX: I don't know if "superficial" is the right word. It implements all the right interfaces, the fact that it doesn't use structural sharing is an implementation detail.

22:27 Which is mostly irrelevant.

22:28 callen: well, churn some records in a loop and see how irrelevant it is :)

22:28 http://cemerick.com/2011/07/05/flowchart-for-choosing-the-right-clojure-type-definition-form/

22:28 you should note that this is specifically for defining a type in Clojure, not for defining interfaces.

22:29 if all you're doing is defining an interface, not a type associated with a protocol, then you don't necessarily need protocols.

22:29 SegFaultAX: 1 protocol. 3 distinct implementations.

22:30 callen: Are you thinking definterface?

22:30 callen: no :(

22:30 I'm thinking Clojure code that doesn't give a damn about Java crap.

22:31 SegFaultAX: No Java interop required.

22:31 callen: then why are you using protocolsssssss

22:31 * callen turns into an inky black 8 tentacled beast and thrashes around

22:31 callen: I never thought having used CLOS in Common Lisp would be superseded by a situation where I'm telling people YAGNI. I thought CLOS was the ultimate flouting of YAGNI, but it has been overcome.

22:32 SegFaultAX: protocols are explicitly about dispatching on type and only type. If types and the associated Java-ness aren't an important part of what you're doing...then don't make an interface that dispatches on type...

22:33 * callen points to multimethods impatiently

22:33 callen: the only other reason to use protocols is "performance"

22:33 Apage43: beh, this is reminding me I have some code I should be using multimethods on

22:33 callen: and I swear to god I am going to start going after people that claim that as an excuse without a benchmark showing dispatch was a non-trivial part of the runtime.

22:34 Apage43: right now its covered in functions that are nothing but a big-assed (cond)

22:34 callen: Apage43: lol. I applaud you for your restraint though.

22:35 premature multimethods/protocols is worse than having a cond.

22:35 * callen thinks back to the CLOS of yesteryear...

22:35 SegFaultAX: As I said, in this case it's more about documenting the interface.

22:35 Apage43: the only reason I really want to do it is to make it easier to read

22:36 callen: SegFaultAX: can't write docs unless it's prefaced with a defprotocol? Do you have a prescription for that?

22:37 bja: callen: refactoring tends to flow from if->cond->multimethods

22:37 with a correlation to people requesting more features

22:37 SegFaultAX: callen: More like "if you want to implement a new one of these thingies, this is the minimum interface you need to adhere to"

22:38 Protocols are a good in-code form of documentation for that.

22:38 callen: bja: me gusta

22:38 SegFaultAX: orrrrr multimethods.

22:39 I want you to swallow your insanity for the whole 30 minutes it would take to just do it in multimethods just so you see how it feels.

22:39 SegFaultAX: callen: Yes, I understand your opinion on multimethods.

22:39 bja: multimethods are like slingshot. best used in small doses, lest I remember that throw+ is just a super convenient multi-level-escape-capable flow-control method

22:40 Apage43: I've only ever used slingshot with clj-http, to catch some HTTP errors but not others

22:41 bja: and the last time I did that I lost several hours refactoring the resulting "slingshot-enabled" code to be readable in the following days/weeks/months

22:41 callen: bja: multimethods are not dangerous the way slingshot is.

22:41 they're simpler than protocols half the time.

22:42 bja: I figured out how to log the namespace in my console.log messages from clojurescript today

22:42 that was actually pretty exciting

22:43 callen: bja: black triangle?

22:44 ambrosebs: is there a good reason why Clojurescript cannot be AOT compiled?

22:44 SegFaultAX: callen: While I don't need Java interop, type based dispatch is /exactly/ what I'm after.

22:45 bja: ambrosebs: isn't that basically what happens? you AOT compile it to javascript instead of .class files

22:45 SegFaultAX: If I used multimethods, I'd just invent something like dispatching on type anyway.

22:45 ambrosebs: bja: I mean cljs.compiler.

22:46 SegFaultAX: callen: Generally I agree with you, but in this case protocols does actually seem warranted.

22:46 callen: SegFaultAX: then go forth with my blessing, but know that it'll fuck with your REPL anyway.

22:46 and if they're mappy data structures, use defrecord.

22:46 SegFaultAX: callen: How so? I thought defrecords and deftypes can be freely re-eval'd?

22:46 callen: you'll be torn limb from limb if you use defstruct.

22:47 Apage43: SegFaultAX: they can

22:47 callen: SegFaultAX: they can

22:47 Apage43: but you wind up with two classes with the same name

22:47 which is Fun (TM)

22:47 SegFaultAX: Actually in this case deftype is sufficient.

22:47 callen: DOdl;kfhmklnflhknf

22:47 don't.

22:47 bja: callen: no. the black triangle was a couple months ago. this just improves my debuggering immensely. Since I can now write (??? interesting-value) and end up with something like "my.first.namespace: (foo (bar baz))" in the console log

22:47 err, debugging

22:47 callen: debuggering? are you oppressing homosexuals?

22:47 SegFaultAX: callen: No no, definitely not using defstruct.

22:47 callen: bja: very illiberal of you :|

22:48 SegFaultAX: use defrecord anyway >:)

22:48 xeqi: ambrosebs: you mean compiled and distributed as a library?

22:48 danielszmulewi-1: Just use tools.namespace and read the warnings: https://github.com/clojure/tools.namespace#warnings-for-protocols

22:48 SegFaultAX: What if I only /ever/ have like 3 fields, you reckon the overhead is worth it?

22:48 Apage43: (you'll have things like instances of the pre-reeval class and the post-reeval class behaving differently, and such)

22:48 bja: SegFaultAX: I find it to be

22:48 Apage43: and not being considered to be the same type

22:48 ambrosebs: xeqi: Basically. I'm jumping through hoops to get Clojurescript working with my AOT code.

22:48 Apage43: or .equals to each other

22:49 callen: SegFaultAX: you should use defrecord by default. deftype is for when you need the chainsaw.

22:49 SegFaultAX: Understood.

22:49 callen: ie, your name is aphyr.

22:49 SegFaultAX: callen: Thanks!

22:49 And the rest of you, thanks! :)

22:49 xeqi: ambrosebs: ack, I was thinking you meant your own code, not the compiler.. hmm

22:49 ambrosebs: xeqi: sorry. I only use the compiler ;)

22:51 callen: SegFaultAX: pretty sure Stuart Sierra's workflow handles how to manage things like protocols cleanly in a REPL workflow.

22:51 SegFaultAX: callen: Ok thanks. I pretty much just looked at the flowchart, I'll give the article a closer read.

22:52 Apage43: the main thing is you just gotta be careful with old instances hangin around

22:52 if you make sure you don't do that, you're pretty much alright

22:52 SegFaultAX: Apage43: Was that to me?

22:53 Apage43: in general, about the topic of protocols and REPLs

22:53 to whoever cares :)

22:53 SegFaultAX: Why would objects just arbitrarily hang around?

22:54 Apage43: I personally have scratch names all over the place when I'm REPLing

22:54 SegFaultAX: Apage43: Memory is cheap. ;)

22:54 Apage43: I might reload a protocol and forget the instance I created of it earlier and gave a name to was from before I reloaded it

22:55 or you might have a "on-app start" function in your app that builds its initial state, and if that instantiates some things and you *don't* rerun it after you reload a protocol definition

22:56 it could get hairy

22:58 danielszmulewi-1: Apage43: at which point you restart a new REPL...

22:59 SegFaultAX: danielszmulewi-1: Like... ew

23:00 danielszmulewi-1: SegFaultAX: exactly... anathema

23:11 chord: anyone here?

23:13 akurilin: Am I correctly understanding that a maybe monad would be one decent way to solve the issue of having a lot of conditionals in my ring handlers that make sure the result of each subsequent operation isn't nil?

23:17 weavejester: akurilin: In Clojure 1.5, there is the some-> function that fulfils a similar role.

23:17 chord: just use haskell

23:18 akurilin: weavejester, awesome, thanks for the tip. I always forget about those as I'm always on clojuredocs. That github wiki from the google groups seems to have it though.

23:26 marco1: for clojurescript, what's the equivalent of: someObj["func"]() ?

23:27 gfredericks: ((aget someObj "func")) last time I used cljs

23:29 marco1: Thanks!

23:31 danielszmulewicz: weavejester: you nightbird :-)

23:31 weavejester: danielszmulewicz: I code better at night, but I'm just about getting to bed :)

23:32 danielszmulewicz: weavejester: same here, my friend

23:32 weavejester: already in bed :-)

23:32 Raynes: Owl.

23:37 john2x: "((aget someObj "func"))" it's not possible to do ((:func someObj)) in cljs?

23:46 chord: lets make a game with clojure ok

Logging service provided by n01se.net