#clojure log - Mar 03 2011

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

0:31 ossareh: technomancy: have you any thoughts / experiences about how hard / easy it would be to get a git revision value in a hooke?

0:41 hm, seems jgit can be wrapped reasonably easily.

0:41 technomancy: ossareh: those seem pretty orthogonal to me

0:41 ossareh: well... I want to be able to load a version number into my output html and I figured git version would be the most helpful

0:42 zz my english is sucking right now :/

0:42 i guess my question was more like - have you done this / know of a project doing this.

0:44 technomancy: the pom.xml that comes with every lein-generated jar has git revision info in it

0:45 ossareh: OK - that is good. So accessing that from the runtime is just a case of read/parse the pom.xml?

0:48 technomancy: yeah, should work with clojure.java.io/resource

0:49 tomoj: mine doesn't appear to have git revision info

0:50 maybe I misunderstood

0:51 ossareh: technomancy: ah, and there is the magic - I've realised that through my learning curve with clojure I learn about a new set of language features every 6 weeks or so - I then spend 6 weeks crow baring them into a solution that is usually already handled somewhere in the stdlibs...

1:03 technomancy: tomoj: lein pom has no git info?

1:04 tomoj: `lein pom && grep git pom.xml` gives only " https://github.com/technomancy/leiningen -->"

1:05 technomancy: it's actually able to read files straight out of .git/; you don't even need git installed to do it

1:05 crazy

1:05 tomoj: is the project OSS?

1:05 tomoj: oh, is it only supposed to work when the project root is the git root?

1:05 naturally, I suppose

1:05 technomancy: yeah, I guess it might not work for a project that's nested

1:05 tomoj: nope

1:06 I tried to argue for multiple repos but wound up with one mega-repo into which all my various projects go :(

1:06 technomancy: ah, bummer

1:07 tomoj: of course in this case it doesn't matter anyway, I'm not publishing the pom and would want to strip any git information that did make it in..

3:28 bairespace_: ,(defn <- [& args] (reduce #(%1 %2) args))

3:28 clojurebot: DENIED

3:29 bairespace_: ,(+ 2 2 2 2)

3:29 clojurebot: 8

3:40 bairespace_: ,(source core/->)

3:40 clojurebot: java.lang.Exception: Unable to resolve symbol: source in this context

3:41 bairespace_: ,(doc ->)

3:42 clojurebot: "([x] [x form] [x form & more]); Threads the expr through the forms. Inserts x as the second item in the first form, making a list of it if it is not a list already. If there are more forms, inserts ...

3:47 bairespace_: ,[0 1 2 #{3 4 5}] (-> {:a {:b 3}} :a :b)

3:47 clojurebot: [0 1 2 #{3 4 5}]

3:53 bairespace_: ,(([0 1 2 #{3 4 5}] (-> {:a {:b 3}} :a :b) 4)

3:53 clojurebot: EOF while reading

3:55 bairespace_: ,([0 1 2 #{3 4 5}] (-> {:a {:b 3}} :a :b))

3:55 clojurebot: #{3 4 5}

4:03 bairespace_: ,[]

4:04 clojurebot: []

4:04 bairespace_: ,{}

4:04 clojurebot: {}

4:04 bairespace_: ,#{}

4:04 clojurebot: #{}

7:08 clgv: &(macroexpand-1 '(when-let [bla blubb] haha hoho))

7:08 sexpbot: ⟹ (clojure.core/let [temp__3589__auto__ blubb] (clojure.core/when temp__3589__auto__ (clojure.core/let [bla temp__3589__auto__] haha hoho)))

7:09 clgv: why are there two let expressions involved? wouldn't one be sufficient?

7:42 raek: &(macroexpand-1 '(when-let [[foo bar] blubb] haha hoho))

7:42 sexpbot: ⟹ (clojure.core/let [temp__3589__auto__ blubb] (clojure.core/when temp__3589__auto__ (clojure.core/let [[foo bar] temp__3589__auto__] haha hoho)))

7:44 raek: clgv: I think it is done this way make sure that the expression is only evaluated once, even when combined with desctructuring

7:44 clgv: raek: thx. hoeck already gave me a similar hint :)

7:57 fogus`: Whoa! Clojure's juxt is FP's []! That is all

7:58 __name__: FP?

7:59 $source juxt

7:59 sexpbot: juxt is http://is.gd/8fgyhN

8:01 fogus`: http://en.wikipedia.org/wiki/FP_(programming_language)

8:14 clgv: what's that supposed to mean? java.lang.IllegalArgumentException: recur arg for primitive local: sum must be matching primitive

8:15 I get it in this line: (loop [complist (second group-complist), cdf (transient []), sum (double 0.0)]

8:17 raek: clgv: what does the recur form lool like?

8:17 mduerksen: clgv: is the third argument in in your recur form a double?

8:18 clgv: it should be. it is like: new-sum (+ sum (f x)) and new-sum is in the recur

8:19 AWizzArd: http://www.classnamer.com/

8:20 clgv: AWizzArd: "SecureGirlfriendStream" roflmao.

8:24 mduerksen: clgv: if (f x) doesn't return a double, then + won't return a double as well afaik

8:25 clgv: mduerksen: ok, but (f x) is a method specified in a protocol. can I type hint its return type?

8:25 mduerksen: i'm not sure about that. i guess it also depends on the clojure version

8:25 clgv: 1.2

8:26 well otherwise I surround it with (double ...)

8:26 mduerksen: you could find out with (class (f x))

8:27 clgv: I know that it should return a double since I wrote it myself

8:27 but I don't know how to tell the compiler that this protocol method will return a double

8:27 raek: hrm, I thought this primitive stuff was new for 1.3...

8:28 clgv: raek: not everything

8:30 Chousuke: functions can't return primitives in 1.2 IIRC :/

8:31 clgv: but there is the fibonacci example that is said to be valid in 1.2

8:31 Chousuke: http://dev.clojure.org/display/doc/Enhanced+Primitive+Support this describes 1.3

8:32 clgv: oh ok. damn :(

8:32 hmm I thought I read something related to 1.2 in a blog entry on ^:static

8:32 is ^:static also 1.3?

8:34 cemerick: IIRC, ^:static became a no-op with the recent var changes

8:34 a no-op and unnecessary, that is

8:40 clgv: ok. probably (double ...) will work then

9:00 &(doc empty?)

9:00 sexpbot: ⟹ "([coll]); Returns true if coll has no items - same as (not (seq coll)). Please use the idiom (seq x) rather than (not (empty? x))"

9:01 clgv: &(empty? nil)

9:01 sexpbot: ⟹ true

10:36 flatt: should I be using eval here: (defn [x] (eval (doto (SomeClass.) (.doStuff x))))? can I (or should I) pull it off with defmacro instead?

10:38 raek: flatt: you very rarely need to use eval.

10:38 flatt: why not (defn [x] (doto (SomeClass.) (.doStuff x)))

10:38 flatt: oh, wait, that was over-simplified.

10:40 (defn [& args] (eval `(doto (SomeClass.) ~(list '.doStuff ~args))))

10:40 Chousuke: flatt: why would you do that with a function?

10:40 one big problem with eval is that it can't access locals

10:41 so all you can pass to your function are symbols that name globals.

10:41 or literals

10:41 raek: flatt: ah, so you want something like apply, but for methods?

10:41 flatt: oh, then then eval doesn't help there.

10:42 imagine variable number of forms in the body of doto, depending on what args are supplied

10:44 bennylu: how to use ns-publics? (ns-publics 'some-ns)

10:44 => #<ClassCastException java.lang.ClassCastException: clojure.lang.Var cannot be cast to clojure.lang.IObj>

10:44 i want to retrive all the functions in the namespace with a certin type ..

10:44 raek: ,(ns-publics 'clojure.core)

10:44 clojurebot: {sorted-map #'clojure.core/sorted-map, read-line #'clojure.core/read-line, re-pattern #'clojure.core/re-pattern, keyword? #'clojure.core/keyword?, val #'clojure.core/val, chunked-seq? #'clojure.core/...

10:46 bennylu: , (ns-publics 'clojure.xml)

10:46 clojurebot: {content-handler #'clojure.xml/content-handler, *stack* #'clojure.xml/*stack*, attrs #'clojure.xml/attrs, element #'clojure.xml/element, tag #'clojure.xml/tag, startparse-sax #'clojure.xml/startparse...

10:46 raek: bennylu: it looks like the exception is from the code that uses the value of your (ns-publics 'some-ns) call

10:48 flatt: it is certainly possible to do that with a macro, but dependending on what you know about the methods (e.g. arity) you could possibly implement it as an ordinary function (which is preferred if possible)

10:48 bennylu: i am calling it directly from the repl..

10:49 flatt: raek: I see, thanks.

10:51 TimMc: bennylu: Are you bennylut?

10:51 raek: bennylu: what does the stack trace look like?

10:52 bennylu: also, does this happen for all namespaces? for instance, does (ns-publics 'clojure.core) work for you?

11:03 perkinsc: ,(clojure-version)

11:03 clojurebot: "1.2.0"

11:09 sattvik: flatt: If you know the number of arities you will be working with, you can do something like:

11:09 ,(let [invoker (fn ([a] (. Integer valueOf a)) ([a b] (. Integer valueOf a b)))] (apply invoker ["100" 2]))

11:09 clojurebot: 4

11:09 pyr: hi

11:10 sattvik: The only other non-macro approach I can think of is using Java's reflection APIs.

11:10 pyr: it's not clear to me if there's a way to kill agents forcibly

11:10 i'm using agents with await-for

11:10 if an agent returns false from await-for

11:11 do I need to kill it or will the thread be available for a new agent ?

11:11 TimMc: $findfn [1 2 3] 3 4 [1 2 4]

11:11 sexpbot: []

11:12 chouser: pyr: I don't think there's any good way to forcibly kill an agent.

11:13 pyr: ok

11:15 clgv: where do I get clojure-contrib 1.3.0 alpha 4?

11:49 gtrak: how do you guys do a find-usages?

11:53 sattvik: find-usages?

11:54 gtrak: yea

11:55 TimMc: Like, all references to a var in a project?

11:55 I generally grep. -.-

11:56 gtrak: I guess that's pretty simple :-)

11:57 dakrone: b

11:58 amalloy: gtrak: slime has a feature like that, but i don't know if the clojure swank server supports it

11:58 gtrak: ah

11:58 amalloy: heh, indeed. "Wrong type argument: listp, :not-implemented"

11:59 if it did work, though, it would be C-c C-w C-r

11:59 for "who references"

12:00 bennylu: TimMc, yes i am bennylut

12:00 gtrak: amalloy, i can confirm "error in process filter: who-references is not implemente yet on clojure"

12:00 TimMc: bennylu: OK, so you were confused some days back about why ^foo didn't give you the metadata on foo. It turns out this was a change from CLojure 1.1. to 1.2.

12:01 I was reading Programming Clojure and ran into the same problem.

12:01 bennylu: raek, i just checked and to clojure.core and it not throwing exception..

12:01 sattvik: gtrak: If you wanted to do it within clojure, you could probably abuse the source macro.

12:02 bennylu: TimMc, Thanks! i was reading the book programming clojure and there it was explained that that sould work, i guess that it changed after the book came of

12:02 amalloy: $source ->

12:03 sexpbot: -> is http://is.gd/yfj1XP

12:03 __name__: good morning

12:04 gtrak: anyone ever had lein marg throw an exception that it can't find the project.clj?

12:05 amalloy: TimMc: the findfn you were looking for a bit ago is probably replace

12:05 &(replace {3 4} [1 2 3])

12:05 sexpbot: ⟹ [1 2 4]

12:06 TimMc: Oh, right!

12:06 And replace has the wrong semantics for me.

12:06 behavior, rather

12:07 amalloy: oh?

12:08 TimMc: I need identical? instead of =.

12:10 I ended up writing replace-1: https://gist.github.com/853113

12:10 amalloy: TimMc: you could use an identity map

12:11 TimMc: What's this now?

12:11 amalloy: http://download.oracle.com/javase/1.4.2/docs/api/java/util/IdentityHashMap.html in java - i think there's something similar in clojure

12:12 TimMc: Oh yeah, I just came across that the other day.

12:15 Haha, it works!

12:16 (replace (IdentityHashMap. {d0 d1}) [3 4 d0 5])

12:16 amalloy: TimMc: or (into (sorted-map-by identical?) mymap)

12:17 except rewritten so that it actually works :P

12:25 TimMc: That's even longer.

12:25 naeu: is there anyone about that can help me understand how I may avoid inserting a race condition by using the STM and refs?

12:25 TimMc: naeu: Do you just want to make sure that a read-update-write is consistent?

12:26 naeu: TimMc: I'm not sure what you mean. In my head I want to make sure that if while I read a given ref, it can't be updated elsewhere

12:27 perhaps I just want basic locking

12:27 but that doesn't feel right

12:27 TimMc: You don't want locking. Nobody does, even if they think they do.

12:27 naeu: :-)

12:27 so I have a ref of keywords

12:28 and I want one thread to be able to look at that ref, and if a particular keyword doesn't exist in there, to register a fn to be called when it does

12:28 TimMc: A ref of a collection of keywords?

12:28 naeu: and on another thread I want to be able to update the ref and add a keyword to the collection

12:29 and call all the registered fns associated with that keyword

12:29 yup, I'm just currently using a vector

12:29 TimMc: You might find a set more appropriate than a vector, depending on your app.

12:30 naeu: TimMc: oh sure

12:30 sattvik: Does ensure solve your problem?

12:30 TimMc: But anyway, there are a couple of ways to do this, and I'm still learning about concurrency in Clojure.

12:31 naeu: You're familiar with dosync, yes?

12:31 naeu: TimMc: by familiarity, I've used it

12:31 and I understand that it stops modification from multiple places by re-running

12:31 TimMc: So you know that inside a dosync you have a consistent view of the world.

12:31 naeu: sattvik: so you just call (ensure my-ref) in the dosync?

12:32 TimMc: sure, but is that just a consistent view of the refs you modify or also the refs you deref?

12:33 TimMc: All of them.

12:33 naeu: TimMc: perhaps not, it doesn't explain the existence of ensure

12:33 sattvik: I think that this is exactly what I need

12:34 TimMc: I believe that in a dosync the state of a ref you deref may change during the rest of the execution of the transaction

12:35 without requiring the transaction to re-run

12:35 sattvik: naeu: Your welcome.

12:35 naeu: whereas a ref you modify may not change elsewhere during the rest of the execution of the transaction

12:35 sattvik: is what I'm saying making any sense?

12:35 I might be totally wrong :-)

12:35 TimMc: huh

12:36 sattvik: From http://clojure.org/refs : No changes will have been made by any other transactions to any Refs that have been ref-set/altered/ensured by this transaction

12:37 amalloy: yes, that's what ensure is for

12:37 chouser: naeu: I don't think that's right. Once you're in a transaction, every deref of a ref will return the same value.

12:37 naeu: chouser: yeah, but it will return the first value

12:38 even if the ref has been modified elsewhere since the first deref

12:38 at least that's what I understand

12:38 chouser: oh, maybe I misunderstood you

12:38 joshua__: Alright, I'm confused. I have two programs running congomongo. If I use one of the programs to upload items via the swank repl it does fine. If I use it to upload items via normal running it fails, despite the upload being accomplished through the same method calls. The other program doesn't have this problem. What am I not understanding?

12:38 naeu: so it provides a consistent view in the transaction

12:38 but not necessarily across transactions

12:39 whereas if you change the ref, the transaction will ensure a consistent view across transactions

12:39 by forcing other transactions to repeat if necessary

12:40 which brings me to my next question - how do I have a side-effect fn get executed immediately*after* a transaction has completed

12:41 obviously I can't put it in the transaction

12:41 do i use an agent for that?

12:41 Chousuke: dunno about immediately, but agent sends are queued until the transaction finishes

12:43 naeu: cool, i think a combo of dosync, ensure and agents will do what I want

12:43 sattvik: naeu: I may be misunderstanding your question, but can't you just call the function after the transaction? (do (dosync ...) (my-fn ...))?

12:46 Or you can even use the result of a transaction as an argument to a function.

12:46 naeu: sattvik: I'm not sure I can as the arg to my-fn will be the dereffed ref

12:47 sattvik: that might work

12:47 amalloy: sattvik: https://github.com/Raynes/sexpbot/blob/master/src/sexpbot/registry.clj#L96 is an example of doing this

12:47 sattvik: ,(conj [1 2] (dosync 3))

12:47 clojurebot: [1 2 3]

12:47 amalloy: er

12:47 naeu: ^ was for you

12:51 mattmitchell: is there a way to extract values from a hash in a ordered way?

12:54 naeu: amalloy: so that works because bot is altered within the transaction

12:54 but if there was no alter on bot, then @bot might be different at time t+1 on another thread than the value of @bot at time t within the transaction

12:57 amalloy: naeu: https://github.com/Raynes/sexpbot/blob/master/src/sexpbot/plugins/ping.clj#L10-17 maybe? captures the return value of the dosync. still uses alter so maybe this doesn't address your concern but i guess i don't understand your concern :P

12:57 naeu: amalloy: I probably don't understand my concern either!

12:58 but i think capturing the result of a dosync will be enough

12:59 TimMc: naeu: "All reads of Refs will see a consistent snapshot of the 'Ref world' as of the starting point of the transaction (its 'read point'). The transaction will see any changes it has made. This is called the in-transaction-value."

12:59 http://clojure.org/refs

12:59 amalloy: mattmitchell: you can use a sorted-map

13:00 otherwise, no, hashes are not ordered

13:00 mattmitchell: amalloy: ok excellent thanks!

13:00 naeu: TimMc: so reads don't affect a transaction then?

13:00 TimMc: I don't grok this snippet " The transaction will see any changes it has made."

13:01 amalloy: &(let [x (ref 0)] (dosync (println @x) (alter x inc) (println @x)))

13:01 sexpbot: ⟹ 0 1 nil

13:01 naeu: I'm assuming it means the transaction will see any changes to the ref within it, but care of changes outside of it if the ref is only read

13:01 TimMc: If I (dosync @foo (ref-set foo ...) @foo) the two reads will be different.

13:01 amalloy: Holy shit you're fast.

13:01 naeu: TimMc: sure, but that's setting the ref from within the same transaction

13:02 TimMc: but if you did a ref-set in a different transaction on a different thread, @foo would always be the same

13:03 amalloy: naeu: that's the point. it's a transaction. you don't want to see changes others have made: if you did, it would be unrestrained global mutability, no?

13:03 naeu: exactly, but I want to retry my transaction if others have made changes to the ref I'm reading

13:03 TimMc: amalloy: Then what does ensure do?

13:03 naeu: which is why I believe I need ensure

13:03 which does exactly that

13:04 amalloy: right

13:04 i belive you do too. we could both be wrong, but it seems like you'll find out faster if you just try

13:04 naeu: the docs say it's similar (but more efficient) to doing (ref-set myref @my-ref)

13:05 the problem is that it's not so easy to try out things that might have a race condition

13:05 raek: ensure is for when you want to ensure that a ref that you don't need to read or write from stays unmodified during the transaction

13:06 TimMc: raek: Ah! It is a way of pulling other refs into the transaction?

13:06 naeu: thanks everyone for your help, it's much appreciated

13:07 mattmitchell: amalloy: is there a way to take a hash-map, and convert it into a sorted-map?

13:07 raek: I think it's like saying "this ref must be unchanged during the transaction"

13:07 amalloy: mattmitchell: yes, but if you aren't building a sorted map to begin with it will be slow and you might as well just do (sort (keys m))

13:08 naeu: raek: that's my understanding too

13:08 devn: re-reading WhyFP is a good idea

13:08 mattmitchell: amalloy: ok makes sense. thanks.

13:08 devn: it's like re-reading the agile manifesto, it should be done every now and then

13:08 bennylu: hi, a little quiestion about managing clojure project -

13:08 devn: bennylu: go ahead

13:09 amalloy: &(let [m {"test" 1 "egr" 2 "wer`1" 3}] (print m) (print (into (sorted-map) m)))

13:09 sexpbot: ⟹ {test 1, egr 2, wer`1 3}{egr 2, test 1, wer`1 3}nil

13:09 amalloy: mattmitchell: ^

13:09 bennylu: if i have a reletivly big project do you split it to several namespaces in a hirarchy similar to java?

13:10 devn: bennylu: yes and no

13:11 bennylu: im trying to think of how to expand on that... heh

13:11 clojure is not java so the hierarchies look a bit different

13:12 bennylu: i try - but it look like namespaces are "larger" in scope than classes and so there is too few name spaces and too much code in each ...

13:13 devn: bennylu: My opinion is that what you want to do is Separation of Concerns, and modularize where appropriate

13:13 bennylu: im finding myself scrolling reletivly large text in order to find the function that i want to modify / read

13:13 devn: ive found that it is helpful to write one gigantic file where everything lives in the same namespace

13:13 and then split it out from there

13:13 but i havent done anything that's like 800k lines of code

13:13 so perhaps that would not work for you

13:14 bennylu: clojure.core, the source, is mostly in one place

13:14 over-namespacing can be equally annoying

13:15 bennylu: i not talking about 800k too :) but even on 900 lines of code it gets preety heavy to find stuff..

13:15 yes, i know what you means .. i guess i just have to learn to use the find function more :)

13:16 amalloy: bennylu: are you using slime/swank?

13:16 devn: bennylu: i mean, this is not so much a clojure problem as it is how you decide to separate the modules

13:16 "modules"

13:16 TimMc: ,[(identical? 3 3) (identical? 300 300)]

13:16 clojurebot: [true false]

13:16 TimMc: Is this an instance of interning in Integer?

13:16 or rather, in the compiler's handling of int literal?

13:16 amalloy: TimMc: yes

13:16 the first 32 ints (or 256?) are interned

13:16 bennylu: i started with it but i hear about counterclockwise and give it a shot - its preety good ..

13:17 so i now use cw

13:17 amalloy: bennylu: well, find ccw's "find" feature, then :P

13:17 TimMc: WHOA

13:17 amalloy: instead of looking around by hand

13:17 devn: CCW is pretty awesome if you want to stay in IDE land. learning a little bit of slime isn't a bad idea, though. it's awesome.

13:17 mattmitchell: amalloy: cool thanks again :)

13:17 bennylu: lol :)

13:17 devn: lpetit is a champ.

13:17 bennylu: lpetit?

13:17 TimMc: I just got the last screenful of text within a couple seconds. latency weirdness

13:17 devn: bennylu: he did most of CCW

13:18 amalloy: &(identical? 1 (inc 0))

13:18 sexpbot: ⟹ true

13:18 devn: he put a ton of thought into the structural editing

13:18 bennylu: he did relly good job

13:18 devn: yeah it's pretty great

13:19 amalloy: funny how from where i'm sitting, your latency issues are indistinguishable from illegal drugs

13:19 devn: im an emacs guy until the day i die, but CCW is fantastic

13:19 bennylu: i tried enclojure to but it was awfull - crashing all the time and slow...

13:19 devn: amalloy: who me?

13:19 amalloy: no, tim

13:19 devn: ah

13:19 amalloy: his sudden WHOA just reminded me of stoners

13:19 devn: :)

13:19 WHOA DUDE THIS FUNCTION IS LIKE, WHOA

13:20 TimMc: amalloy: Same here, actually.

13:20 IT'S LIKE EACH SEXPR IS ITS OWN UNIVERSE

13:21 devn: hahaha

13:21 amalloy: *chuckle*

13:21 devn: that sounds like something id say after a beer or two

13:21 im not proud of that

13:21 it's just true

13:23 this is your chance to make fun of me

13:24 pyr: (str :foo) yields ":foo"

13:24 amalloy: &(name :foo)

13:24 sexpbot: ⟹ "foo"

13:24 amalloy: i think stoner TimMc makes an excellent observation about the ramifications of immutability

13:24 devn: amalloy: say more

13:24 pyr: amalloy: :)

13:24 amalloy: thx!

13:25 cemerick: devn: it's going to keep getting better. I'm hoping to take a day for it next week.

13:25 devn: cemerick: yeah i didn't mean to assign all of CCW's development only to lpetit

13:25 thanks for your work as well. :)

13:25 cemerick: oh, wasn't trying to grab credit

13:26 He's absolutely the driving force -- I only pitch in here and there. :-)

13:26 devn: cemerick: nono i wasn't trying to suggest you were im just interested in giving it where it's due

13:26 cemerick: :-)

13:26 devn: :)

13:26 cemerick: devn: how's things, BTW

13:27 devn: great, started a clojure meetup in Madison, WI -- have our 2nd meeting next monday, still pretty small but im slowly making the rounds to local meetup groups and attracting some interest

13:27 i've slowly convinced a few ruby guys to pair program with me on some clojure

13:27 they scoffed and hemmed and hawed at first, but i think i beat them into submission by showing them ruby came out of dylan, scheme, and the CLOS :)

13:30 cemerick: how about you?

13:30 cemerick: devn: sorry, pulled in different directions :-)

13:31 absurdly busy

13:31 usually in a good way, sometimes not

13:31 it's been an odd year so far

13:31 devn: :) sine waves or square waves?

13:31 cemerick: Been working on a bunch of Clojure open source stuff in the past couple of weeks, which is a nice change of pace

13:31 square, definitely :-/

13:32 devn: yeah, that can be exhilirating though! when people walk in the door, hit the whiteboard and the room explodes with action that's a great feeling

13:33 cemerick: going to make it to the next conj?

13:33 cemerick: devn: can't imagine not :-)

13:34 devn: :) good to hear it

13:34 cemerick: what open source projects have you been cracking at? (btw if you're busy feel free to table this discussion -- i had a doctor's appointment today so I'm slacking a bit)

13:36 cemerick: devn: there's https://github.com/cemerick/bandalore, some nREPL fixes, and a refurbishing of a simpledb client library based on Rich's original implementation.

13:36 * devn needs to read up on simpledb

13:36 devn: cemerick: wanna give me an elevator pitch? :)

13:37 cemerick: on simpledb?

13:37 devn: *nod*

13:37 also, i didn't know rich wrote a simpledb implementation

13:38 cemerick: devn: it's a zero-admin couchdb with "proper" indexes and ad-hoc query capabilities

13:38 * devn reads that 3 or 4 times

13:39 cemerick: hosted by a known-good vendor, etc

13:39 right next to the EC2 instances I'm using already, etc

13:39 Essentially, I'm going all-in on AWS.

13:39 devn: yeah absolutely -- ive been pretty much doing everything on S3 and EC2 lately along with a bit of heroku here and there

13:39 cemerick: Thus the SQS client impl.

13:40 devn: Redis is really cool. Play with that at all?

13:40 cemerick: No, never looked at it.

13:41 I've been trying to simplify everything as much as possible of late -- and anything with a whiff of administration overhead is getting tossed overboard.

13:41 devn: Redis in a lot of ways reminds me of the clojure STM -- do you can wrap multiple commands in a pipeline etc

13:41 cemerick: devn: FYI, the most recent maintained fork of Rich's SDB client is here: https://github.com/bapehbe/sdb

13:41 devn: O(1) for pretty much everything except on lists, and so on

13:42 cemerick: I'm mostly rebuilding it though: https://docs.google.com/document/d/1K5p2RRVtvYxBNLEJuWGNf1iZak2ri8cI73joWu9K1W0/edit?hl=en&authkey=CMDR_6AF

13:42 devn: cemerick: im definitely going to look into that

13:42 we've been using mongo quite a bit lately

13:42 (where appropriate of course)

13:42 cemerick: it sounds like redis has a lot going for it, especially since they managed to work out larger-than-memory datasets

13:43 That was the limitation that kept me away initially

13:43 devn: cemerick: the coolest part of redis that i have yet to toy with is the pub/sub system

13:43 http://redis.io/commands#pubsub

13:46 it gives you what is essentially a broadcast server to transmit messages over channels to many subscribers in real time

13:47 lots of cool ideas come to mind

13:50 edw```: Are there Clojure-native string->number procedures? I wind up doing #(Integer. %) a lot, which is rather tedious.

13:50 cemerick: edw```: if you're certain the string only contains a number literal, use read-string

13:50 edw: That sort of seems like using an atomic bomb when a firecracker is called for. How efficient is that?

13:50 In practive, I have STRING-TO-INT and STRING-TO-FLOAT defined in a million files, which is what makes me think having a built-in would be wise. (I do a lot of reading from text files and URLs.)

13:54 cemerick: ah, so an ad-hoc mq

14:07 devn: cemerick: yeah good way of thinking about it

14:07 cemerick: i think about using it for things like...you have data being funneled from one big EC2 instance to many smaller instances that handle specific subsets of the total dataset

14:08 this is probably a cliche by now, but also, if you wanted to do a Twitter clone, that's your ticket

14:09 redis 2.3 is i believe going to introduce a more complete distributed system, it will be interesting to see how pub/sub works in that context

14:09 Nanarpuss: Anyone work with slime? I'm getting an error everytime I hit return on the REPL... It says "Error in process filter: Wrong number of arguments: nil, 1"

14:10 devn: Nanarpuss: ah yeah i was getting that... i think it's your version of SLIME

14:10 are you running slime from source?

14:10 Nanarpuss: yeah

14:10 devn: yeah, use the ELPA package

14:10 mattmitchell: i'm using the contrib.sql lib and attempting to insert a date to mysql. How does it handle dates? Just as strings? Do I have to format the value myself?

14:10 Nanarpuss: I've tried ELPA too

14:10 devn: that will get rid of it

14:10 Nanarpuss: hm, weird. that fixed it for me

14:11 Nanarpuss: so ELPA slime and swank-clojure worked for you?

14:11 devn: Nanarpuss: are you sure you don't have slime loading from source still?

14:11 Nanarpuss: yes. with 1.3.0-SNAPSHOT

14:11 Nanarpuss: ohh I'm on 1.2

14:11 let me try 1.3 and see what happens

14:11 devn: Nanarpuss: im not sure how much of a difference it makes, but that's my setup and it seems to be working

14:12 raek: I don't think the clojure version should make any difference here

14:12 devn: raek: is 1.3.0-SNAPSHOT just for clojure 1.2 then? and swank-clojure is just 1.2?

14:12 err and swank-clojure 1.2 is just for 1.1.0?

14:13 technomancy: any version of swank-clojure should work with all clojure versions

14:13 raek: ah, thought you were refering to clojure versions...

14:13 technomancy: modulo a few times where I apply patches I get without thinking them through =(

14:13 devn: technomancy: i saw your post on the Wrong number of arguments: nil, 1 i think

14:13 IIRC you suggested to just use the ELPA packages, and so I did, and then never received the error again

14:13 technomancy: the slime version is what you have to watch out for

14:14 devn: i was compiling from source

14:14 technomancy: why no marmalade in the starter-kit, btw?

14:14 technomancy: I wish that were simpler, but I don't really have the patience to work it out with the CL guys.

14:14 devn: no reason; just haven't gotten around to it

14:15 tarball packages are slightly more complicated; I guess that's the excuse

14:15 devn: *nod* -- ill submit a pull req.

14:16 TimMc: What is a use-case of ensure?

14:17 That is, why protect a ref from modification if you never read or write it in that transaction?

14:19 devn: TimMc: ive seen several opinions on that

14:20 what ive concluded is that it's a read with an annotation

14:20 it increases parallelism w/r/t a dummy read/write like ref-set

14:20 TimMc: Surely there's no behavioral difference within one transaction between @foo and (ensure foo)?

14:21 devn: i think it basically means that you're going to be changing foo later and so others should stay away from it

14:21 maybe to ease contention?

14:21 Nanarpuss: hmm still no luck

14:21 just tried 1.3

14:22 TimMc: devn: Like a way to say early on in a long transaction, "back off, I'll be using this"?

14:22 devn: TimMc: i THINK so

14:22 it increases isolation

14:22 bennylu: what is the difference between into and concat?? (besides the order of the result)

14:23 TimMc: I don't see any usage inside the clojure source.

14:23 amalloy: bennylu: concat is lazy

14:23 bennylu: amalloy, thanks!

14:23 amalloy: &(take 1 (into () (range)))

14:23 devn: TimMc: i think it is ref-set's half-brother

14:23 amalloy: &(take 1 (concat () (range)))

14:23 sexpbot: ⟹ (0)

14:23 raek: bennylu: into is conj'ing on some element to any data structure, concat concatenates two sequences

14:23 sexpbot: Execution Timed Out!

14:24 TimMc: bennylu: I believe into gives you back a collection of the type you asked for.

14:24 devn: TimMc: i think i found an answer for you

14:24 amalloy: TimMc: into is just (partial reduce conj), more or less

14:25 &((partial reduce conj) [1 2] (range 5))

14:25 sexpbot: ⟹ [1 2 0 1 2 3 4]

14:25 amalloy: &(into [1 2] (range 5))

14:25 sexpbot: ⟹ [1 2 0 1 2 3 4]

14:25 raek: ,[(into [1 2] [3 4]) (into (list 1 2) [3 4]) (concat [1 2] [3 4]) (concat (list 1 2) [3 4]]

14:25 clojurebot: Unmatched delimiter: ]

14:25 raek: ,[(into [1 2] [3 4]) (into (list 1 2) [3 4]) (concat [1 2] [3 4]) (concat (list 1 2) [3 4])]

14:25 clojurebot: [[1 2 3 4] (4 3 1 2) (1 2 3 4) (1 2 3 4)]

14:25 devn: TimMc: The scenario you describe cannot happen in Clojure's STM. Clojure's STM uses MVCC and provides snapshot isolation to transactions - a transaction will never see inconsistent state. Being MVCC-based, it is subject to write skew, and provides an ensure construct that allows one to tag dependent reads, with more concurrency than the dummy writes usually used to address write skew. Livelock is a theoretical scenario, but it is not a non-blocking ...

14:25 ... design, thus mitigating churn. Actual livelock is avoided via retry limits and timeouts. There is, as you mention, as-yet-unrealized potential for configurable contention resolution policy.

14:26 -rich hickey, 2009

14:27 TimMc: I don't know what livelock is (though I could guess) and I don't know what write skew is.

14:27 So... ensure is probably there if you need super concurrency performance.

14:27 ...but is never strictly necessary from a results point of view.

14:27 devn: TimMc: there's a lot of literature out there, but most of it is specific to an implementation

14:29 TimMc: i wish i could be of more help, but i can't really give you anything more than i already have without speculation

14:29 TimMc: As long as I don't need to know about ensure, I'll probably hold off on trying to figure it out. :-)

14:30 devn: TimMc: yeah I'm hunting for some code that uses it, but then you need to be sure that they're not just using it for the sake of using it

14:30 TimMc: It's not present in contrib either, I think.

14:31 devn: TimMc: http://www.cs.rochester.edu/research/synchronization/rstm/primer.shtml

14:31 that's interesting and somewhat relevant to this discussion

14:31 TimMc: (I've only beenlooking on the .clj side of things.)

14:31 devn: TimMc: http://www.cs.rochester.edu/research/synchronization/rstm/libraries.shtml

14:31 that's good as well

14:33 gfrlog: ,(format #"this won't work %s cuz it's a regex" "oh well")

14:33 clojurebot: java.lang.ClassCastException: java.util.regex.Pattern cannot be cast to java.lang.String

14:33 gfrlog: so is there any function for regexly escaping a string?

14:33 and did I state that question in an understandable way?

14:33 devn: IIRC there is

14:34 gfrlog: I just looked on java.util.regex.Pattern and don't see anything

14:34 TimMc: $findfn "." "\\."

14:34 sexpbot: []

14:34 gfrlog: TimMc: brilliant, if unsucessful

14:35 devn: i used to have a thingamajig that let me build up a regex from strings

14:35 brehaut: (str #".")

14:35 ,(str #".")

14:35 gfrlog: ,(str #".")

14:35 clojurebot: "."

14:35 * devn hunts

14:35 clojurebot: "."

14:35 TimMc: ooh

14:35 ,(java.util.regex.Pattern/quote ".")

14:35 clojurebot: "\\Q.\\E"

14:35 gfrlog: wtf is \Q and \E?

14:35 TimMc: Oh, uh, I guess that works too.

14:36 jweiss: quote, end quote?

14:36 gfrlog: man I looked right at that function in the javadocs and didn't see it cause it wasn't called "escape"

14:36 TimMc: ,"\\"

14:36 clojurebot: "\\"

14:36 gfrlog: ,(java.util.regex.Pattern/quote "\\E")

14:36 clojurebot: "\\Q\\E\\\\E\\Q\\E"

14:36 gfrlog: holy cow

14:37 TimMc: haha

14:37 gfrlog: man testing to make sure that does what I think it does sounds like a headache

14:37 TimMc: ,(java.util.regex.Pattern/quote "\\$")

14:37 clojurebot: "\\Q\\$\\E"

14:37 devn: this seems like the wrong way to go about doing this...

14:38 gfrlog: devn: it sounds perfect, what could be wrong with it?

14:38 TimMc: ,(java.util.regex.Pattern/quote "$")

14:38 clojurebot: "\\Q$\\E"

14:38 gfrlog: ,(re-pattern (java.util.regex.Pattern/quote "\\E"))

14:38 clojurebot: #"\Q\E\\E\Q\E"

14:38 devn: maybe i misunderstand your original problem, but you wanted to call format on a regex

14:38 i dont see how this solves your problem

14:38 TimMc: OK, so it doesn't attempt to quote its own sentinals via nesting or anything.

14:38 gfrlog: devn: no, I actually just needed an escape

14:38 ,(re-pattern (java.util.regex.Pattern/quote "\\E\\Q\\E"))

14:39 clojurebot: #"\Q\E\\E\Q\Q\E\\E\Q\E"

14:39 gfrlog: how the heck does that work?

14:39 devn: lol

14:39 gfrlog: devn: I can do format manually with (str)

14:39 devn: then pass to re-pattern

14:39 devn: okay now we're on the same page gfrlog

14:39 gfrlog: I'm seriously dumbfounded by the escaping strategy here

14:40 devn: that's what my suggests was

14:40 suggestion*

14:40 gfrlog: I'm sure it works but I'm not sure why

14:40 TimMc: After a \Q, go into raw mode until \E.

14:41 ,(java.util.regex.Pattern/quote "\\")

14:41 clojurebot: "\\Q\\\\E"

14:41 Null-A: ,```foo

14:41 clojurebot: (clojure.core/seq (clojure.core/concat (clojure.core/list (quote quote)) (clojure.core/list (quote sandbox/foo))))

14:41 TimMc: See, that string is \Q\\E, but the \\ isn't an escape.

14:42 For a literal \E, drop out of raw mode, emit an escaped \E (\\E) and then go back into raw mode.

14:42 It's a bit silly that it puts empty raw clauses in when the beginning or end of a string is \E

14:43 devn: "patches welcome" ;)

14:43 gfrlog: TimMc: okay, I think that makes sense

14:43 thanks

14:43 smnirven: got a question about clojure.contrib.sql with-query-results

14:43 gfrlog: smnirven: ask that question

14:44 smnirven: im trying to write a query by datetime, so I'm building a prepared statement - its not clear what I have to pass in

14:44 here's my code:

14:44 (sql/with-connection db/conn

14:44 (sql/with-query-results rs [(str "select * FROM users WHERE updated_at >= ?" [start-dt-str])]

14:44 (doseq [res rs]

14:44 (prn res)))))

14:45 gfrlog: you're right. that is not clear. Have you tried anything?

14:45 smnirven: yeah, tried running that code - got this error

14:45 gfrlog: I know with sql you can use some kind of time literal in single-quotes. Maybe c.c.sql will take a string?

14:45 smnirven: java.sql.SQLException: No value specified for parameter 1 (NO_SOURCE_FILE:0)

14:46 gfrlog: smnirven: I don't think you want the argument to be in a vector

14:46 i.e., use start-dt-str instead of [start-dt

14:46 smnirven: yeah, in that code, start-dt-str is a string

14:46 gfrlog: -str]

14:46 smnirven: just get rid of the vector

14:46 gfrlog: right

14:46 smnirven: cool, i'll try that quick

14:46 TimMc: smnirven: Is start-dt supposed to be inside (str ...)?

14:46 gfrlog: the error message still looks weird, but maybe that's why anydow

14:46 anyhow*

14:47 smnirven: nope, it gets passed into a function as a string

14:47 TimMc: smnirven: ##(str "f" 5)

14:47 sexpbot: ⟹ "f5"

14:47 TimMc: Do you want concatenation?

14:47 gfrlog: maybe you forgot to include the (:fix-bugs) clause within the namespace declaration

14:47 TimMc: I think he was just using the c.c.sql api wrong

14:48 smnirven: here's a more direct example:

14:48 (sql/with-query-results rs [(str "select * FROM raw_leads WHERE sdb_updated_at >= ?" "2011-03-03 12:00:00")]

14:49 TimMc: smnirven: Right, you don't want the date inside str.

14:49 smnirven: ohh i think i see what i did

14:49 yeah

14:49 oy - thanks

14:49 TimMc: Just kill str, actually.

14:49 np

14:50 smnirven: excellent

14:50 that worked

14:50 ty

14:51 gfrlog: oh weird I didn't even see he did that in the original code

15:49 chouser: is this old news here? http://doc.akka.io/stm-java

15:49 mattmitchell: i have a lazy seq. i'd like to use map, to transform all of the values. i seriously, can't figure out how to do this, but i'm thinking doall might help me out here?

15:50 chouser: mattmitchell: why do you want to force the lazy seq instead of letting it remain lazy?

15:51 mattmitchell: hmm, let me try something

15:51 chouser: is it possible to use map on a lazy seq?

15:52 chouser: mattmitchell: absolutely. and map returns a lazy seq in turn.

15:52 mattmitchell: chouser: interesting. ok.

15:55 TimMc: Wait wait wait... http://lambda-the-ultimate.org/node/3700#comment-52647 indicates that transactions do not provide consistency, if I'm understanding write skew correctly.

15:59 chouser: within the transaction, you always see a consistent state.

16:00 TimMc: That's isolation, I think.

16:00 chouser: As I understand it, most relational databases that claim ACID are also subject to write skew unless you do dummy writes.

16:01 TimMc: ...which is what ensure is a replacement for.

16:01 chouser: right

16:02 in practice, it's an unusual bit of code that is susceptible to write skew, but of course it's worth knowing about so that you can use ensure when needed.

16:02 amalloy: mattmitchell: ##(take 10 (map inc (range)))

16:02 sexpbot: ⟹ (1 2 3 4 5 6 7 8 9 10)

16:02 TimMc: chouser: How do I know if I need it?

16:03 Rather, do you know of an example of Clojure code that is susceptible?

16:03 * TimMc googles

16:12 TimMc: OK, so it looks like I need to ensure any refs whose state I only read but whose final value must be consistent with refs I am writing.

16:12 chouser: that's a better description than I was in the middle of writing. :-)

16:14 TimMc: OK, I'll put this on the clojuredocs site.

16:16 Look good? http://clojuredocs.org/clojure_core/clojure.core/ensure

16:17 devn: ^ found out about ensure

16:18 And now if you'll excuse me, I'm off to make sure all my dosyncs are safe from write skew.

16:29 Here's a question: If inside a writing dosync I call a bunch of methods that read from various global refs, how am I supposed to know what I might need to ensure?

16:29 * amalloy just uses atoms

16:31 TimMc: amalloy: How does that help?

16:32 amalloy: TimMc: it doesn't really

16:32 TimMc: heh

16:32 chouser: TimMc: you really want to keep your transactions as small and contained as possible

16:32 amalloy: but i find it easier to think about having a single mutable object enclosing the N things i might need to change

16:33 if i had lots and lots of threads hammering on it at once that might be bad for performance, but this way i don't have to worry about other reds

16:33 refs

16:35 mattmitchell: trying to get contrib.sql do-prepared to work with a collection of records. Anyone know if this actually works with a collection?

16:36 TimMc: My app is a Swing graphics program where everything runs off the event loop, so it is essentially a single-threaded program. I don't *really* need to worry about concurrency. But the moment I add another thread, it'll matter.

16:38 chouser: When the user drags something on the canvas, I have to use a snapshot of the current view rotation, translation, and scale along with the program's tool mode and the list of objects on the canvas. I do some computation, and then I need to update the objects on the canvas and maybe the tool state.

16:39 I do try to keep the transactions small and contained, but in this case one atomic unit of work involves about 3 different refs of maps, minimum.

16:40 amalloy: TimMc: wtf, no it doesn't. minimum, it involves one atom enclusing three maps :P

16:41 TimMc: amalloy: If I merge all my global state into one reference, my program can no longer make use of concurrency when I add threads for animation, etc.

16:43 amalloy: animation threads can just get a @snapshot and not worry if it's a little out of date, no?

16:43 i mean, i'm not asserting that your app would be better with atoms

16:43 but to claim that it is impossible with atoms is patently false

16:46 TimMc: I suppose that animation just needs a snapshot, yeah. It wouldn't be writing anything back to references.

16:46 amalloy: Only one transaction could run on the atom at a time, right?

16:47 amalloy: yes

16:47 or at any rate only one could succeed

16:47 TimMc: right

16:48 I guess I'll stop complaining until I actually need concurrency. :-P

17:10 solar_sea: When I try to start "lein repl" in a new project, I'm getting this - http://pastebin.com/sxJdqYNk What host / port does lein's repl command require ?

17:11 http://pastebin.com/9zmSKe4R - nothing weird in netstat either

17:12 dmiles_afk: does clojure's "," syntax preclude it from ever being read by the lispreader?

17:13 technomancy: solar_sea: it uses localhost and a random port above 1024, but you can override it with LEIN_REPL_HOST LEIN_REPL_PORT

17:13 solar_sea: is it repeatable?

17:13 solar_sea: yes, everytime

17:14 dmiles_afk: i suppose a reader macro of #J could make the lisp reader tollerate clojure's ","

17:14 "," is alwaswy whitespace right?

17:15 hiredman: yes

17:15 technomancy: solar_sea: can you open a ticket with copious details so I can check it later?

17:15 solar_sea: sure, where's the tracker for it ?

17:15 dmiles_afk: teh [ and ] might i guess get tricky

17:16 technomancy: solar_sea: http://github.com/technomancy/leiningen/issues

17:16 TimMc: dmiles_afk: And {}

17:20 NielsE: hi, I have created a new clojure project in eclipse but it does not recognise things from contrib like 'sqrt' and 'primes', but clojure-contrib is in the classpath under libraries in eclipse, how come?

17:21 TimMc: chouser: I would *really* like to see some mention of write skew on the clojure.org/refs page. Should I bug Rich about that?

17:22 NielsE: Have you used :require or :use in your namespace declaration to pull in contrib?

17:23 NielsE: TimMc: somehow I was not aware that I had to use or include the contrib library explicitely, I'll look into it, thanks :)

17:24 raek: technomancy: what does it mean for a project to be installed in leiningen? (I'm thinking about two-param "lein install")

17:24 technomancy: raek: it places shell scripts in ~/.lein/bin

17:24 raek: also, I just discovered "lein repl" outside a project and the swank-clojure shell wrapper. this will aid my introductory talk on clojure very much. :)

17:24 technomancy: raek: I think swank is the only thing that uses it so far

17:25 but I want more people to try it out; clojure's command-line story right now sucks =\

17:25 cools!

17:27 solar_sea: technomancy, I found it, it turned out that my "lo" iface somehow was down

17:27 TimMc: NielsE: (:require [clojure.contrib.math :as math]) in your (ns ...) will let you do math/sqrt

17:27 solar_sea: there's nothing wrong with lein :)

17:27 technomancy: solar_sea: whoa; I didn't even know you could do that. =)

17:28 solar_sea: me neither ... I guess the wicd network manager that I use for wifi settings is to blame, I'll dig it up further some day :)

17:28 TimMc: solar_sea: How did you discover that?

17:29 solar_sea: netstat showed nothing wrong. LEIN_REPL_PORT/HOST didn't work either. Then I disabled ipv6, again to no avail. And I glanced again that "lo" was actually missing from ifconfig's output.

17:30 TimMc: Entirely missing? I would not have noticed that ever.

17:46 Is the rational for class-per-fn that this allows selective code reloading?

17:54 mattmitchell: if i have a function, that accepts a series of optional arguments, how can i pass in a list of args without knowing the length?

17:55 brehaut: (apply + [1 2 3 4 5])

17:55 ,(apply + [1 2 3 4 5])

17:55 clojurebot: 15

17:55 mattmitchell: brehaut: ok cool. so the function i'm actually working with is clojure.contrib.sql do-prepared

17:55 brehaut: i have a collection of row values

17:56 looks something like this: (sql/with-connection db/conn

17:56 (sql/do-prepared insert values))

17:56 brehaut: (apply clojure.contrib.sql/do-prepared foo bar seq-of-values)

17:56 mattmitchell: brehaut: ahh ok :)

18:01 brehaut: thank you

18:02 brehaut: no worries

18:02 raek: TimMc: what would be the alternative to class-pre-fn? you need to have separate classes for separate functions if one function should behave differently from another when called with the same method

18:05 TimMc: Oh right, there are different methods for different arities.

18:06 amalloy: TimMc: i don't think that's relevant

18:06 the point is that functions have to have a general "call me" button, which has to be wrapped up in a method for java

18:06 if function a is to behave differently from function b, they must be different classes implementing IFn

18:06 TimMc: And they all have to be instances of different classes, right.

18:45 amalloy: TimMc: plus, have you ever thought about how closures are implemented? it's a neat trick

18:45 TimMc: Hmm, fair point/

19:10 bennylu: what the equivalance of substring in clojure?

19:11 anyone?

19:12 clojurebot: Please do not ask if anyone uses, knows, is good with, can help you with <some program or library>. Instead, ask your real question and someone will answer if they can help.

19:12 Apage43: ,(.susbtring "doghouse" 3)

19:12 clojurebot: java.lang.IllegalArgumentException: No matching method found: susbtring for class java.lang.String

19:12 bennylu: getit! thanks..

19:12 Apage43: yeah, that should work outside the bot xD

19:14 amalloy: subs

19:14 which i think is in clojure.string

19:14 &(use 'clojure.string)

19:14 sexpbot: ⟹ nil

19:14 amalloy: &(subs "test" 1)

19:14 sexpbot: java.lang.IllegalStateException: replace already refers to: #'clojure.string/replace in namespace: sandbox6385

19:15 amalloy: &(use 'clojure.string)

19:15 sexpbot: java.lang.IllegalStateException: replace already refers to: #'clojure.string/replace in namespace: sandbox6385

19:15 amalloy: lol wtf

19:15 oh i guess it's in core anyway

19:15 &(subs "test" 1)

19:15 sexpbot: ⟹ "est"

19:15 amalloy: bennylu: ^

19:16 bennylu: amalloy, Thanks!

19:34 what the convention for constants in clojure? (for example - in jave its uppercase splitted by '_')

19:35 technomancy: bennylu: lowercase dash-separated

19:37 bennylu: technomancy, but this is the convention for normal variables - because clojure dont have a final/constant keyword i wanted to show the readers of my code that some variable is constant - i guess i will have to add somthing like c-varname

19:38 Apage43: bennylu: shouldn't the preponderance of your variables in clojure be constant..

19:39 if you

19:39 technomancy: you can tell when things are mutable by the presence of deref/atom/agent/ref

19:39 Apage43: if you're going around re'def'ing things that's probably wrong

19:40 bennylu: Apage43, i guess you right.. :)

19:40 i still thinking in java :)

19:43 pdk: bennylu it's a given that they're constant

19:43 amalloy: how do i specify a "source dependency" with cake/lein? it looks like with maven you add a <classifier> element

19:43 pdk: they're all immutable :p

19:43 if you're naming a global symbol though

19:43 the convetion is *like-this*

19:43 amalloy: pdk: that's overgeneralizing

19:44 you define global symbols all the time; only the ones that you intend to be rebound are usually given *earmuffs*

19:44 pdk: barring java objs/reference types

19:44 amalloy: ooo i see there's a :classifier entry in the dependency thingy

19:44 bennylu: pdk, amalloy, thanks

19:50 TimMc: amalloy: I was using the convention of all my global refs (there are about 5) have, uh, earmuffs.

19:50 amalloy: well, altering global refs is similar to rebinding

19:51 except more evil :P

20:00 technomancy: amalloy: what are you using source dependencies for?

20:00 amalloy: technomancy: i'm not really. i just wanted an easy way to get the source for a project

20:01 technomancy: I could see the use for a plugin that could pull in source and build a TAGS file if I had the misfortune to need such a thing.

20:02 seems saner to inspect the <scm> element of the pom though

20:16 pdk: hm

20:16 i'll ask again, for folks who preordered joy of clojure through amazon do you know if you still get early access that way

20:58 TimMc: What is the M in MEAP?

20:58 (speaking of EAP)

21:00 brehaut: Manning (the publisher)

21:00 (i think)

21:02 TimMc: Hah, OK.

21:24 amalloy: indeed

21:30 devn: so erm, any idea on a good regex to capture sexps from strings?

21:32 brehaut: devn, do you want to just find them? or actually get sexps back?

21:32 devn: im typing in this line right now and then i do this (foo (bar (baz 4) "16") \c)

21:33 i want to capture (foo (bar (baz 4) "16") \c)

21:33 Despite_: ooo, fun!

21:33 brehaut: devn: theres not really a good solution to that with regexp

21:33 devn: i figure this is a solved problem but, hm...

21:33 amalloy: devn: if you use regexes to do this you are asking for pain, and also are probably a satan worshipper, no offense

21:33 Despite_: you'll need perl for this!

21:33 devn: amalloy: well, how do you suggest i do it?

21:33 brehaut: for instance (is this) one or (two sexp) ?

21:34 amalloy: &(read-string "(foo (bar (baz 4) \"16\") \c)")

21:34 sexpbot: java.lang.Exception: Unsupported escape character: \c

21:34 brehaut: fnparse

21:34 amalloy: &(read-string "(foo (bar (baz 4) \"16\") \\c)")

21:34 sexpbot: ⟹ (foo (bar (baz 4) "16") \c)

21:34 devn: https://gist.github.com/854070

21:34 that works right now, and it's fast

21:34 but im sick of that code. it's disgusting.

21:35 Despite_: wow

21:35 brehaut: devn: you really are outside of the bounds of regular grammars, and need to write areal parser

21:35 amalloy: devn: please comment on why read-string is no good?

21:36 devn: &(read-string "hello i am in the #clojure irc channel (foo (bar (baz 4) \"16\") \c)")

21:36 sexpbot: java.lang.Exception: Unsupported escape character: \c

21:36 devn: &(read-string "hello i am in the #clojure irc channel (foo (bar (baz 4) \"16\") \\c)")

21:36 sexpbot: ⟹ hello

21:36 amalloy: &(with-in-string "hello i am in the #clojure irc channel (foo (bar (baz 4) \"16\") \\c)" (take-while identity (repeatedly read)))

21:36 sexpbot: java.lang.Exception: Unable to resolve symbol: with-in-string in this context

21:37 amalloy: &(with-in-str "hello i am in the #clojure irc channel (foo (bar (baz 4) \"16\") \\c)" (take-while identity (repeatedly read)))

21:37 sexpbot: Execution Timed Out!

21:37 amalloy: well, something like that anyway

21:37 you probably need a try/catch for eof

21:38 devn: it doesn't need to be perfect and like...understand that \c is ok. it basically just needs to match an equal number of parens on both sides

21:38 (((()))) is valid, for instance

21:39 amalloy: devn: the "regular" in regular expressions means that it has to be context-free, ie not tracking nested parens

21:39 devn: (1(j(4(d)))), same deal

21:39 brehaut: devn are you familiar with http://en.wikipedia.org/wiki/Pumping_lemma_for_regular_languages ?

21:40 devn: brehaut: no, reading now

21:40 amalloy: *nod*, fair enough

21:40 amalloy: these days regular expressions have some non-regular extensions that *do* allow you to do stuff like this, but there are so many reasons not to, especially when you have a whole dang compiler at your disposal

21:40 TimMc: devn: TL;DR: You at least need a stack.

21:40 amalloy: heh

21:40 devn: lol

21:40 pumping lemma sounds like a math porn movie

21:41 TimMc: hawt

21:41 amalloy: TimMc: how much will it cost me to have you follow me around with tldr explanations of my verbose rubbish?

21:41 TimMc: :-P

21:43 devn: lol

21:44 Despite_: perl -MText::Balanced :)

21:44 brehaut: devn the 'best' you can use regexps for here is tokenisation such as ##(re-seq #"(\"(\\.|[^\"])*\")|[()]|[^()\"]*" "abc ( 1 2 ( c d \"ber\" ) ) ) asdf")

21:44 sexpbot: ⟹ (["abc " nil nil] ["(" nil nil] [" 1 2 " nil nil] ["(" nil nil] [" c d " nil nil] ["\"ber\"" "\"ber\"" "r"] [" " nil nil] [")" nil nil] [" " nil nil] [")" nil nil] [" " nil nil] [")" nil nil] [" asdf" nil nil] ["" nil nil])

21:44 brehaut: please excuse the evil

21:44 devn: holy evil

21:44 that's almost worst than what i have now :D

21:44 brehaut: haha

21:44 devn: (but i appreciate the suggestion (and yes this should match too))

21:44 brehaut: its also bound to be broken

21:45 devn: i mean, here's the scenario so you have some context

21:45 because maybe this changes things...

21:46 im rewriting something i was messing with around a year ago that read-lines from the #clojure logs, pulls out s-exps and try to run them in a sandbox

21:46 if they run, the expression as a string is the key, and their value is the result as a string

21:46 that happens in a try catch so i dont really care if its faulty, liberal with parens, etc.

21:47 i just want something that is good enough

21:49 amalloy: &1

21:49 sexpbot: ⟹ 1

21:49 brehaut: $findfn [1 2 3] ([1 2 3] [2 3] [3] [])

21:49 sexpbot: java.security.PrivilegedActionException: java.lang.IllegalArgumentException: Wrong number of args (3) passed to: PersistentVector (NO_SOURCE_FILE:0)

21:50 amalloy: devn: that's a sexp you won't get right :P

21:55 brehaut: devn: (defn tails [s] (when (seq s) (lazy-seq (cons s (tails (rest s)))))) (defn horror [s] (keep #(try (read-string (str %)) (catch Exception e e)) (tails s)))

21:56 its missing an apply before str

21:57 (defn horror [s] (keep #(try (read-string (apply str %)) (catch Exception e nil)) (tails s)))

21:57 much better (for a given value of better)

21:57 that'll find all the legit clojure expressions in a string

21:57 including a bunch of stuff you dont want (eg, anything that looks like a symbol)

21:58 amalloy: brehaut: given input " 1" you'll generate a zillion instances of the expression "1"

21:58 brehaut: amalloy: he said it had to be approximate ;)

21:58 amalloy: also isn't tails just (partial reductions rest)?

21:59 er not quite

21:59 brehaut: i know theres a good way to do it

21:59 but its late friday here and my brain is tired

21:59 amalloy: brehaut: late friday already?

21:59 it's barely late thursday here

21:59 brehaut: new zealand, its the future

21:59 by late i mean late in te work day; about 4pm

22:00 amalloy: i guess i was reading late as 11pm

22:00 brehaut: (defn horror [s] (set (keep #(try (read-string (apply str %)) (catch Exception e nil)) (tails s))))

22:00 hows that :P

22:00 amalloy: (defn tails [s] (take-while identity (iterate #(subs % 1) s)))

22:00 brehaut: my hero!

22:01 brehaut: hah brilliant :)

22:01 amalloy: i use take-while/identity/iterate so often i need to give it a function

22:01 name proposals?

22:01 chouser: TimMc: point 8 refers to the usage of ensure. You wish it used the words "write skew" in particular?

22:03 brehaut: amalloy: its a "take-" something for sure

22:03 perhaps even just take-iterations ?

22:03 amalloy: i have trim-seq for take-while identity

22:03 hm, sensible

22:03 or just iterations

22:04 brehaut: yeah that could work

22:05 amalloy: brehaut: putting that into my new little portably utils library now

22:06 brehaut: awesome :)

22:07 amalloy: i see you have on-thread; why not join the lazier world and just use future :P

22:08 amalloy: well yes

22:08 brehaut: i have that there because i grabbed everything from sexpbot.utils, and apparently Raynes has a reason to want different error semantics

22:08 mebbe i'll junk it

22:11 brehaut: also, (def make-str (transform-if keyword? name str)) instead of keyword you probably want (partial instance? clojure.lang.Named)

22:12 amalloy: brehaut: good point. that too was extracted from another application

22:12 as you can see my util package is pretty new so it's rough around the edges

22:12 brehaut: yeah for sure

22:12 no point creating a utilities package whole cloth

22:12 amalloy: heh

22:13 i'll wait until i can use it to replace contrib, then release it

22:13 brehaut: haha

22:20 later

22:46 dnolen: does calling seq on a lazy-seq force evaluation of the first item?

22:46 to determine if it's non-empty?

22:48 ah

22:48 it seems like it does.

22:49 amalloy: dnolen: yes

22:50 next is basically (comp seq rest)

22:50 er, no it's not. but whatever

23:26 amac: the docstring for future-cancel is hilarious

23:28 tomoj: I never read it that way before :)

23:29 amac: :)

23:31 spewn_: ,(doc future-cancel)

23:31 clojurebot: "([f]); Cancels the future, if possible."

23:31 spewn_: hah

23:34 amalloy: heh

23:34 hopefully it always fails

23:35 arguably it doesn't matter though. some kind of variation on the quantum bogosort

23:39 man, the wikipedia article on quantum bogosort is terrible. if anyone is wondering why i would make such a stupid reference, see http://www.mathnews.uwaterloo.ca/Issues/mn11103/QuantumBogoSort.php

23:45 amac: Man, I hope some parallel asshole doesn't destroy our universe simply because his list was unsorted.

23:46 I like this universe, it contains all my stuff.

23:47 dnolen: is it possible to get the name of a fn like (fn foo []) ?

23:48 technomancy: dnolen: there's an open ticket for putting stuff like that in metadata

23:48 (no patch, just an unhelpful "this should have metadata")

23:48 dnolen: technomancy: heh, thx.

23:49 amalloy: dnolen: you can kinda-sorta do it with ##(class (fn foo[]))

23:49 sexpbot: ⟹ sandbox11264$eval13423$foo__13424

23:49 dnolen: ,(println (fn foo[]))

23:49 clojurebot: #<sandbox$eval2577$foo__2578 sandbox$eval2577$foo__2578@1a707a0>

23:50 dnolen: I just need it for debugging really. would prefer to not get the mangled version.

23:50 amalloy: dnolen: regexes for the win?

Logging service provided by n01se.net