#clojure log - Jan 05 2011

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

0:01 devn: clizzin: check out line 4762 in core.clj for clojure-1.2.0 stable

0:01 clizzin: dale, devn: okay, nvm, dale is correct. the only caveat is that y is accessible either as y or f/y

0:02 dale: clizzin: Heh, yeah, that. Was just typing up https://gist.github.com/765957 .

0:03 devn: oh my god.

0:03 dale: clizzin: So that ClojureDocs example is correct but not complete, I'd say.

0:03 devn: i just realized SLIME has this cross-reference capability

0:03 M-. on (loo|p) for instance in the SLIME REPL where | is my cursor

0:04 C-c C-w c Who Calls: loop RET

0:04 dale: clizzin: Continuing on from that example you could also reference anything in clojure.string, not just the stuff named in :only. Ex: s/escape works.

0:05 clizzin: devn: M-. is insanely useful

0:05 devn: yeah M-. is pretty much why i extoll the virtues of lisp

0:06 the tools around it are just insane.

0:06 (in a good way, of course)

0:06 clizzin: esp. precisely because namespace require/use-ing often make it really confusing where any particular function came from

0:13 amalloy: clizzin: that's why you're discouraged from use-ing libraries wholesale

0:14 if you use..only or require..as, it's unambiguous where a given function comes from

0:16 clizzin: amalloy: true, but some people are not always so clean with their code. =(

0:16 amalloy: clizzin: go on a github crusade like devn :)

0:17 clizzin: amalloy: haha, is devn just making lots of pull requests that fix that precise issue?

0:17 amalloy: no, he has his own set of pet peeves, but that's the idea

0:42 interesting: ##{a b (comment c d)} throws a CompilerException caused by an ArrayIndexOutOfBoundsException; i'd have expected slightly friendlier handling

0:59 Raynes: amalloy: It might be useful to add { and [ to the list of things that ## sets off, don't you think?

0:59 amalloy: Raynes: heh. it didn't occur to me that was the problem

1:20 tomoj: why ever use rest?

1:24 I mean, say rest were removed and we were stuck with next. a loss?

1:24 ..besides backward-compatibility issues

1:27 amalloy: tomoj: laziness

1:28 in particular suppose my lazy-seq has side effects (gross, i know)

1:29 then if map uses rest, (first (map f myseq)) will result in only one set of side effects; if map uses next, it will result in two sets of side effects

1:36 tomoj: ah, right

1:36 I expected to find corroboration in LazySeq, but don't..

1:37 oh, I wasn't looking hard enough

1:44 huh

1:45 (when x) == (when-not x) == (do x nil)

1:45 of those I guess I have to prefer (do x nil), any better?

1:46 hiredman: ((constantly nil) x)

1:49 tomoj: I name (constantly nil) "nilf"

1:51 is there any use of (constantly constantly)?

1:52 hard to imagine it being useful

2:07 clizzin: is there an rsplit function anywhere in core or contrib? (that is, behaves like split, but goes from the right instead of from the left)

2:07 to clarify: i'm talking about splitting strings

2:12 amalloy: &(let [s "hello there!"] (map (partial apply str) (split-at (- (count s) 3) s))) is kinda ugly :P

2:12 sexpbot: ⟹ ("hello the" "re!")

2:15 amalloy: clizzin: ^ if you're just looking for something that works

2:17 clizzin: amalloy: was looking for something that splits on a delimiter rather than on an index

2:18 amalloy: &(let [s "hello there!"] (map (partial apply str) (split-with #{\space} s)))

2:18 sexpbot: ⟹ ("" "hello there!")

2:18 amalloy: &(let [s "hello there!"] (map (partial apply str) (split-with (complement #{\space}) s)))

2:18 sexpbot: ⟹ ("hello" " there!")

2:19 tomoj: "goes from the right?"

2:19 amalloy: clizzin: still not simple; if you just want to use a simple delimiter, what about one of the regex functions?

2:20 clizzin: tomoj: i.e. (rsplit "hello there pardner!" #" " 2) -> ("hello there" "pardner!")

2:21 _na_ka_na_: clizzin, how about reverse, then reverse again ?

2:21 clizzin: amalloy: took a look at the pattern class...it doesn't have a similar function, but what i can maybe try is writing a regex where the delimiter regex requires that it be followed by a series of non-delimiter chars, then the end of the line

2:22 and then split on that regex

2:22 tomoj: clizzin: ah

2:23 clizzin: _na_ka_na: that seems like it would work but have poor performance

2:23 and the function that has to do this splitting is the main bottleneck in the code, so keeping its performance snappy would be nice

2:24 _na_ka_na_*

2:24 let me play around a bit, and i'll report back if i figure out something good

2:24 _na_ka_na_: clizzin, I'm not sure it would be that bad, coz in any case a splitting from right means non lazy

2:25 so you have to start at the back

2:25 amalloy: clizzin: and you want the numeric argument to be the maximum number of splits?

2:25 tomoj: how do you propose to reverse the string?

2:25 clizzin: amalloy: yes

2:25 tomoj: i assume using the reverse function, no?

2:25 tomoj: (apply str (reverse s)) doesn't exactly look snappy to me

2:25 clizzin: the reverse strategy only works if the delimiter is whitespace

2:26 tomoj: yeah, that was my concern as well

2:26 the proper way to do this is properly with some java code that essentially does the same thing as Pattern/split but iterating in the opposite direction

2:26 is probably with*

2:27 _na_ka_na_: do you have the string to be split in one single huge string?

2:27 clizzin: _na_ka_na_: er, what do you mean by that?

2:27 _na_ka_na_: clizzin, I mean the first arg to your rsplit, how do you get that?

2:29 clizzin: _na_ka_na_: hm, still not sure what you mean. my ideal rsplit usage would be (rsplit s delimiter max-num-pieces) where s is the string to be split, delimiter is the string to split on, and max-num-pieces is the number of pieces i end up with. dose that answer your question?

2:29 does*

2:30 _na_ka_na_: clizzin, yes it does

2:31 tomoj: it does?!

2:31 wasn't the question where these strings are coming from?

2:32 clizzin: tomoj: yeah, i don't really get what's being asked either, but apparently what i said answered it. =P

2:33 tomoj: the strings are coming from arbitrary input land

2:33 where the edge cases roam

2:34 _na_ka_na_: ,(clojure.contrib.string/split #"ab" 3 "1111ab2222ab3333ab44444ab55555")

2:34 clojurebot: ("1111" "2222" "3333ab44444ab55555")

2:34 _na_ka_na_: ,(map clojure.string/reverse (clojure.contrib.string/split #"ba" 3 (clojure.string/reverse "1111ab2222ab3333ab44444ab55555")))

2:34 clojurebot: java.lang.RuntimeException: java.lang.RuntimeException: java.lang.ClassNotFoundException: clojure.string

2:34 _na_ka_na_: no clojure.string ?

2:34 &(map clojure.string/reverse (clojure.contrib.string/split #"ba" 3 (clojure.string/reverse "1111ab2222ab3333ab44444ab55555")))

2:34 sexpbot: ⟹ ("55555" "44444" "1111ab2222ab3333")

2:36 _na_ka_na_: what I basically wanted to ask is the signature of rsplit, whether it takes its first arg as a string

2:36 tomoj: that looks probably a lot snappier

2:37 _na_ka_na_: but the trouble is you have to "reverse" the regex also

2:37 #"ab" --> #"ba"

2:37 clizzin: _na_ka_na_: yeah, that was what i was going to say

2:38 tomoj: &(let [s (apply str (repeat 1000000 \0))] (time (when (clojure.string/reverse s))))

2:38 sexpbot: ⟹ "Elapsed time: 14.803962 msecs" nil

2:38 tomoj: &(let [s (apply str (repeat 1000000 \0))] (time (when (apply str (reverse s)))))

2:38 sexpbot: ⟹ "Elapsed time: 1324.168299 msecs" nil

2:38 clizzin: tomoj: what's the when for?

2:38 _na_ka_na_: tomoj, hmm it uses a stringbuilder

2:39 tomoj: to avoid returning the return value

2:39 _na_ka_na_: that's a neat trick :P

2:40 clizzin: tomoj: haha cool

2:40 tomoj: that's not at all idiomatic

2:41 just a cheap trick I discovered a while ago to save keypressed compared to (do x nil)

2:42 only 2 keypresses, I guess..

2:42 somehow (when ) still feels easier than (do nil)

2:43 just a simpler sexp I suppose

2:43 clizzin: it's because you don't have to remember to put the nil at the end -- once you type the when, you can concentrate on the actual thing you want to test

2:43 amalloy: tomoj: (= ) saves still more keystrokes

2:44 tomoj: :D

2:44 clizzin: amalloy: oohhh. but my pinky has to extend farther then =/

2:44 amalloy: &(= (apply str (repeat 1000000 \0)))

2:44 sexpbot: ⟹ true

2:44 tomoj: for me, = is index finger, so perfect, thanks!

2:45 _na_ka_na_: clizzin, if your regexes are simple enuf, maybe you can reverse the pattern yourself :P

2:45 ,(.pattern #"ab")

2:45 clojurebot: "ab"

2:45 tomoj: unary = also seems even more delightfully mysterious than a body-less when

2:46 devn: I'd like to build a refactoring tool for clojure that helps you reorganize your functions and split them out into different files

2:47 _na_ka_na_: also: (dorun ["huge string"])

2:47 devn: im not sure what i'm thinking makes sense...

2:47 for instance, if i require, are those requires obeyed in terms of their order?

2:47 (in the ns macro)

2:48 tomoj: what does order matter?

2:48 devn: (:use [foo.bar] [fred.green])

2:48 what about there?

2:49 tomoj: last wins I think

2:49 _na_ka_na_: devn, don't think you can rely on any ordering

2:49 why do you want ordering

2:49 devn: maybe im "doing it wrong"(tm), but I write clojure top-down and then the file eventually becomes big enough that id like to split it out

2:50 there are like-functions which could be grouped, but they are now interwoven into the single large file

2:50 _na_ka_na_: devn, you mean splitting into different nses or the same ns

2:50 devn: different

2:50 different files, different nses

2:51 _na_ka_na_: but isn't that a decision only you can take, on what to name the nses & grouping of fns

2:51 devn: _na_ka_na_: yes but it could be automated

2:52 _na_ka_na_: oh i see, maybe a dag of fns .. then split by connected components ?

2:52 hmm

2:52 amalloy: _na_ka_na_: i think he just means "okay tool, please move functions XYZ into ns foo"

2:52 devn: i could say (organize {:defn "foo" :def "buzz"}) or something

2:52 _na_ka_na_: oh that

2:52 devn: and it would split the function and the def out into a new file that i specify there

2:53 _na_ka_na_: ya that might not be difficult to do i guess

2:53 devn: (organize {:defn "foo" :def "buzz"} "path/to/new/file.clj")

2:53 and then have it rewrite the (ns) macro on the current file im reading these from

2:54 to point to file.clj and have it rewrite calls to foo and buzz so they are now namespaced :as k/foo, k/buzz

2:54 i think it would be nice to be able to toy with the organization -- i find breaking out a large clojure file to be a bit tedious, but like i said maybe im doing it wrong

2:55 for instance, clojure.core is like 6000 lines of code, so it can't be that bad, right? :)

2:55 _na_ka_na_: devn, clojure.core is an exception :P

2:55 tomoj: (defn foo [] (let [foo (fn [] 2)] (+ (foo) 3)))

2:55 good luck

2:56 devn: oh...right... :X

2:56 maybe tcrayford has solved this much for me?

2:56 * devn looks at clj-refactoring on github

2:57 devn: https://github.com/tcrayford/clojure-refactoring

2:59 tomoj: that's not so hard to parse, though, is it?

2:59 i mean i can imagine a few rules that you continuously apply as descend

2:59 tomoj: maybe, I dunno

2:59 devn: as you* descend

3:00 tomoj: I know there's some undocumented compiler api that can help

3:00 which it looks like tcrayford is thankfully not using

3:00 bobo_: oh, i like that clojure-refactoring. ive been wanting something like it!

3:00 devn: if var-in-question occurs after the most recent let and is the first of the args inside a [] you can ignore the replacement of this var until you reach the end of the let's scope

3:00 something like that?

3:01 bobo_: it's great. really fun to play with to refactor thread-first/last and test it out and see where it fits without rewriting your code

3:01 tomoj: let is not the only form that introduces local bindings

3:01 but maybe you could hack it

3:01 devn: absolutely not, but you could enumerate those

3:01 amalloy: tomoj: stole my thunder there

3:01 bobo_: but why do i need to add it as a dev-dependency? shouldnt i just have to add it to emacs?

3:02 devn: you'd need something like ctags or something along those lines...

3:02 actually swank has that "Who Calls?" functionality

3:02 tomoj: yes, but it's dumb

3:02 devn: dumb or not it does a good job of laying out the options i have in front of me

3:02 tomoj: for clojure at least

3:03 I mean that it will pick up (foo) as calling foo even if it's really a local binding

3:03 devn: yeah -- hm

3:03 any other ideas on how you'd do it?

3:04 maybe meta-data...

3:05 that'd be easy to do as you were hacking, simple tagging based on functionality, :functionality 'utils'

3:05 'support/utils' etc.

3:06 tomoj: I find that my big files usually require skilled chainsaw operation, sometimes dynamite

3:08 _na_ka_na_: tomoj, how is that foo above a problem?

3:08 i would like something like this: (defn bar ..) (defn foo .. (let [bar ..] (bar ..))) would be a problem

3:08 amalloy: devn: metadata wouldn't help you resolve anything, and nobody would want to type it out. why write ^{:group :utils} "just in case", instead of just making utils.clj now?

3:08 _na_ka_na_: amalloy, i'm with you on that

3:09 tomoj: that local binding that clobbered the function name occurred inside the function was just a curiosity of brevity

3:09 that _the_ local binding...

3:11 devn: tomoj: of course, but it would be nice to make it work there as well

3:11 ive seen that happen more than one

3:11 _na_ka_na_: tomoj, would you know if that compiler API you mentioned above gives: what all fns a given fn depends upon

3:12 tomoj: absolutely not

3:12 I mean, absolutely.

3:12 devn: unless i hacked it to do so

3:12 tomoj: I absolutely know that it absolutely does not

3:12 it's far more low level than that

3:13 devn: does it occur after a defn or a def, is it part of a binding context?

3:13 i think those are two things you can figure out... no?

3:14 tomoj: are you working with unmacroexpanded code?

3:14 devn: I mean -- "Who Calls" should respond in that fashion...

3:14 yes

3:14 tomoj: then defmacro kinda screws things up, doesn't it?

3:14 ..still, you can probably get most cases right without too much trouble

3:14 _na_ka_na_: ya unmacroexpanded code will be much tougher to deal with

3:16 tomoj, does that mean that IDE refactoring tools for Clojure are a distant dream

3:18 tomoj: c-in-c I think will bring the dream a bit closer, but it's not my dream and so I don't really know anything about it

3:19 bobo_: it is alot harder to make IDE refactoring tools for any dynamic language.

3:20 _na_ka_na_: that's kind of sad

3:20 tomoj: I guess I should have done the IDE thing before

3:20 LauJensen: Morning all

3:21 tomoj: hard to understand the attraction never having used one

3:26 amalloy: tomoj: eclipse's java support is a tremendous boon; emacs is equally good for CL but in different ways

3:26 it's not as good for clojure, yet, but it's still a huge improvement over, say, gedit

3:27 tomoj: I remember some blog post which tried to set up a dichotomy here

3:27 and suggested the excuse "clojure's so good we don't need an IDE"

3:27 amalloy: tomoj: between what and what?

3:28 tomoj: focus on language and focus on tools

3:29 maybe this one http://osteele.com/archives/2004/11/ides

3:30 amalloy: there's some function around that returns a reversed view of a vector in constant time, isn't there?

3:30 $findfn [1 2 3 4] [4 3 2 1]

3:31 tomoj: rseq?

3:31 sexpbot: Execution timed out.

3:31 [clojure.core/rseq clojure.core/reverse]

3:31 amalloy: ah, thanks tomoj (and sexpbot eventually)

3:31 clojurebot: sexpbot is not a clojurebot

3:31 _na_ka_na_: :P

3:32 someone's jealous

3:32 tomoj: I was peeking at that and subseq/rsubseq earlier

3:32 wonder why I never noticed the latter two even though their metadata says 1.0G

3:33 Fossi: wth does findfn do?

3:34 amalloy: $findfn 3 2 1

3:34 sexpbot: [clojure.core/bit-xor clojure.core/rem clojure.core/- clojure.core/unchecked-subtract clojure.core/quot clojure.core/compare clojure.core/mod clojure.core/unchecked-remainder clojure.core/bit-and-not clojure.core/unchecked-divide]

3:34 amalloy: Fossi: finds functions f such that (f 3 2) == 1

3:36 tomoj: $findfn *ns* '+ nil

3:36 sexpbot: [clojure.core/ns-unalias clojure.core/ns-unmap clojure.core/extend clojure.core/descendants clojure.core/prn clojure.core/print clojure.core/alter-meta! clojure.core/parents clojure.core/get clojure.core/underive clojure.core/ancestors clojure.core/println clojure.core/pr]

3:36 tomoj: &(+ 1 2)

3:36 sexpbot: ⟹ 3

3:36 tomoj: impressive

3:36 amalloy: *chuckle*

3:37 tomoj: i think there actually is a vulnerability in there if you work hard enough

3:38 i'm not sure exactly where it is, but ns-unmap isn't as carefully sandboxed as the eval plugin

3:48 s/ns-unmap/findfn

3:48 sexpbot: <amalloy> i'm not sure exactly where it is, but findfn isn't as carefully sandboxed as the eval plugin

3:50 tomoj: huh..

3:50 &*ns*

3:50 sexpbot: ⟹ #<Namespace sandbox6382>

3:50 tomoj: $findfn *ns* "sandbox6382"

3:50 sexpbot: [clojure.string/trim clojure.string/lower-case clojure.core/munge clojure.core/str clojure.core/namespace-munge clojure.contrib.string/as-str]

3:50 tomoj: $findfn 'clojure.core :only () nil

3:50 sexpbot: [clojure.core/prn clojure.core/print clojure.core/refer clojure.core/apply clojure.core/println clojure.core/pr clojure.core/print-special-doc]

3:50 tomoj: &(+ 1 2)

3:50 sexpbot: ⟹ 3

3:50 tomoj: how???

3:53 guess it's a good thing so I didn't totally bork sexpbot..

4:59 LauJensen: Is there anything in clojure-/javaland which has the same capabilities as Solr but is suited for use in a desktop client?

5:01 Fossi: standalone solr?

5:03 LauJensen: Fossi: Havent come across that before, looking into it

5:10 Fossi: AFAIK there is no option to run Solr outside of a servlet container of some sort

5:14 Fossi: hmm. i thought there was a standalone version

5:16 but maybe i'm confusing using it in your own servlet vs in it's own

5:16 so there's still a container (just your own)

5:17 but i guess one could at least use lucene

5:20 well, i guess you could also deploy with a standalone jetty

5:22 LauJensen: Jetty is an option, but Im afraid that on certain clients that will spawn some firewall warnings

5:22 Fossi: might be

5:23 bobo_: LauJensen: you could use lucene without solr?

5:24 LauJensen: bobo_: How much does solr add to lucene?

5:24 bobo_: not sure, mostly the restfull stuff i think

5:24 never used solr

5:24 LauJensen: Interesting, I'll check it out

5:26 It doesnt say so under features, but can I assume that Lucene reads .doc, .pdf, etc as Solr?

5:26 ah wait, no. Thats one of the things Solr adds

5:27 bobo_: seems weird to require a servletcontainer for things like that

5:28 LauJensen: Solr imports Tika, http://tika.apache.org/0.8/formats.html

6:41 mduerksen: chouser: [14:17:26] chouser: isn't there another way to say (iterate inc 0) ? yes, there is: (range) ##(doc range)

6:41 sexpbot: ⟹ "([] [end] [start end] [start end step]); Returns a lazy seq of nums from start (inclusive) to end (exclusive), by step, where start defaults to 0, step to 1, and end to infinity."

7:09 LauJensen: mduerksen: It seems odd that chouser would ask that question, since I know, he knows the answer

7:17 mduerksen: LauJensen: rereading the conversation, i think i might have got the context of that question wrong,

7:22 now i feel kinda goofy :)

7:30 LauJensen: hehe, it happens a lot on IRC - Though I think you're the first to educate an author of Clojure books on the use of range :)))

7:43 Berengal_work: In interfacing with some Java code, I need to subclass an abstract class and pass that class into a method. Is there a better way of doing this than gen-class?

7:43 cemerick: Berengal_work: proxy is your only other built-in option for concrete inheritence.

7:44 Berengal_work: cemerick: proxy doesn't give me a class, it gives me an instance

7:44 cemerick: It produces instances of an anonymous class, so you'll not be able to refer to the class by name (if that happens to be important to you).

7:44 Berengal_work: The method in question takes in a class object

7:44 Fossi: hmm nice design

7:44 cemerick: Berengal_work: which API is this?

7:45 Berengal_work: cemerick: It's a homemade one... -_-

7:45 Fossi: Berengal_work: then hit whoever designed that with a large stick

7:45 cemerick: Berengal_work: is the passed class going to be doing e.g. .newInstance, etc?

7:45 Fossi: won't solve the problem, but makes you feel better

7:45 Berengal_work: cemerick: Yes, that's the idea

7:46 Fossi: There are legitimate cases for passing class objects around in Java (even though this isn't one)

7:47 Fossi: yeah, and most of them are crude workarounds for generic problems :(

7:47 or problems with generics rather

7:47 cemerick: Berengal_work: looks like proxy classes don't respond well to .newInstance. gen-class would appear to be your best bet.

7:48 Or, you can use the ASM built into Clojure to build a concrete inheritence class-generation form. ;-)

7:48 Berengal_work: cemerick: gen-class works, but it sucks for dynamic development. I have to compile the project AOT to be able to play with it

7:48 cemerick: mind you, once I have the class, redefining the methods works fine

7:49 cemerick: Berengal_work: When one needs externally-referenceable classnames, that's the tradeoff currently involved. *shrug*

7:50 Berengal_work: cemerick: deftype seems to manage, but it only does interfaces

7:52 cemerick: Was the ASM comment in jest, or is it a legitimate way of doing things_

7:52 )

7:52 ?

7:52 cemerick: Berengal_work: I meant statically-referenceable classnames

7:53 Berengal_work: They don't need to be statically referenceable, as in I don't need them to be available from inside Java code

7:53 I just need a class that's a subclass of an abstract class, and that I can call newInstance on

7:54 cemerick: Berengal_work: deftype, definterface, etc are all built on top of ASM, so you certainly *could* build a form that generated concrete classes.

7:55 Not many people touch the ASM stuff directly, though. You need to know bytecode well. :-P

7:55 Berengal_work: deftype/record not supporting concrete inheritence was an intentional design decision

7:56 Fossi: well, asm isn't *that* lowlevel

7:56 Berengal_work: cemerick: I'm well aware of that, and I support that decision, but in this case it doesn't work out that well.

7:57 cemerick: Fossi: well, it certainly helps to know what's going on under the covers :-)

7:57 Berengal_work:

7:57 Fossi: Berengal_work: could you subclass/change the receiver of the class param?

7:57 cemerick: bah

7:57 Berengal_work: Anyway, gen-class /works/, just not as seamlessly as I'd want it to.

7:57 Fossi: or is that out of your control as well?

7:57 Berengal_work: Fossi: It's a static method, so no

7:58 Fossi: yeah, well, sounds like a heap of trouble :)

7:58 good luck, time for more javascript now ;)

7:59 cemerick: Berengal_work: Yeah, it's a blind spot in the interop stuff, but also an edge case AFAICT.

8:00 Perhaps someone will eventually need to do that sort of thing a lot, and a dynamic defclass (or whatever) form will result.

8:01 Berengal_work: cemerick: Maybe. I don't know much about the clojure internals, but from what little I've seen it seems it should be possible to make a modified gen-class that loaded the resulting class instead of writing it to disk

8:01 If that's the case then making defclass would be rather easy

8:03 Anyway, it doesn't hinder anything. It just makes things a little bit uncomfortable during development

8:03 cemerick: Sure, though I suspect most people would probably prefer inline method bodies.

8:11 LauJensen: Does anybody know what a letter of "no objection" is ?

8:20 Berengal_work: cemerick: Hillarious, (if (not *compile-files*) (compile (symbol (str *ns*))) `(macro expansion ...)) works :P

8:21 anars: LauJensen: if you have a letter of no objection for, say, a building, thenit's a confirmation than you can continue to use the building.

8:21 then it's*

8:21 that*

8:21 cemerick: Berengal_work: what do you mean, "works"?

8:21 Berengal_work: cemerick: That way it'll generate the class

8:21 LauJensen: anars: okay. So the one sending the letter is giving up his right to object to something?

8:22 anars: LauJensen: exactly

8:22 are you in luck?

8:22 LauJensen: Right, thanks a lot

8:22 cemerick: Berengal_work: you mean, from a gen-class?

8:22 Berengal_work: cemerick: yes

8:22 cemerick: That doesn't sound right at all.

8:24 Berengal_work: cemerick: No, it's an absolute kludge, but it does what I wanted

8:24 cemerick: Berengal_work: yeah, there's no provision at all for loading gen-class-generated classes at runtime.

8:25 Berengal_work: either I entirely misunderstood what you're trying to do, or you're seeing a previously-generated class

8:25 Berengal_work: cemerick: I'm not seeing a previously generated class at least

8:26 cemerick: I have a macro that, if called when *compile-files* is false, compiles the current namespace, else it expands to the gen-class definition

8:28 cemerick: Berengal_work: Perhaps I'm just dense this morning. I'm not sure what that gets you -- compiling the current ns isn't going to give you a class at runtime.

8:31 Berengal_work: cemerick: It does give me the class in the repl

8:38 cemerick: Berengal_work: My confusion stems from the fact that gen-class is a no-op if *compile-files* is false. https://github.com/clojure/clojure/blob/master/src/clj/clojure/genclass.clj#L612 Given that, compiling the current ns won't produce the class named in any gen-class form.

8:41 Berengal_work: ah, see gen-and-load-class. It's exactly what you're looking for.

8:41 I'd forgotten about that. :-(

8:42 apgwoz`: hey all, so, i'm using clojure 1.2, and i thought for sure that (duck-streams/with-in-reader socket (read-line)) should work, but it doesn't. looking at the source seems that it works with a BufferedReader or LineNumberingPushBackreader.. does this sound right?

8:47 Berengal_work: cemerick: Ah, thanks

8:49 fliebel: morning

8:53 Berengal_work: cemerick: Also, compile sets *compile-files* to true

8:53 cemerick: good point :-)

8:54 Berengal_work: in any case, compiling a namespace simply won't give you a corresponding class at runtime, unless your macro is doing something extraordinarily clever.

8:56 Berengal_work: cemerick: When compiling, the macro emits a gen-class declaration. I don't know exactly how class-loading works, but it seems it's loading it when it's first referenced.

8:56 ... and I can't find gen-and-load-class ...

8:57 chouser: gen-and-load-class has been gone for a long time

8:58 it did what you want, except apparently behaved badly enough in some circumstances to warrant removal.

9:00 Berengal_work: chouser: Probably because evaluating the same declaration more than once causes the jvm to throw a hissy-fit

9:01 chouser: I think it may have had logic that attempted to avoid that by printing a warning if you changed the def and reloaded it

9:01 cemerick: chouser: it's in head right now?

9:02 chouser: gen-and-load-class is??

9:02 cemerick: yup

9:02 https://github.com/clojure/clojure/blob/master/src/clj/clojure/genclass.clj#L700

9:03 chouser: wrapped in (comment)

9:03 * cemerick *facepalm*

9:03 chouser: took me a moment too

9:03 cemerick: OK, that's it, I'll be back in an hour. :-P

9:05 Berengal_work: You could maybe get around it by loading each class defined this way in a separate classloader

9:06 ... I seem to be full of awful hacks today...

9:08 LauJensen: ClojureQL 1.0.0 is now released, info on http://clojureql.org

9:12 fliebel: LauJensen: Congrats!

9:13 LauJensen: thanks :)

9:14 fliebel: This is going to give people a hard time, deciding what is more 'cool', to use a noSQL db, or a functional DSL on a SQL db. ;)

9:14 LauJensen: So you're saying I should write a nosql backend for cql ? :)

9:15 fliebel: LauJensen: If that makes sense, it would be total awesomeness. Otherwise: no, just that both noSQL and CQL are cool :)

9:16 LauJensen: Well, relational algebra was cooked up for relational databases. But it would be fun to see if I could make the connection. The interfaces are über pleasant to work with, if I do say so myself

9:17 fliebel: LauJensen: You should have a look at Django, someone managed to get their ORM to work with CouchDB, IIRC.

9:18 LauJensen: I'll take a look at Couch and see what can be done

9:18 Berengal_work: Couch is pretty much "object" oriented already, isn't it?

9:18 fliebel: LauJensen: FYI: Clutch has a Clojure view server.

9:18 Berengal_work: At least compared to relational databases

9:19 LauJensen: Berengal_work: I think they call it 'document oriented'

9:19 fliebel: Berengal_work: I'd say document orientated. But they use map/reduce.

9:20 bobo_: A column database is probably more suitable for relational algebra then a document store? ie maybe redis rather than couch?

9:20 * fliebel 's ego is running http://clojurewise.blogspot.com/2011/01/clojure-in-2010.html to check how far down he is in the list.

9:23 LauJensen: bobo_: You might be right, but I'll have to check both of them out to see if it makes sense at all

9:23 fliebel: bobo_: I don't know Redis, but from Wikipedia, it seems like a kay-value store: http://en.wikipedia.org/wiki/Redis_(data_store)

9:24 Berengal_work: LauJensen: Would it be a good idea to make it possible to bind columns selected to names?

9:24 LauJensen: Berengal_work: Im not sure

9:24 bobo_: fliebel: yes, and key value stores can be treated as column databases

9:25 maybe cassandra is even more suitable? never used it

9:25 Berengal_work: LauJensen: Having to manually get the values out of records after I've just namned them all the select statement is one of my major annoyances with SQL

9:25 *in the select

9:25 bobo_: the biggest annoynace in rdbm is to create tables and change tables

9:26 LauJensen: Berengal_work: Well, with ClojureQL you can count down on the work some

9:27 Just looked at redis - It looks like you could somewhat quickly write a backend for CQL.. I'll see if I can find some time this week unless somebody else does it first *hint* *wink*

9:27 Berengal_work: LauJensen: Well, writing the SQL has never really been an issue with me. What's annoying is dealing with the ceremony around the result sets and records

9:28 bobo_: LauJensen: i toyed with the idea to write one. but i never have any time =(

9:28 LauJensen: (let [cols [:id :name :wage]] (with-results [r (project (table :users) cols)] ......)) that way you only write your columns once Berengal_work

9:28 bobo_: Berengal_work: well, that depends on the language? in java if you use simplejdbcTemplate its kinda pleasant

9:29 fliebel: LauJensen: If I was to attempt it, I'd do Couch anyway. Not for any technological reason whatsoever. This is the Django thing, btw: https://github.com/benoitc/couchdbkit

9:29 Berengal_work: LauJensen: Ah, so with-results binds the columns? I missed that

9:30 LauJensen: Berengal_work: No, Im just showing you, that your var containing the column names, can both be pushed into the sql statement, and extracted later, like [{:keys cols}] so you save the added layer of extraction

9:30 with-results is just lazy eval of f on the resultset

9:31 fliebel: looks simple enough

9:32 fliebel: LauJensen: Until I actually need it, it's on my somewhere-in-the-next-ten-years list.

9:35 Berengal_work: LauJensen: I must be missing something. Are you talking about destructuring the record using {:keys cols}?

9:35 raek: anyone have a recommendation of how to quickly render a preview of one's README.md file?

9:36 fliebel: raek: Uhm, take a Markdown parser, and open it in your browser?

9:37 raek: fliebel: yes, something like that. is there any good command line program for that?

9:38 fliebel: raek: Probably just the original Perl version, or something in Clojure. One moment...

9:38 raek: There's markdownj, Showdown via Rhino, and Pegdown.

9:39 Berengal_work: pandoc's also neat

9:39 raek: fliebel: ok, thanks!

9:45 fliebel: harhar, Bash rulz! Clojure took ages to compute irc chat lines/user and ran out of memory. Bash did it instantaneously: ls . | xargs cat | grep "<b>fliebel" | wc -l 2437

9:46 Obvious: that's not bash, that's xargs, grep and wc.

9:48 fliebel: Obvious: When I wrote something that (println "something"), would you say I used Clojure, or println?

9:49 LauJensen: raek: http://github.github.com/github-flavored-markdown/preview.html

9:50 raek: LauJensen: oh. that's exatctly what I needed. thanks!

9:50 Obvious: fliebel, you could write calls to xargs, grep and wc with Runtime.exec from clojure, you can't write a call to clojure's println with bash.

9:51 LauJensen: raek: np, you can also roll your own quite quickly if you like

9:51 (defn markdown-to-html [txt]

9:51 (let [cx (Context/enter)

9:51 scope (.initStandardObjects cx)

9:51 input (Context/javaToJS txt scope)

9:51 script (str showdown

9:51 "new Showdown.converter().makeHtml(input);")]

9:51 (try

9:51 (ScriptableObject/putProperty scope "input" input)

9:51 (let [result (.evaluateString cx scope script "<cmd>" 1 nil)]

9:51 (Context/toString result))

9:51 (finally (Context/exit)))))

9:54 fliebel: Who wrote the #clojure statistics thing?

9:55 lpetit: hello

9:56 fliebel: lpetit: hi

9:56 abedra: you mean encanter?

9:56 fliebel: abedra: No, http://clojurewise.blogspot.com/2011/01/clojure-in-2010.html

9:56 abedra: ah

9:56 fliebel: He uses encanter though.

9:56 abedra: yes

9:58 LauJensen: Is encanter an alternative to incanter?

9:59 fliebel: LauJensen: Not that I know, I think it was a typo.

9:59 LauJensen: I thought so at first, but when you both said it, it got me wondering

10:01 abedra: yep typo

10:02 early morning

10:08 raek: what would be a good name of an 'assoc' that throws an exception if the key is already in the map?

10:08 blablubb: hey all, do you know of any time schedule for the stable clojure 1.3 release?

10:09 fliebel: blablubb: Clojure/core doesn't seem to like roadmaps, so I guess no-one know, not even Rich.

10:10 raek: assoc-once?

10:10 blablubb: the alpha releases seemed to have a month distance it seemed ;)

10:11 fliebel: raek: Or just add?

10:11 raek: hrm

10:14 fliebel: raek: Or (assoc-unless map identity key)

10:15 raek: I like assoc-once

10:15 blablubb: it's definitely very precise ;)

10:17 fliebel: raek: The oposite would be fun for ad-hock records. e.g. you can't add new keys.

10:20 blablubb: hmm I am currently involved to perform perfomance tuning of my code which is pretty slow right now

10:21 fliebel: blablubb: Slow compared to what?

10:21 blablubb: do you know any resources that discuss issues of performance pitfals in clojure?

10:21 fliebel: blablubb: Sure, one moment.

10:23 https://groups.google.com/group/clojure/browse_thread/thread/3c759739c265d14d/1daa9744a3e19704

10:24 blablubb: thanks. I am going to read into it :)

10:24 fliebel: blablubb: I short: Clojure boxes primitive data, on long sequences be sure not to hold onto the head, do no more work than is needed, multithreading does not always pay off.

10:24 blablubb: This is the second page, fyi.

10:25 Starts here: https://groups.google.com/group/clojure/browse_thread/thread/3c759739c265d14d/073475ace2810b94

10:27 * fogus` it's official. http://blog.fogus.me/2011/01/05/the-marginalia-manifesto/

10:31 Berengal_work: The jvm needs some support for lightweight preemptive multitasking

10:31 chouser: in some way that is different from threads?

10:31 Berengal_work: In a way that's more lightweight than native threads

10:32 raek: the executors framework might solve some of the problems

10:32 Berengal_work: raek: Not preemptive...

10:32 chouser: agents solve some related problems

10:33 Berengal_work: agents too aren't preemptive

10:35 chouser: in what way?

10:35 Berengal_work: Put enough agents in an infinite loop and the entire agent system stops

10:36 chouser: if you have one processor and an agent running on it, and send an action to another agent, both agents will share the one processor

10:36 Berengal_work: Yes, using two different native threads

10:36 Unless I've missed something

10:36 chouser: yes, but the 1000 other idle agents aren't using any native threads at all

10:36 Berengal_work: Indeed, but what if they're not idle?

10:37 chouser: then they are. :-)

10:37 I only said that agents solve *some* related problems.

10:37 there are cases when raw Java threads or Executors are too heavy where agents are not.

10:37 Berengal_work: Yes, but the preemptive part is important

10:38 chouser: there may be other cases where agents are also too heavy

10:38 Berengal_work: I thought agents used executors behind the scenes?

10:38 raek: they do

10:38 Berengal_work: So you spare yourself the cost of booting one up then

10:39 Anyway, I don't really use it often, but I miss the semantics of Haskell's forkIO...

10:39 raek: send uses a j.u.c.Executors.newFixedThreadPool and a j.u.c.Executors.newCachedThreadPool

10:40 hrm, I think I'm starting to realize what you are thinking about

10:41 Berengal_work: There aren't many multitasking frameworks where you can fire up 100000 threads and still have a useable machine

10:42 raek: a fixed number of native threads, but still preemptive?

10:42 Berengal_work: raek: Yes. Haskell preempts on gc. Erlang too works in a similar fashion, but I'm not familiar with it

10:43 gc as in both allocation and collection, that is

10:43 raek: I don't think java/the jvm has any way of pausing the a running in one thread and resuming it in another

10:44 (if I'm wrong, please tell me)

10:44 Berengal_work: No, I've looked for a way the last hour. The only relevant thing I found was a paper from about 10 years ago

10:45 http://www.xcf.berkeley.edu/~jmacd/cs262.pdf

10:45 raek: something like that could perhaps be accomplished by thread interruption, but that would only work for your own code

10:47 Berengal_work: If it requires code mofification, you could get away with a custom trampoline and a manual cps transformation

10:47 modification*

10:48 Which wouldn't be that comfortable to program in

10:58 fliebel: Berengal: That sounds nice… a trampoline that returns onto a queue, so you can do cooperative stuff.

11:14 StartsWithK: what would be the easiest way to load all forms from file so that line numbers metadata is attached to them but forms are not evaluated?

11:15 Berengal: fliebel: Still not preemptive on the runtime level. Context switching still happens at predetermined points in the code.

11:20 fliebel: Berengal: I'll have to google preemptive to see what you mean I think...

11:20 Berengal: fliebel: preemptive is the alternative to cooperative

11:21 fliebel: Basically, where cooperative tasks say "I'm done for now, someone else run", preempted tasks get told by the runtime "Your time is up, it's someone else's turn now"

11:21 fliebel: Berengal: But that is like regular threads work, right?

11:22 Berengal: fliebel: Yes, they're preempted

11:22 But kernel threads are also pretty expensive

11:23 For example, my machine starts becoming slow when I start about 1000 Java threads, even when they all mostly sleep

11:23 chouser: is there any option other than (a) the OS interrupting (therefore a real OS thread) or (b) having something in userspace periodically checking to see if it needs to give up control?

11:23 Berengal: While it manages 100,000 Haskell lightweight threads just fine, even when they all do some work

11:24 fliebel: chouser: Haskell is the user space in this case I think. Is this what they call 'green threads'?

11:25 Berengal: fliebel: Yes, but I think that's mainly a java term. They're called lightweight threads in Haskell at least

11:25 chouser: I don't know about Haskell. I think ruby and python check periodically in userspace to allow multiple "threads" to make "simultaneous" progress.

11:25 Berengal: (Other terms include user threads and fibers, I think)

11:26 Haskell does scheduling on allocation, gc and IO. Maybe some other times as well

11:27 Ruby and Python reschedule every few VM "tick", if I remember correctly

11:27 fliebel: So what about sending tasks to a thread pool?

11:27 chouser: I would expect there to be a Java lib for this actually, though I'm not seeing one.

11:28 Berengal: fliebel: They're not preempted.

11:28 fliebel: If you fill up the pool, new tasks are put in a queue and don't make any progress at all until some other task finish

11:29 chouser: hm, nevermind

11:29 without continutaion support, it may not be possible on the JVM.

11:29 fliebel: Berengal: You are right. So it's a JVM limitation then?

11:30 (not so related: what is clojure.langRT doing?)

11:30 Berengal: chouser: The paper I linked to earlier did a CPS transform on the code, but there seemed to be severe limitations. A limited form is possible, but you can't have the entire cake without changes to the jvm it seems

11:31 chouser: Clojure rejected CPS transform in favor of host-compatible calling conventions.

11:32 Berengal: I think you could get away with just changing the jvm implementation though, but I'm not intimately familiar with the specs

11:32 It would have some consequences for code that expects a thread to always run on the same native thread though

11:33 (Haskell has a separate forkOS call to fork a native thread when e.g. interfacing with C)

11:41 fliebel: What is 'the' way to use PersistentQueue in Clojure? JoC uses EMPTY and conj to add things to them. If I wanted to convert or add a sequence to a PersistenQueue, would I reduce conj over the items?

11:50 blablubb: humm if I have (deftype my-type ...) what exactly is the constructor "(my-type. ...)" in clojure? is it a function?

11:52 StartsWithK: blablubb, a real java class constructor where ctor args match your fields

11:53 (deftype Foo [a b c]) (Foo. 1 2 3)

11:56 blablubb: oh it's a macro expanding to new...

11:56 found it ^^

11:57 pdlogan: fliebel: if you want to "add all" from another collection there is an addAll method - unless you want more control over the order in which elements are added I don't see a reason not to use that.

11:57 fliebel: oh, except that method throws an exception

11:57 fliebel: right...

12:00 raek: reduce + conj = into

12:00 fliebel: raek: Oh, right :)

12:01 raek: so yeah, it seems like (into empty-queue some-coll) is the easiest way

12:01 (assuming (def empty-queue clojure.lang.PersistentQueue/EMPTY))

12:03 fliebel: Would this make sense, or is there a better way? (into clojure.lang.PersistentQueue/EMPTY (concat [f1 f2] fs))

12:05 raek: maybe you could replace the concat call with the somewhat unknown list

12:05 list*

12:05 (into clojure.lang.PersistentQueue/EMPTY (list* f1 f2 fs))

12:05 fliebel: oh, nice :)

12:11 raek: it would be nice to have (defn queue [& elems] (into clojure.lang.PersistentQueue/EMPTY elems)) in core

12:11 to complement 'vector', 'hash-set', etc...

12:11 chouser: such a thing is so simple and obvious, there must be some reason it isn't.

12:12 raek: sure. *shrugs*

12:22 chouser: I think it's because of the potential to confuse a persistent queue and a blocking queue -- similar terms, but very different things.

12:24 islon: how do I create a map programaticaly in clojure? something like (create-map ([:a 1] [:b 2]))

12:25 amalloy: &(into {} [[:a 1] [:b 2]])

12:25 sexpbot: ⟹ {:a 1, :b 2}

12:25 islon: oh thanks amalloy

12:25 totaly forget about into

12:25 amalloy: islon: or ##(zipmap [:a :b] (rest (range)))

12:25 sexpbot: ⟹ {:b 2, :a 1}

12:25 mrBliss: islon: there's also hash-map and array-map

12:26 islon: thanks

12:34 raek: fogus`: marginalia is wonderful.

12:35 fogus`: raek: Thank you. :-)

12:37 raek: not only does it present everything in a very readable form, but also in a very stylish one

12:38 oh no! the unicode snowman looks broken now...

12:39 Crowb4r: lol

12:39 raek: fogus`: I would suggest adding <meta charset="UTF-8"> to the head element

12:39 since clojure code is in UTF-8

12:39 fogus`: OK. Will do. Thanks

12:39 raek: and browser most often default to something else

12:39 s

12:50 islon: how do you check if a vector contains an element?

12:50 raek: islon: some

12:51 &(some #{3} [1 2 3 4 5])

12:51 sexpbot: ⟹ 3

12:51 raek: &(some #{7} [1 2 3 4 5])

12:51 sexpbot: ⟹ nil

12:51 islon: weird

12:51 raek: this operates in linear time, since it might have to look through every element in the vector

12:52 if you want to check this for many elements, consider using a set instead

12:52 since they have nearly-constant-time lookup

12:53 as you probably have seen, contains? works on vectors, but does something else

12:53 islon: i was hoping for something like (exists? 4 [1 2 3 4]) -> true but some will do the job

12:55 raek: yes, 'some' is a bit more general. it not only tells you if it found it, but also returns the "whitness"

12:56 islon: and receives a function as parameter

12:57 raek: yup. that function should return the argument if it is "it", and nil otherwise

12:58 which is what sets do when you use them as functions

12:58 islon: understood

13:22 StartsWithK: http://paste.pocoo.org/show/315430/ when i try to get line numbers from LineNumberingPushbackReader i am getting line number where forms end and not where they start

13:22 am i doing something wrong here?

13:24 http://paste.pocoo.org/show/315431/ clojure.lang.Compiler has this kind of strange looking loop where it first collects where form ended and then where is started, hmm..

13:27 hiredman: because you are reading the loop backwards

13:27 or, the loop is written backwards

13:28 StartsWithK: what do you mean by backwards?

13:29 lines increment, but they report line where form ends

13:35 mids: LauJensen: gratz on ClojureQL 1.0.0

13:35 LauJensen: mids: thanks! :)

13:48 hiredman: StartsWithK: if you write the loop out and unroll it from the for syntax it makes more sense

13:58 rata_: hi all

14:00 amalloy: hiredman: i guess i'm dense; i don't see what's backward there. it looks to me like get-line is always being called before get-form, and res is clearly associating each form with its corresponding meta

14:01 hiredman: amalloy: looking at the java code from Compiler

14:01 amalloy: oh

14:05 hiredman: yeah, although doesn't this result in the first form being read not having its LINE_BEFORE set? i guess it's out of context: LINE_BEFORE is probably initialized to zero somewhere

14:05 StartsWithK: amalloy, yes, default to zero

14:06 i think its all good, only thing it is missing is to manualy slupr all whitespace before reading next form

14:06 so i can mark start position, i think LispReader will do that internally

14:07 so, thanks ppl for help

14:20 fliebel: chouser, Berengal: Cooperative concurrency experiment: http://pepijndevos.nl/cooperative-concurrency-in-clojure

14:21 chouser: ParsistentQueue -> PersistentQueue

14:21 interesting.

14:21 fliebel: chouser: I'm still checking for errors myself as well. I must get used to posting to draft@posterous.com :S

14:31 Berengal: fliebel: That's interesting, and shows how simple custom execution semantics can be

14:35 fliebel: Berengal: :)

14:36 fogus`: fliebel: Really cool.

14:36 fliebel: fogus`: Thanks :)

14:38 tipair: Oh hi friends. Has anyone here embedded Clojure into a C# or Java app before?

14:39 (i.e. use clojure as a scripting language)

14:40 fliebel: tipair: I read about someone who made an wrapper for Clojure that allows it to be used in the JSR 323(or whatever) scripting bridge. You know… what Rhino runs in.

14:41 amalloy: tipair: someone posted to the mailing list recently about writing a ClojureREPL component for swing

14:41 but it was a closed-source project

14:41 clojurebot: project euler is http://ProjectEuler.net

14:42 amalloy: clojurebot: your mom is http://ProjectEuler.net

14:42 clojurebot: Ik begrijp

14:44 fliebel: tipair: http://code.google.com/p/clojure-jsr223/

14:45 amalloy: Do you have a link to that thread? Or do you know of any generic JSR 223 REPL?

14:45 cemerick: amalloy: really? The enclojure REPL component is out there already: http://www.enclojure.org/The+Enclojure+REPLs+%28Not+just+for+Netbeans!%29

14:45 amalloy: cemerick: they were doing something special with their repl. i didn't read very carefully

14:46 cemerick, fliebel: http://groups.google.com/group/clojure/browse_thread/thread/e4f7e37d3306daa4/4ce34bbcc3d8d59c?show_docid=4ce34bbcc3d8d59c

14:47 tipair: ^

14:50 Berengal: fliebel: http://hpaste.org/42769/lightweight_threads_and_stm <- example of Haskell's lightweight threads in action, by the way

14:51 ossareh: I love that clojure has ratio's... I hate that nothing else has ratios.

14:51 nothing else == riak and javascript

14:52 fliebel: ossareh: Riak? That's a DB, right?

14:52 ossareh: fliebel: ye

14:52 fliebel: a nosql db - pretty cool imho

14:53 fliebel: ossareh: Don't know about it. Does it have a REST API? Anyway, I guess you can implement ratio in JS yourself.

14:54 ossareh: fliebel: it does. I'm not of the thinking that writing a json parser in javascript to run on their db is a good idea.

14:54 fliebel: ossareh: Javascript IS a JSON parser… Javascript Object Notation ;)

14:57 ossareh: fliebel: I know, I'm pretty conversant with javascript. The issue here is that if you tell c.c.json to produce json of 3/4 it will spit it out as a number string mishmash which cases parsers to barf.

14:57 parsers other than c.c.json.

14:58 c.c.json switches over to a clojure form reader when it finds a number - since Ratio falls into that category it can parse and consume its own json but other things cannot parse it - like Riak.

14:59 on one hand this is fine -I'm asking it to jsonify something that doesn't exist in the json spec and it does the best it can. on the other hand it json has a well defined format and this breaks it.

14:59 fliebel: ossareh: If you use Riak only from Clojure, you can store your own representation for a ratio, like {"denominator":4,"devider":5} or whatever they're called.

15:00 ossareh: yeah, exactly. This is probably what I'll end up doing.

15:00 fliebel: ossareh: You know the Clojure functions the pull them out of a ration?

15:01 ossareh: (doc denominator)

15:01 clojurebot: "([r]); Returns the denominator part of a Ratio."

15:01 tipair: fliebel, amalloy: Cool, thanks. We're actually using ClojureCLR, truth be told, but that's awesome.

15:01 ossareh: (doc numerator)

15:01 clojurebot: "([r]); Returns the numerator part of a Ratio."

15:01 fliebel: ossareh: Ah, numerator was what I wanted to know :)

15:02 tipair: Heh, you should do a Clojure blog about the CLR. There is currently very little about CLR trick with Clojure :(

15:03 tipair: fliebel: If this works, it will be blogged about. :)

15:03 fliebel: Berengal: I am not yet able to read that kind of Haskell. If you feel like explaining it line-by-line, cool. Otherwise, I believe you on your word it's awesome :)

15:04 tipair: Where is the blog?

15:06 Berengal: fliebel: The short of it is it's making numThread (command line arg) threads. These wait for the ref runFlag to become True, before decrementing the counter. The main thread then waits a bit, to allow the other threads to settle in. It then sets the runFlag to True, and waits for the counter to reach zero

15:08 fliebel: 100,000 threads doing this takes 1.3 seconds in the interpreter (0.5 when compiled and run with 3 native threads)

15:08 fliebel: Berengal: Thanks :) What is <- for?

15:08 Raynes: Pulls a value out of the IO monad, iirc.

15:08 Berengal: Raynes: Well, any monad, but yes

15:08 Raynes: Right.

15:09 markskilbeck: Anyone know why I'm getting a 'unable to resolve symbol: setLayout in this context' exception? http://pastebin.com/EDtjsn7n

15:09 Berengal: It's basically assignment, except it can only do name shadowing

15:09 amalloy: markskilbeck: you want .setLayout

15:09 and .add, and .setSize...

15:09 fliebel: Berengal: Does this means it runs all those threads in a tight loop? when (not doRun) retry

15:11 Berengal: fliebel: It's a bit smarter than that. When an STM transaction fails, it doesn't actually retry until any of the vars touched change

15:11 fliebel: At least I think that's how it works. I'm not too familiar with the internals

15:11 markskilbeck: amalloy: of course. Danke!

15:11 fliebel: Berengal: Thanks :)

15:12 Berengal: Speaking of retry, does clojure have that?

15:12 fliebel: Berengal: Refs have hooks, so you could write it :)

15:13 chouser: An explicit retry for STM transactions? no.

15:13 you can throw an exception yourself and start the transaction over again if you'd like.

15:14 Berengal: fliebel: Could you also implement orElse?

15:15 fliebel: Berengal: Dunno… what does it do?

15:15 Berengal: fliebel: it takes two transactions as arguments. If the first one retries, it runs the second

15:16 It allows for nice select-like transactions

15:17 ossareh: woo - haskell kinda looks like python and erlang had a kid.

15:17 fogus`: Berengal: It also requires read-tracking

15:19 Berengal: fogus`: orElse, you mean?

15:20 fogus`: Beregal: Yes. It also conflates flow control and transactions.

15:20 Berengal: fogus`: I think orElse only chooses on an explicit retry. If a transaction discovers it won't be able to commit, there's no use in trying the second transaction, since that won't be able to commit either. The entire transaction as a whole has touched dirty bits and needs to be redone

15:22 I could be mistaken. As I said, I'm no expert on the internals

15:24 fogus`: I am not an expert in Haskell's impl (or Clojure for that matter), but I believe that I my points describe why orElse was excluded.

15:25 Berengal: Clojure transactions see a snapshot of the refs from when the transaction started, right?

15:25 fogus`: The flow control should happen outside of a transaction to determine if work is needed, then if it is, then it should be done in a transaction

15:26 amalloy: Berengal: unless you modify the ref inside the transaction, in which case you see that value

15:26 fogus`: Berengal: And without orelse, there is no real need for retry (as you alluded to) :-)

15:26 Berengal: fogus`: It's rather the other way around. Retry by itself can be useful for waiting on a value

15:27 amalloy: Does this mean that a transaction won't fail until it tries to commit?

15:27 fogus`: Berengal: That would require blocking no?

15:28 Berengal: fogus`: It would block the thread, yes

15:28 amalloy: Berengal: correct

15:28 Berengal: Which is the point of waiting

15:28 amalloy: because it's okay to have two transactions modify the same ref, so long as they both commit the same value

15:28 Berengal: amalloy: Or they use commute

15:29 fogus`: If you see my earlier Haskell example, I use retry twice to wait. First to wait for a runFlag to become true, then to wait for the counter to reach zero

15:30 fogus`: Beregal: If you want to block for a value then something other than a transaction is likely better.

15:31 Berengal: fogus`: Not if you want to block for several values

15:32 fogus`: That's sort of the point of transactions: atomic changes to multiple shared states

15:32 In this case, atomic reads of multiple shared states

15:32 hiredman: Berengal: you can easily return a collection of a consistent set of read values from a transaction and block outside of the transaction

15:33 Berengal: hiredman: How can you block on multiple values at the same time outside of a transaction?

15:33 fogus`: The point of Clojure transactions are that they should never block the world

15:34 Berengal: fogus`: The world, no, but the thread?

15:34 hiredman: Berengal: you read, return the collection, if the values are not what you want you read again

15:35 Berengal: hiredman: But once you exit the transaction, those values could become inconsistent in relation to eachother again

15:37 fogus`: Berengal: Well, time keeps on going. It never stops. :p

15:37 hiredman: Berengal: uh, no they wouldn't

15:37 values are immutable

15:38 the refs may end up pointing to different values, but they would with retry inside a transaction anyway

15:38 Berengal: hiredman: Are you familiar with the dining philosophers problem?

15:39 hiredman: Berengal: how does that require blocking?

15:39 Berengal: hiredman: Each philosopher has to wait for both his forks to become available

15:39 hiredman: http://rosettacode.org/wiki/Dining_philosophers#Clojure

15:39 Berengal: So each fork is a ref containing either :available or :unavailable...

15:40 Crowb4r: lol, rosetta code. the guy who made that lives in the same town as me.

15:40 Berengal: hiredman: That implementation uses spinning

15:41 hiredman: Berengal: as opposed to?

15:42 Berengal: hiredman: Waiting, as in wait/notify

15:42 hiredman: what do you think retrying a transaction is?

15:42 Crowb4r: which the STM takes care of automatically correct?

15:42 Berengal: Crowb4r: Not in this case

15:45 hiredman: Berengal: so you are saying that doing whatever you do in haskell to retry a transaction waits on the references to be changed before retrying the transaction?

15:46 Berengal: hiredman: Yes, basically

15:46 It can spin, of course, if the values still aren't what you expected them to be

15:46 hiredman: you can do that with watchers on refs if you like

15:46 ,(doc add-watch)

15:46 clojurebot: "([reference key fn]); Alpha - subject to change. Adds a watch function to an agent/atom/var/ref reference. The watch fn must be a fn of 4 args: a key, the reference, its old-state, its new-state. Whenever the reference's state might have been changed, any registered watches will have their functions called. The watch fn will be called synchronously, on the agent's thread if an agent, before any ...

15:47 hiredman: you can add a watch to the refs you care about then block on those watches being called

15:47 Berengal: I guess that's true

15:48 Anyway, compare the related Haskell version http://rosettacode.org/wiki/Dining_philosophers#Haskell

15:49 hiredman: why?

15:49 clojurebot: http://clojure.org/rationale

15:50 hiredman: clojurebot: bzzt

15:50 clojurebot: Huh?

15:51 Berengal: hiredman: It's just where I'm coming from regarding explicit retry.

15:52 It's not explicit in the code, but it's inside the TMVar related functions, as opposed to in commit conflicts

15:52 hiredman: at work (biggest clojure code base I am familar with) we don't use the stm at all, little to no coordination between threads

15:53 Berengal: What kind of system is that?

15:54 hiredman: email processing

15:55 anytime the idea of cross thread coordination comes up we quickly remember that infact we have more than one machine we need to coordinate across and maybe there is some way to do with out

15:59 solussd: why?

15:59 clojurebot: why not?

15:59 solussd: why?

15:59 clojurebot: why not?

15:59 solussd: why not?

15:59 shortcircuit: why?

15:59 clojurebot: http://clojure.org/rationale

16:01 solussd: ,(println "why?")

16:01 clojurebot: why?

16:01 solussd: haha!

16:01 I'll ask the questions clojurebot.

16:03 Berengal: hiredman: Anyway, it's your comment about retry and orElse conflating control-flow and transactions is true, and it /does/ bother me somewhat, but on the other hand they're useful to have inside a transaction, and I'm not sure you could build them out of other primitives

16:05 Then again, Clojure and Haskell have different concurrency primitives. Maybe Clojure doesn't need retry and orElse

16:19 bendlas: Fun clojure quirk of the day:

16:19 ,[do 1 2 3]

16:19 clojurebot: 3

16:19 bendlas: ,#{do do do}

16:19 clojurebot: Duplicate key: do

16:20 bendlas: ,#{do}

16:20 clojurebot: nil

16:20 hiredman: interesting

16:20 amalloy: &(let [do 10] #{do})

16:20 sexpbot: ⟹ #{10}

16:20 fliebel: bendlas: Why does that wok?

16:20 hiredman: looks like a bug

16:21 bendlas: Compiler.java:6209

16:21 if (form instanceof IPersistentCollection)

16:21 instead of

16:21 ,(class '())

16:21 clojurebot: clojure.lang.PersistentList$EmptyList

16:22 hiredman: well, you want clojure.lang.ISeq

16:23 bendlas: ISeq?

16:23 hiredman: yes

16:23 ISeq is more or less everthing that prints with parens

16:24 bendlas: yes, but I'm quite sure that special forms are supposed work only as source literals

16:24 which means PersistentList

16:24 hiredman: no

16:24 because macros can produce seqs

16:24 bendlas: oh

16:25 pdk`: producing seqs is pretty much what makes macros tick

16:25 pdlogan: it might be easier to ask than search... a while back I had a link to an early implementation of clojure in common lisp... anyone have that handy?

16:25 bendlas: but seqs are no IPersistentCollections, are they?

16:25 hiredman: they are, I believe

16:26 well, at least concrete instances typically are

16:26 ISeq may not be

16:26 fliebel: bendlas: Pretty much everything is a IPersistentCollections, except maybe numbers :P

16:26 hiredman: that whole if seems suspect

16:26 [def x 1] seems like it would run too

16:27 bendlas: indeed, ISeqs are IPersistentCollections

16:27 bmh: I just came across assoc-in, is there anything confounding the existence of a dissoc-in?

16:27 bendlas: bmh, it's already in contrib afair

16:27 bmh: bendlas: oh. That's convenient. Where in contrib?

16:29 bendlas: http://richhickey.github.com/clojure-contrib/core-api.html#clojure.contrib.core/dissoc-in

16:29 hiredman: clojure and contrib have moved to the clojure github account

16:30 bendlas: yes, just noticed & updated bookmark

16:37 lambdatronic: Howdy folks. I'm running into trouble with a macroexpansion that works on 1.1.0 and 1.2.0 but not on 1.0.

16:37 qbg: lambdatronic: Whats the macro?

16:38 And what are you using Clojure 1.0 for?

16:39 lambdatronic: http://pastebin.com/0HV9SKng

16:39 I'm working with a legacy project that is build on 1.0. It's headed by someone else who doesn't want to change it.

16:39 qbg: Are you getting an exception?

16:40 lambdatronic: Anyway, it seems like kind of a strange thing, as I don't think I'm using any syntax that's not 1.0 friendly. Clearly I'm mistaken.

16:40 Yeah, the exception is: java.lang.ExceptionInInitializerError

16:40 No fun stacktrace info to go with that.

16:40 ossareh: what if you macroexpand-1 - same issue?

16:40 qbg: Why are you using eval?

16:41 hiredman: ew

16:41 that is a horrible macro

16:41 lambdatronic: Alright, provide a better one that does the same thing.

16:42 hiredman: hard to even read it, what is it supposed to do?

16:43 lambdatronic: The macroexpansion works fine as expected and returns the same result as with 1.1.0 and 1.2.0, so the problem is in the eval stage.

16:44 qbg: (defmacro defsource [name & body] `(defn ~(with-meta name {:source-code `(defn ~name ~@body)}) ~name ~@body))

16:44 hiredman: right, the macro is garbage, rewrite it to be clearer and it will work

16:44 qbg: Untested, something like that

16:44 hiredman: but it is so bad that, I am unable to get a clear picture of what you want from it, so if you have specs for what you want in english...

16:45 qbg: It seems to attach the source of the function to its var

16:45 lambdatronic: hiredman: The macro with-source-code is wrapped around any arbitrary def form to capture the source code of that form at read time and attach it to the metadata of the def'd var.

16:45 hiredman: it seems like you want to store the form in metadata

16:45 lambdatronic: hiredman: no need to be a troll. It was a simple engineering question.

16:45 hiredman: I am not trolling

16:47 lambdatronic: hiredman: Then you could offer a practical solution, or try testing the macro to see what it does.

16:47 hiredman: The pastebin example is pretty english readable.

16:47 hiredman: What do you think (get-source-code foobar) does?

16:47 hiredman: what do you expect it to do?

16:48 bendlas: lambdatronic: have you looked at clojure.repl/source in 1.2 or clojure.contrib.repl-utils/source?

16:48 hiredman: return the form? return the entire function body? I see eval called in the macro and the level of quoting is not immediately obvious

16:49 qbg: I wonder if porting source would be a better solution

16:50 bendlas: and yes the macro is ugly and non obvious

16:51 hiredman: for get-source-code I wouldn't even use a macro

16:51 (get-source-code #'foobar)

16:52 lambdatronic: Alright, I just solved it myself.

16:53 http://pastebin.com/2c0n1Tvs

16:54 bendlas`: and mutation means lurking bugs

16:54 lambdatronic: The solution was simply replacing ~(var-get (eval form)) with (var-get ~form).

16:54 Done

16:55 qbg: Your solution is limited to only defn statements. I want a general solution for arbitrary def-based forms. This is required because I am working in a domain-specific language with additional macros like defmodel, defcontext, defscenario that need to be wrapped genearlly.

16:56 hiredman: whether or not to make get-source-code a macro is a matter of opinion. I find the macro solution perfectly elegant in this case because I don't want to expose the internals of where I'm storing the source code in my public API. Again, this is part of a DSL for modellers who don't know clojure and are certain to screw up the #' reader-macro syntax.

16:57 hiredman: *shrug*

16:57 qbg: lambdatronic: Have you thought about having your own def* forms add :source-code themselves and then provide your own versions of the def forms from core that do the same thing?

16:57 lambdatronic: bendlas`: The only mutation happening here is that the var being def'd is interned twice in succession, first without the :source-code metadata and then by it. However, as these forms are chained in the same macro, I don't see any holes where bugs could get though.

16:58 qbg: lambdatronic: take a look at the result of (doc foobar) with your solution

16:59 lambdatronic: qbg: By abstracting this task into the with-source-code macro, I can embed it in all of my def* forms without having to repeat the logic an arbitrary number of times.

16:59 bendlas`: lambdatronic: yes, but as your solution proves, it does make a difference *when* the interning happens

17:00 with the eval, it happened *during* macroexpansion (as opposed to ~ which splices forms)

17:00 lambdatronic: bendlas`: I do see that now. For some magical reason 1.1 and 1.2 didn't seem to mind the compile-time interning, but 1.0 certainly is upset by it. Now it's resolved.

17:00 qbg: lambdatronic: This solution requires you use with-source-code everywhere

17:01 lambdatronic: qbg: I don't see your distinction. I place with-source-code in each of my def* macro definitions, and then it propagates perfectly well.

17:01 Without having to rewrite the core library or repeat the logic over and over in different def* macro definitions.

17:03 Thus (defmodel mymodel ...) would be defined as (defmacro defmodel [modelname ...] (with-source-code (def ...)))

17:03 And no one has to ever worry about it.

17:04 qbg: Do you really want the source of mymodel to be in terms of def and not defmodel?

17:04 Also, you macro drops docstring/arglists

17:05 lambdatronic: qbg: I had them in an earlier version that used gensyms, and it works fine in 1.1 and 1.2. This was a simplified version for 1.0.

17:07 qbg: I eval-ed the form at compile-time and captured the metadata off the interned var (which holds the docstring and arglists) and then assoc-ed the :source-code field onto that before reattaching it to the var.

17:08 qbg: I modified the second paste to a form that should work

17:08 You don't need eval here

17:08 lambdatronic: qbg: There isn't an eval anywhere in there. What are you referencing?

17:09 qbg: To get the docstring/arglists

17:09 lambdatronic: I didn't use eval.

17:09 qbg: "qbg: I eval-ed the form at compile-time and captured the metadata off the interned var"

17:10 lambdatronic: Yes, because you can't attach metadata to a def-ed symbol in a defmacro statement.

17:10 The metadata reader-macro is lost during macroexpansion.

17:11 Where is your pastie?

17:11 I don't see it at the link I provided.

17:12 qbg: lambdatronic: Unless that was a bug in 1.0, you can add metadata to a def'ed symbol in defmacro

17:13 http://pastebin.com/6LQzaenX

17:14 You use with-meta, not the reader macro

17:15 hiredman: well you want alter-meta

17:16 naeu: if I have compiled Foo.java to Foo.class and the class file is on the classpath and Foo isn't explicitly associated with any namespace, how do I refer to it from within clojure?

17:17 qbg: naeu: is Foo in the default package?

17:17 naeu: qbg: I'm not sure - how would I determine that?

17:17 lambdatronic: hiredman: you are thinking of vary-meta.

17:18 qbg: naeu: Do you use the package keyword in Foo.java?

17:18 naeu: nope - should I?

17:18 qbg: Default package in Java = bad

17:18 hiredman: whichever

17:19 qbg: You can't import from it

17:19 naeu: qbg: ah ok...

17:19 qbg: And you need to import Foo in Clojure to use it

17:19 naeu: qbg: so i just need to make up a package name for it

17:20 qbg: That should work

17:20 naeu: can I just say package foo;

17:20 qbg: Should work

17:21 Then Foo.class needs to be in foo on the classpath

17:21 naeu: ah..

17:22 you mean Foo.class needs to be in a dir called foo which needs to be a sub dir of one of the dirs in the classpath?

17:22 qbg: Correct

17:23 naeu: the repl says it's looking for foo__init.class

17:24 qbg: Use (import 'foo.Foo)

17:24 naeu: when i just have foo/Foo.class

17:24 qbg: Sounds like you are trying to use or require it instead

17:24 naeu: qbg: yeah, i was doign (use 'foo.Foo)

17:25 qbg: use/require are for Clojure namespaces only

17:25 naeu: qbg: i got it working

17:25 qbg: thanks very much :-)

17:25 qbg: Good

17:30 lambdatronic: qbg: Thanks for the help. I like replacing (first `('~form)) with `'~form. That's the solution I was looking for, but I somehow missed that particular combination while testing at the repl. Otherwise, the version you provided looks pretty much exactly like the one I created before I tried to solve the problem of preserving the previous metadata liks arglists and docstrings.

17:31 qbg: That led me down the path of gensyms, compile-time evaling the passed in form so I could extract the metadata off of the returned var and then using plain old def to attach the new metadata onto the original stuff.

17:33 qbg: Not sure where I slipped up back there with the simpler solution to capture the metadata after all, but ah, live and learn.

17:45 qbg: Maybe I should try Marginalia, but my willingness to type documentation seems to be negatively correlated to the distance my cursor is from code...

17:47 vIkSiT: hi all

17:59 ossareh: given an arbitrarily deep datastructure (of maps and vectors) how best to transform values of a particular type?

17:59 amalloy: ossareh: clojure.walk/postwalk?

18:00 * ossareh looks.

18:00 ossareh: dude, you can have my first born. You help me that much.

18:00 (and I'm not excited about a first born)

18:03 (inc amalloy)

18:03 sexpbot: ⟹ 2

18:04 ossareh: I think it would be cool if sexpbot actually tracked this value and provided a league table - somewhat like stackoverflow does.

18:09 Raynes: ossareh: That wouldn't be very difficult.

18:09 ossareh: Raynes: happy to help if you'd rather not do it.

18:11 Raynes: All of the values are stored in MongoDB, so they should be very easy to extract. Feel free to take a shot at it. The relevant plugin is https://github.com/Raynes/sexpbot/blob/master/src/sexpbot/plugins/karma.clj

18:12 lpetit: hi, enlive gurus there?

18:12 Raynes: ossareh: http://github.com/Raynes/sexpbot/wiki/Plugin-quick-start-guide Might be helpful if your unfamiliar with how sexpbot does things.

18:16 lpetit: i have a tree made of maps, following clojure.xml conventions, so it's consumable by enlive w/o problems. I have this parsley grammar which produces things for "(ns foo)" like {:tag :list :content [{:tag :symbol :content ["ns"]} {:tag :symbol :content ["foo"]}]}

18:16 (simplifying a little the tree)

18:17 with enlive selectors, I'm able to get the namespace name by doing smt like : (html/select m [ :list :symbol])

18:19 but where things get interesting, is when I introduce handling of metadata: "(ns ^:foo ^:bar name)"

18:19 Now the name "name" can theoretically be nested within 0..n metas.

18:20 And the question: I'm having a hard time figuring out how to write the selector for this (if even possible in one pass) ?

18:22 amalloy: lpetit: i don't know anything about enlive, but could you get xpath involved?

18:24 lpetit: if you know of a library which can consume clojure.xml datastructures, maybe (I cannot afford the time penalty of transforming clojure.xml datastructures back to DOM)

18:24 amalloy: /ns/**/symbol/last() or something like that - it's been a long time since i used it

18:25 lpetit: not so simple. I don't want to match e.g. fake in "(ns ^{:baz 'fake} ns-name)"

18:26 erikcw1: In my main namespace, I have a var named settings which is an empty {}. My -main fn sets the contents of settings with another def and conj based on some command line args. I'm trying to access the contents of this map from another namespace to pull out some of the settings. When I try to compile with lein into an uberjar, I get a traceback saying "No such var: lb/settings". What am I missing? Is there a better way to handle app wid

18:26 settings?

18:26 amalloy: lpetit: there's a difference between symbol/last() and symbol[last()]

18:28 lpetit: amalloy: the real use case will be more like "(ns ^{:doc "bleh" :deprecates old-name} new-name (:require baz) ...)" :-(

18:29 amalloy: need to think about it more, I guess. To understand the possibilities of each "selector language"

18:29 amalloy: okay, granted, it's not as trivial as my expr

18:29 * lpetit goes back to school :)

18:29 amalloy: lpetit: /ns/first()/**/symbol/last() i guess

18:30 lpetit: amalloy, yes, maybe, thanks for the food for thought (will go to bed now)

18:30 cu

18:31 amalloy: night

18:33 dale: Calling (.submit an-ExecutorService #(+ 1 1)) throws "More than one matching method found." Is (cast Runnable #(+ 1 1)) the right way to fix that? ^Runnable #(...) didn't work.

18:33 (There's submit(Runnable) and submit(Callable<T>) according to the Java docs, and I'm guessing Clojure callables implement both.)

18:34 amalloy: dale: yeah, i think it is right

18:36 btw dale: ##(-> [] fn class supers)

18:36 sexpbot: ⟹ #{java.io.Serializable java.lang.Object java.util.concurrent.Callable clojure.lang.AFn clojure.lang.AFunction clojure.lang.IObj java.lang.Runnable clojure.lang.IMeta java.util.Comparator clojure.lang.Fn clojure.lang.IFn}

18:37 dale: Nice, thanks. I just called instance? in my REPL a minute ago to confirm I was right about Runnable and Callable. I like (supers).

18:38 I have to confess that I often find -> quite unreadable, though. I hope I'm not alone in that.

18:38 Raynes: Why?

18:38 clojurebot: http://clojure.org/rationale

18:38 dale: Maybe easier reading of -> will come to me with time, but for example I find (supers (class #())) easier to read.

18:39 amalloy: dale: well, my usage there isn't exactly idiomatic. but yes, you'll find it easier with time

18:39 Raynes: In his example, it suffices to just read it backwards.

18:40 dale: I saw -> used in zippers and there it seemed very readable, but elsewhere I've been a little frustrated by it.

18:40 Raynes: &(#() class supers)

18:40 sexpbot: java.lang.IllegalArgumentException: Wrong number of args (2) passed to: sandbox6382$eval8909$fn

18:40 Raynes: &(-> #() class supers)

18:40 sexpbot: ⟹ #{java.io.Serializable java.lang.Object java.util.concurrent.Callable clojure.lang.AFn clojure.lang.AFunction clojure.lang.IObj java.lang.Runnable clojure.lang.IMeta java.util.Comparator clojure.lang.Fn clojure.lang.IFn}

18:40 dale: Raynes: Actually, yeah, that helps.

18:40 amalloy: technomancy's favorite code-transforming macro is ##(macroexpand '(doto myproj.foo require in-ns))

18:40 sexpbot: ⟹ (let* [G__8923 myproj.foo] (require G__8923) (in-ns G__8923) G__8923)

18:40 dale: amalloy: Sorry, didn't mean to pick on your example. :)

18:41 amalloy: dale: no worries. i have a heart of stone; your mockery leaves me unmoved

18:42 dale: Another example from nREPL: (-> submit class (.getResourceAsStream "/clojure/tools/nrepl/version.txt"))

18:43 amalloy: dale: that makes more sense if you're familiar with classloaders

18:43 dale: And actually I'm still having trouble seeing what the hell that does.

18:43 Asks a class of a semi-randomly-chosen function for a resource from the Jar file from which it was loaded?

18:43 amalloy: yeah

18:44 &(use 'clojure.javadoc)

18:44 sexpbot: java.io.FileNotFoundException: Could not locate clojure/javadoc__init.class or clojure/javadoc.clj on classpath:

18:45 amalloy: &(use 'clojure.java.javadoc)

18:45 sexpbot: java.security.AccessControlException: access denied (java.util.PropertyPermission os.name read)

18:45 amalloy: huh

18:45 &(javadoc Class)

18:45 sexpbot: java.lang.Exception: Unable to resolve symbol: javadoc in this context

18:45 dale: In my head I think just end up translating that to (.getResourceAsStream (class submit) "...") anyway, so I'm just not fond of the -> form there. Anyway, like I said, maybe I'll become accustomed to it over time.

19:08 amalloy: dale: ##(macroexpand '(->> (range) (filter even?) (take 100) (reduce +)))

19:08 sexpbot: ⟹ (reduce + (take 100 (filter even? (range))))

19:09 amalloy: the former seems a lot clearer to me: "take the first hundred even integers and add them up" vs "add up the first hundred elements of the list of even elements in the set of integers"

19:09 dale: amalloy: Oh, now I see what you were getting at with macroexpand like that, nice.

19:11 Perhaps years of programming, including dabbling in things like CL and toy languages, have predisposed me to reading and understanding inside out? Dunno.

19:11 amalloy: dale: there are some things that read better inside out and some that don't

19:12 both styles take some practice

19:12 dale: I could believe that, and I don't have enough exposure to ->/->>, sure.

19:13 amalloy: my (-> [] fn class supers) is, imo, less legible the way i wrote it, but it involved less reaching for the shift and () keys

21:43 qbg: Combinators are awesome. It was painful moving my syntax-rules lib over to them, but it was well worth it.

21:49 cnataren: qbg: do you know of any good article or reference about them?

21:49 qbg: You could start with http://en.wikipedia.org/wiki/Parser_combinator

21:50 The idea is beautifully simple

21:53 In my case, I have a number of functions which operate on match states, and then I have various combinators which combine them in useful ways

21:56 duck1123: Does anyone know why the Java library I'm using (Abdera) will pick one XMLInputFactory if I run my code through a REPL, but pick another if I use the Lazytest Maven Plugin?

21:58 The lazytest plugin is causing an immutable factory to be picked, which then throws an exception when a property is set on it

22:01 talios: lazytest maven plugin?

22:03 duck1123: yeah, the 2.0 one

22:03 talios: My guess is different class path ordering

22:03 duck1123: if I use clojure:swank to get a repl, and then run the tests, they all pass

22:03 talios: I didnt know there was a lazytest maven plugin - only my clojure-maven-plugin:test goal

22:03 duck1123: yeah, I had to go to 1.3 for it

22:04 I figured I needed to make the leap sooner or later

22:04 talios: ahh - I didn't realise stuart had made a plugin for it :)

22:05 My guess is that classpath ordering is screwing you over and that Abdera is finding a different impl first

22:10 abedra: cemerick: are you around?

22:11 cemerick: abedra: for the nonce. What's up?

22:11 talios: 'lo cemerick

22:11 cemerick: howdy :-)

22:11 abedra: I created you a user cemerick on build.clojure.org

22:11 I wanted to get you the password

22:11 and some info

22:12 cemerick: talios: I'm falling behind on my c-m-p homework :-(

22:12 abedra: SS said he needed your help with some stuff

22:12 cemerick: abedra: you didn't want to just use my key as before?

22:12 talios: cemerick: you and me both. I did some experimenting with the javax.scripting bridge into clojure and is looking nice.

22:12 abedra: cemerick: I do, but you will still need the password for sudo

22:13 cemerick: ah, ok

22:13 talios: cemerick: but if your behind, you won't have read about me looking at that :)

22:22 cemerick: talios: that sounds interesting; this is http://code.google.com/p/clojure-jsr223/ ?

22:22 talios: yep! using that same binary but with 1.3-alpha4 dep. listed worked FINE.

22:23 you don't get a separate scope of clojure tho, but you can have seperate scopes bindings into the user ns

22:24 might propose we graft that into clojure-core itself as an standard embedding strategy, as it seems to work rather nicely, run in the same vm, or fork a vm but still call via jsr223

22:24 (the author already has a contrib agreement signed it seems - handy)

22:28 cemerick: talios: is this part of a plan to hoist some or all of the c-m-p impl into clojure?

22:30 qbg: cemerick: What is c-m-p?

22:30 cemerick: clojure-maven-plugin

22:30 * qbg feels dirty thinking about maven

22:32 * cemerick Gloats a bit after switching over to running a webapp under glassfish instead of jetty locally by adding ~12 lines to his maven pom file.

22:34 duck1123: I like maven. I like having that extra bit of structure to project building, because as your app gets bigger and bigger, you start to want it

22:39 * talios is glad that CMP no longer refers to container managed persistence :)

22:41 cemerick: gaaaah! :-P

22:42 I always try to use the hyphens; not sure if anyone ever gets the hint.

23:25 fmeyer:

Logging service provided by n01se.net