#clojure log - Nov 02 2010

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

0:08 _seanc_: I see that add-classpath is deprecated, what is the correct way to add things to the classpath? I need to add the Sqlite driver :X

0:12 amalloy: _seanc_: i don't actually know about classpath management in clojure. i'd either add it to my CLASSPATH env variable or figure out how to get the jar from maven

0:13 if you're using lein or cake, you should be able to specify a dependency on sqlite in project.clj, and they'll download it, put it on the classpath, and make it Just Work

0:14 _seanc_: I didn't know lein would do that, I'll look into it

0:14 amalloy: it looks like you just have to add [org.xerial/sqlite-jdbc "3.7.2"] to project.clj

0:14 as a dependency

0:16 _seanc_: yeah, just tried it in one of my projects, and it goes and gets it for me

0:16 _seanc_: How did you figure that out?

0:16 amalloy: well, i searched on google for "sqlite maven"

0:16 _seanc_: I was thinking I needed to use clojars, which is 0.5.6

0:16 ah

0:17 amalloy: found the artifact ID and a list of version numbers; picked the newest

0:17 obviously if you need a different version you should specify that instead

0:19 _seanc_: I forget that lein is mavenish

0:20 amalloy: oh by the way, you have to run lein deps to actually *get* the jars

0:23 _seanc_: got that part! :D

0:23 You're awesome, thanks

0:25 amalloy: welcome, _seanc_

0:42 jcromartie: does lein use a local maven repo to store jars of the same version?

0:42 amalloy: jcromartie: ~/.m2

0:42 jcromartie: ok so it doesn't always fetch

0:43 amalloy: no

0:43 jcromartie: I like my build tools to work offline at least at some point

0:43 amalloy: though you can force it to, if you tell it to get a snapshot

1:58 LauJensen: Good morning team :)

2:02 amalloy: mornin' LauJensen

2:08 sthubner: good morning!

2:11 rata_: good morning LauJensen

2:12 how do you get the previous versions of a ref/atom? is it possible?

2:14 amalloy: rata_: you have to track them yourself. you might find add-watch useful

2:14 &(doc add-watch)

2:14 sexpbot: ⟹ "([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 function... http://gist.github.com/659310

2:16 rata_: which files installs lein self-install?

2:17 amalloy: rata_: http://github.com/technomancy/leiningen/raw/master/bin/lein

2:18 rata_: no... I mean... once you run "lein self-install", does it install other files besides "lein"?

2:19 amalloy: rata_: i think it gets a copy of maven, and uses that to get clojure and clojure-contrib, and then the real leiningen jars

2:19 rata_: ok

2:21 amalloy: why do you ask?

2:23 rata_: because the archlinux AUR package installs just /usr/bin/lein and I was suspicious about that

2:23 amalloy: ah

2:24 rata_: ok... a "locate lein" says it installed everything inside ~/.m2 :)

2:24 amalloy: did you solve the problem you had with the value of an atom being changed?

2:25 amalloy: rata_: sorta. i ended up using another atom

2:25 rata_: amalloy: why not use add-watch + set-validator?

2:27 amalloy: rata_: those introduce asynchronicity and/or exception-handling problems that have to be handled with every swap!

2:29 rata_: amalloy: I didn't know that... why is it so? add-watch says the fn is called synchronously

2:30 amalloy: rata_: sure, synchronously, but then your watcher function has to do something that causes the original caller/swapper to abort the swap, or notice it hasn't applied cleanly. that seems even less clean to me

2:32 and even if it's technically synchronous, you have to do basically the same thing as if it were asynchronous. try using it yourself

2:33 rata_: and why don't you compare the old value with the new value in the caller/swapper?

2:34 amalloy: rata_: then i can't tell whether it stayed the same because (f old-val) == old-val, or because (pred (f old-val)) was false

2:35 rata_: do you need to make that difference?

2:35 and the value is an integer, right?

2:35 amalloy: in my particular case...maybe, i'm not sure. but i wanted to generalize this to be useful for every instance of this problem

2:36 rata_: what are you working on?

2:36 amalloy: sexpbot, at the moment

2:36 it wants to make sure only N threads can be servicing requests at a time

2:37 so i could do it by comparing the old-val and new-val, since it's just an integer and i know it's incrementing

2:37 but i was hoping to solve the problem in a more general way

2:38 hiredman: uh

2:39 amalloy: http://download.oracle.com/javase/tutorial/essential/concurrency/pools.html

2:42 amalloy: hiredman: good point, and maybe the right long-term answer. but what if, eg, someone sends sexpbot a million long-running requests via /msg? the current implementation sends them back a million error messages; a thread pool would queue them all up, locking up sexpbot until they were done

2:49 rata_: amalloy: and set-validator! + try-catch?... if the validator fn returns false, it throws an exception and you know it failed... and you don't need the extra atom

2:50 amalloy: rata_: no, but i need a try/catch. i don't think either is much better than the other

2:52 rata_: my current implementation is at http://bit.ly/aw8GIW if you want to tell me how it could be better

2:52 rata_: a macro could hide the try-catch thing in a beautiful thing... maybe (changed? (swap! an-atom inc) :some-kwd)... if it doesn't change :some-kwd will be returned... it's the same logic as (get ...)

2:52 amalloy: rata_: you don't really need a macro; you can do it in a function that hides the same logic

2:53 rata_: can you do it? the exception would be thrown on the swapper function and not in "changed?"

2:54 amalloy: rata_: see the commit i linked. i used an atom, but the function could use try/catch similarly

2:57 rata_: which commit?

2:58 amalloy: http://bit.ly/aw8GIW

3:02 rata_: amalloy: yes, it's the same idea

3:07 but maybe the try-catch thing will be a little faster, as it doesn't need to create an atom (which I suppose isn't cheaper than throwing an exception, but don't know really)

3:08 amalloy: rata_: i don't know either, but i had the opposite intuition - i know exceptions are slow, and the STM seemed like it had to be faster

3:09 rata_: oh ok

3:17 amalloy: I was away when you said it, but congratulations for being in the contributors list =)

3:17 amalloy: heh, thanks

4:50 rata_: good night :)

4:59 esj: Morning all

5:02 LauJensen: Morning esj

6:15 Kenjin: hello

6:30 Could someone take a look please? https://gist.github.com/ffaea21e7de730165da6 thanks

6:44 esj: Kenjin: I get a "connection refused" but I have zero idea about java.rmi

6:45 Kenjin: esj: the java bit has to be running

6:46 basically "r.rebind("rmi://localhost/rmiconnect", rc);" creates an object rmiconnect in the rmi-registry

6:46 esj: ox

6:46 sorry to be no help

6:47 Kenjin: esj: no problem. thanks for taking look :)

7:32 neotyk: &(loop [s '(1 2 3)] ((fn [] (if-let [r (next s)] (recur (rest s))))))

7:32 ,(loop [s '(1 2 3)] ((fn [] (if-let [r (next s)] (recur (rest s))))))

7:32 clojurebot: java.lang.IllegalArgumentException: Mismatched argument count to recur, expected: 0 args, got: 1

7:33 neotyk: can someone explain why (fn [] takes precedence over (loop [..] ?

7:34 LauJensen: neotyk: It looks up the tree and grabs the first match IIRC

7:35 neotyk: Hi LauJensen, yes, that is for sure what happens

7:35 any ideas how do I make sure that loop is used?

7:35 I have no option to get rid of this fn []

7:36 this is generated by macro of with-connection from sql

7:41 ok, local let FTW

8:16 LauJensen: clojurebot: clojureql?

8:16 clojurebot: clojureql is http://gitorious.org/clojureql and tracked @ http://clojureql.lighthouseapp.com/

8:16 LauJensen: clojurebot: forget clojureql

8:16 clojurebot: clojureql is http://gitorious.org/clojureql and tracked @ http://clojureql.lighthouseapp.com/

8:16 LauJensen: clojurebot: clojureql is http://github.com/LauJensen/clojureql

8:16 clojurebot: Roger.

8:32 _na_ka_na_: how to do byte operations in Clojure? For example how to do 76 & 0xFF

8:35 cemerick: -> (bit-and 76 0xFF)

8:35 ,(bit-and 76 0xFF)

8:35 clojurebot: 76

8:36 cemerick: huh, no sexpbot

8:36 _na_ka_na_: ^^

8:36 _na_ka_na_: thanks

9:17 tonyl: morning

9:17 neotyk: afternoon

9:23 fliebel: morning

9:24 raek: fliebel: did you manage to see this? http://pastebin.com/9CUeiq3W

9:24 5 mins after you left...

9:24 fliebel: raek: No, I didn't

9:26 raek: Great! Only I just posted it to the mailinglist :(

9:26 tonyl: fliebel: it's happened to me before

9:27 fliebel: raek: Trying it right away.

9:29 raek: as jarpiain said, reduce builds up a nested lazy sequence of map calls

9:31 fliebel: raek: Right. I was hoping someone would say something like that. My firt thought was a mistake, then I thought of a lazy gotcha, but hten I started to belive it was a real bug.

9:35 raek: Works! Next step is to figure out why it is so slow and make it use all my cores.

10:03 jaley: hello! can anyone clarify the ! naming convention for me? is it supposed to indicate side-effects only? or something else?

10:04 raek: jaley: side-effects that are not safe to do in a transaction or a transition function (or anything that might be executed more than one time)

10:05 drewr: I generally use it to also mean there's no interesting return value from the function (though that's not necessarily clojure's position)

10:05 jaley: ok.. so it'd be sensible to use it for operations that send things over a network? as in... i don't want to resend requests in transactions being retried

10:05 raek: yes

10:05 jaley: cool - thanks guys!

10:10 fliebel: How can I do type hinting inside of ->?

10:11 bsteuber: I like the quote "Java is the new COBOL" from clojure in action

10:12 chouser: heh. I thought that was VB

10:12 bsteuber: might be nice on a T-Shirt :)

10:12 chouser: or PHP, or ...

10:12 bsteuber: true, there are more candidates

10:12 tonyl: fliebel: do you mean data type hinting or fn parameters type hinting

10:14 fliebel: tonyl: I think the data thing. I get reflection warnings for a few method calls without parameters.

10:14 chouser: fliebel: you should be able to hint the previous expression.

10:15 fliebel: tonyl: I'm doing something like (-> file .method1 .method2)

10:16 chouser: I hinted the starting value, but I don't understand where the type gets lost and how to add it back.

10:17 http://github.com/pepijndevos/Clomian/blob/master/src/clomian.clj#L20

10:18 chouser: fliebel: these are just guesses since I don't have the required jars to test it, but it's probably just the (get ...) forms that Clojure can't figure out the return type of

10:19 so try hinting those, like ^LevelObject (get "Level")

10:19 fliebel: chouser: I turned them into .get calls, which didn't help. Will try the hint there.

10:25 chouser: oh, you should hint file too

10:27 fliebel: chouser: I hinted nearly every single line in that macro :(

10:30 chouser: All these methods are now java, so they should have a set return type. But I keep getting 2 of these: Reflection warning, clomian.clj:25 - call to get can't be resolved.

10:30 Reflection warning, clomian.clj:27 - reference to field getValue can't be resolved

10:32 AWizzArd: interesting: I was running (time (dotimes [i 10000000] (XYZ "12345"))) and got those timings (in msecs) for XYZ replaced with: empty? 560, not-empty 560, (not (empty? )) 650 (why is this so much slower?), seq 480, .isEmpty 3 (winner), (not (.isEmpty )) 42

10:32 (time (dotimes [i 10000000] (not true))) ==> 41 msecs

10:33 Is timing (not true) mostly measuring how long looking up 'not' takes?

10:38 $(let [*14-days* 14] 10)

10:38 ,(let [*14-days* 14] 10)

10:38 clojurebot: 10

10:38 AWizzArd: ,(let [+14-days+ 14] 10)

10:38 clojurebot: Invalid number: +14-days+

10:39 AWizzArd: Bug or feature? ;)

10:49 jcromartie: AWizzArd: what

10:49 AWizzArd: I'm confused

10:50 ,'+1

10:50 clojurebot: 1

10:50 jcromartie: ,'+1-

10:50 clojurebot: Invalid number: +1-

10:51 tonyl: so +1 is a number

10:52 ,+1

10:52 clojurebot: 1

10:52 tonyl: ,-1

10:52 clojurebot: -1

10:52 tonyl: pos and neg

10:53 fliebel: get you give a snippet of the blocks fn, to see how the type hinting of java calling is going.

10:54 fliebel: tonyl: "get you give"?

10:55 tonyl: *can you give or post a snippet

10:55 :P mybad

10:56 fliebel: tonyl: I have this with ^java.io.File at the top and get > .get http://github.com/pepijndevos/Clomian/blob/master/src/clomian.clj#L20

10:57 tonyl: alright, i'll test it

10:59 fliebel: awesome

11:00 tonyl: does the input file has some special markup or it can be a file with any content?

11:01 fliebel: tonyl: It's a nbt file. I don't think you can test it without installing jnbt and getting some sample file.

11:02 tonyl: I think I'm better of finding a profiler and utilizing my other core than nitpicking about reflection.

11:04 tonyl: yeah... I haven't mess with nbt files

11:14 jcromartie: wow can we have an official Clojure version of this http://docs.python.org/faq/programming

11:19 chouser: AWizzArd: for me, all the seq/empty calls (with or without not) come in at essentially identical times, and .isEmpty (with or without not) is indeed about 100x faster

11:20 oops, sorry, was scrolled way up.

11:36 AWizzArd: chouser: are you on 1.3α2 ?

11:36 chouser: yeah

11:37 AWizzArd: and is (not (.isEmpty )) as fast as .isEmpty alone, or takes 10x as much runtime?

11:38 mrijk: Hi all... I am looking for the tree picture (hires) from the presentation "The Roots of Clojure"

11:39 * mrijk pings fogus_ :)

11:39 AWizzArd: My timings were .isEmpty < (not (.isEmpty )) < seq < empty? < not-empty < (not (empty? ))

11:42 chouser: AWizzArd: same speed

11:42 .isEmpty == (not (.isEmpty )) < seq == empty? == not-empty == (not (empty? ))

11:42 AWizzArd: you're letting hotspot have a chance to inline everything?

11:51 fliebel: tonyl: I don't understand half of what I'm doing in this profiling app, but it seems it's spending quite a lot of time reflecting, and runs on one core at the moment.

11:53 tonyl: is it reflecting all the methods?

11:54 for sure it is not reflecting anything clojure, that is the weird part

11:54 fliebel: tonyl: I'm not sure. I think only 2-4 of them.

11:57 chouser: fliebel: if you care about performance, it's absolutely worth getting rid of reflection

11:57 fliebel: what version of Clojure are you using?

11:57 fliebel: chouser: I figured… 1.2

11:58 chouser: and it's complaining about .get and .getValue?

11:58 fliebel: yea

11:59 chouser: care to paste or push what you've currently got?

12:00 fliebel: okay, but currently… it stopped "working" i.e. giving reflection warnings. So I'll get those back fisrt.

12:00 chouser: hm

12:01 actually, wait a sec

12:02 fliebel: okay, it "works" again

12:02 http://github.com/pepijndevos/Clomian/blob/master/src/clomian.clj#L23

12:03 Check this for the return values: http://jnbt.sourceforge.net/doc/

12:03 chouser: .getValue only claims to return an Object. What type is it actually going to return?

12:03 fliebel: all but the last one return CompoundTag the last bye[]

12:05 and get returns some sort of map, does it matter which one?

12:05 chouser: a Clojure map?

12:05 fliebel: no, java.util.map

12:05 chouser: ok

12:09 CompoundTag doesn't have a 'get' method

12:09 fliebel: chouser: ^org.jnbt.CompoundTag (.get "Level") for both gets leaves me with only this one: Reflection warning, clomian.clj:28 - call to get can't be resolved.

12:10 chouser: oh, .get is returning a CompoundTag

12:10 ok, I'm caught up

12:10 Kenjin: hi

12:10 fliebel: yea, I'm confused as wel..

12:11 Kenjin: Anyone done some rmi with clojure? https://gist.github.com/ffaea21e7de730165da6

12:11 chouser: try ^java.util.Map (.getValue) instead of the first .getValue

12:11 fliebel: getValue returns a map of tags, and those tags return another map.

12:12 briljant! Works so far :)

12:12 chouser: :-)

12:15 fliebel: Now I only need to figure out how to use my other core. Agents, future, pmap… I don't know. Does Joy of Clojure have a chapter on this?

12:17 chouser: hm, what you want is parallelism, I think, not concurrency

12:18 which is currently better covered outside clojure's core features than within them.

12:18 fliebel: chouser: You mean in Java?

12:18 chouser: I mean Clojure has these innovative features to address concurrency, but little of its own to address parallelism

12:19 but perhaps pmap or the forkjoin lib would help.

12:19 tonyl: futures?

12:20 chouser: either way, you're going to need to figure out what chunks of work are expensive enough to be worth farming out to other threads

12:20 there's some interesting stuff coming to integrate forkjoin with Clojure vectors, but I'm not sure if it's available anywhere yet.

12:20 fliebel: chouser: IO? I'm reading 2000 files ;)

12:20 chouser: Liebke gave a talk on it at Clojure Conj.

12:21 fliebel: chouser: I saw the slides.

12:21 AWizzArd: chouser: did the Conj gave any insights about what opportunities Clojure will have in future versions to tackle parallelism?

12:21 chouser: fliebel: if you're IO-bound, you may not be able to keep all your cores busy

12:22 fliebel: chouser: I'm not sure I am… I'm just doing a lot of it.

12:23 chouser: AWizzArd: just what I mentioned.

12:24 angerman: are there any enty level clojure presentation slides up online somewhere I might take a look at for inspiration?

12:24 chouser: angerman: rhickey's videos are still the gold standard (and widely mimicked) I believe

12:24 angerman: -for-lisp-programmers and -for-java-programmers

12:25 AWizzArd: chouser: yes, saw it after hitting Enter.

12:25 chouser: AWizzArd: :-) ok

12:25 angerman: you're giving an intro talk?

12:25 angerman: chouser: yep, tomorrow.

12:25 chouser: heh

12:26 angerman: it's at the chair at my university where I'm writing my final thesis.

12:26 chouser: well, I've given a couple of those now, and next time I think I'm going to try keep the number of "clojure syntax" slides to 1 or 0

12:27 fogus_: chouser: 1 is more ffective

12:27 chouser: I liked how my expression-problem talk went in that regard -- present an interesting problem and some code in a familiar language that sets up or solves the problem

12:27 fogus_: with a single bullet ;-)

12:27 chouser: fogus_: * none ?

12:28 then once they've got the data structures/problem space in their head, re-present with clojure syntax.

12:28 and *hopefully* they can just ease into it without concentrating on the details too much

12:28 angerman: nah, they do know java fairly well. We had a talk on python a few weeks ago and they were interested and at the same time scared that you could probably poke any object with lots of crap.

12:28 chouser: heh

12:29 "you could, but you don't" :-)

12:29 angerman: though I'd say they are very likely familiar with functional approaches.

12:29 so it's more a "so we got the JVM we like, and here's a language that put's the fun back into programming.

12:31 fliebel: chouser: Some high-tech profiling with Activity monitor and println shows that I'm doing 100% of one core and not so much IO, though the number of files being read is huge(I estimate 5 per second).

12:31 clojurebot: Ok.

12:35 chouser: fliebel: freqs takes the bulk of youre time?

12:36 fliebel: btw, you can (repeat 128 {})

12:37 fliebel: chouser: I think so, but I haven't tried very hard to profile.

12:40 chouser: There are a few copies of pvreduce floating around on github. That sounds like the thing I need.

12:54 lpetit: Hi, in the github "clojure" organization, the sub project names are not prepended with "clojure.". While I can see this makes sense because they already are in the "clojure" organization, there's still the problem that this "organization" metadata is github specific, not git. So by default when people will start to "fork" clojure organization's project, not having this "clojure." prefix may be a problem. At least I know that for my

12:59 Wouldn't it make sense to add a "clojure." prefix to the project names ?

13:10 amalloy: lpetit: like change the clojure repository from "clojure" to "clojure.clojure"?

13:11 lpetit: Oh please

13:12 amalloy: like clojure.data.finger-tree instead of data.finger-tree, (or maybe clojure-data.finger-tree to follow the "contrib" convention ?)

13:16 must leave, have posted the question on IRC? cu

13:16 s/IRC/ml/

13:30 amalloy: &(class #"")

13:30 ,(class #"")

13:30 clojurebot: java.util.regex.Pattern

13:31 amalloy: ,(class java.util.regex.Pattern)

13:31 clojurebot: java.lang.Class

13:31 fliebel: amalloy: The mysterious Class object :)

13:32 amalloy: fliebel: i always forget and try to use Pattern/class

13:37 being able to just use Pattern will be very convenient if i ever remember it

13:48 alpheus: I need help understanding when function names are bound to the function object. I tried to write a trace utility (using robert.hooke) to trace a recursive function, and, of course, the call inside the function was to a function *before* the hook was installed, so only the outer function call was traced.

13:49 In Lisp, I might try to bind later, using something like funcall through a name to designate the function.

13:51 amalloy: alpheus: (declare) is for forward declarations

13:51 chouser: alpheus: this is changing between 1.2 and 1.3. which version would you like to discuss? :-)

13:52 alpheus: 1.2, I guess. I'm hoping to have some working code before 1.3 is released ;)

13:56 chouser: hm

13:56 I thought I knew, but I'm seeing behavior I wasn't expeting

13:56 alpheus: We can pretend I'm debugging fib: (defn fib [n] (if (= n 1) 1 (* n (fib (- n 1))))) ;; not the production version, of course

13:57 chouser: duh, I'm on 1.3

13:58 hm, same on 1.2

13:58 ubii: trying to find some recent Clojure podcasts or videos, can anyone point me to a few?

13:58 most of the ones that I have found so far, are from 2008

13:58 also, any word on when the Clojure Conj videos will be available?

13:58 chouser: alpheus: you can delay var resolution for you recursive call by using (#'fib (- n 1)) instead

13:59 alpheus: indeed?

14:00 Thank you. It does just what I needed.

14:00 chouser: alpheus: that'll work the same going forward

14:01 ubii: chouser: when do you expect JoC to be completed?

14:01 chouser: note there's some runtime cost because it derefs #'fib each time its called

14:01 ubii: going through the MEAP now and am really enjoying it

14:01 kryft: ubii: December, I think.

14:02 chouser: ubii: thanks! the chapters are essentially complete. hoping for tree pulp version in December

14:02 alpheus: It's funny. I tried the same thing with Stuart Sierra's trace and when it didn't show the inner function calls, I decided to write my own using robert.hooke.

14:02 Now I know the real answer.

14:02 chouser: ohhhh

14:03 alpheus: I'm lucky my employers are tolerant of my learning clojure on their dime!

14:03 ubii: chouser: when do you plan to go back and address some of the minor spelling/grammar and formatting issues in the MEAP, which folks have brought up on the MEAP forum?

14:04 chouser: ubii: the copyeditors are hard at work, presumably as we speak.

14:04 ubii: chouser: cool, thx

14:05 kryft: chouser: Hehe, glad to hear that, although I love the content. :)

14:05 clojurebot: amespaces are (more or less, Chouser) java packages. they look like foo.bar; and corresponde to a directory foo/ containg a file bar.clj in your classpath. the namespace declaration in bar.clj would like like (ns foo.bar). Do not try to use single segment namespaces. a single segment namespace is a namespace without a period in it

14:06 chouser: ,(macroexpand-1 '(defn f [] (f)))

14:06 clojurebot: DENIED

14:07 chouser: hmph

14:07 alpheus: anyway, look at the macroexpansion carefully

14:07 alpheus: and tell me what defines f at the point of the recursive call

14:09 ubii: chouser: I have to say that I really like the approach you guys took, where you start off by explaining the philosophy of Clojure and providing an overview of the core concepts, as compared to other books, which simply jump right in to basic syntax

14:09 kryft: Agreed.

14:09 It really is a joy to read in that respect.

14:10 chouser: well, that's good to hear. those two chapters got shuffled repeatedly through the process before finally landing with philosophy first.

14:10 kryft: I also like how you actually explain a bit about what's going on under the hood (eg. how to implement persistent data structures efficiently)

14:11 chouser: kryft: I was going to go with "it's magic", which is just one more reason why it's good to have fogus_ as a co-author.

14:11 ubii: :)

14:12 amalloy: chouser: well, neither of you is wrong

14:13 kryft: chouser: :)

14:17 arohner: when using paredit, how do you split a string into two strings? i.e. "foo | bar" -> "foo " "bar"

14:18 amalloy: arohner: M-shift-s, as i recall

14:18 maravillas: M-S perhaps?

14:19 arohner: amalloy, maravillas: yes, thank you

14:19 paredit-split-sexp

14:20 fliebel: Are there any gotchas for using transients? I have a seq of transient maps, but when I do (map persistent!) on them, I get "Transient used after persistent! call"

14:23 AWizzArd: fliebel: do you have a doall around your map?

14:23 You better should use doseq here.

14:23 amalloy: hm, not that i know of.

14:23 &(map persistent! (map transient! (map range (range 4))))

14:23 sexpbot: java.lang.Exception: Unable to resolve symbol: transient! in this context

14:23 amalloy: &(map persistent! (map transient (map range (range 4))))

14:23 sexpbot: java.lang.ClassCastException: clojure.lang.LazySeq cannot be cast to clojure.lang.IEditableCollection

14:24 amalloy: oh well :P

14:27 fliebel: still nothing.

14:29 chouser: fliebel: transients are not mutable collections in the classic sense. you have to leave your code structured as for persistent collections

14:29 ...and just do a transient up front and a persistent! afterwards

14:30 LauJensen: &(-> [1 2 3] transient (conj! 4) persistent!)

14:30 sexpbot: ⟹ [1 2 3 4]

14:31 fliebel: chouser: I do that… I think. I have a seq of transients, and when I do persistent! on one item, it works. When I do it to all in a map I get an error.

14:31 AWizzArd: fliebel: do you have a 'doall' around your map?

14:32 chouser: hmmm

14:32 fliebel: AWizzArd: I'm on the repl, so they're going to get realized anyway.

14:32 chouser: actually, it might have to be around inner map's

14:34 ,(last (map persistent! (map-indexed #(conj! %2 %1) (map transient (repeat 100 [])))))

14:34 clojurebot: [99]

14:34 chouser: hm, or maybe not

14:34 ,(last (map persistent! (map-indexed #(conj! %2 %1) (repeat 100 (transient [])))))

14:34 clojurebot: java.lang.IllegalAccessError: Transient used after persistent! call

14:35 fliebel: chouser: This works: (persistent! (first t)) This doesnt: (doseq [t t] (println (persistent! t)))

14:35 chouser: fliebel: are you sure they're different transients?

14:36 fliebel: chouser: Different? t and t is the same thing.

14:36 chouser: ,(let [t (repeat 2 (transient []))] (= (first t) (second t)))

14:36 clojurebot: true

14:37 chouser: ,(let [t (map transient (repeat 2 []))] (= (first t) (second t)))

14:37 clojurebot: false

14:38 Raynes: chouser: One of these days I'm going to replace your comma and ampersand keys while you're in the shower.

14:38 fliebel: chouser: wait… you are onto something there. If I would add an item to one of those transients, would the other get updated as well?

14:39 chouser: fliebel: sometimes, yes.

14:39 jarpiain: ,(persistent! (second (reductions conj! (transient []) [1 2 3 4]))

14:39 clojurebot: EOF while reading

14:39 jarpiain: ,(persistent! (second (reductions conj! (transient []) [1 2 3 4])))

14:39 clojurebot: [1]

14:39 jarpiain: ,(map persistent! (reductions conj! (transient []) [1 2 3 4]))

14:39 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.IllegalAccessError: Transient used after persistent! call>

14:40 chouser: Raynes: , is clojure whitespace -- I find this a convenient coincidence

14:40 not to mention a hard habit to break. :-)

14:40 fugue: Is there any way to pass system properties while using lein swank ?

14:40 fliebel: chouser: Woo, changing (repeat 128 (transient {})) into (repeatedly 128 #(transient {})) solved the problem :P

14:41 chouser: fliebel: :-) there you go

14:41 Raynes: chouser: Understandable. Fortunately, outside of #clojure, sexpbot responds to ,.

14:41 chouser: Raynes: have you considered ,, ?

14:41 hm, nm

14:41 Raynes: Everybody hates two character prefixes.

14:41 chouser: ,,:already-taken

14:41 clojurebot: :already-taken

14:42 Raynes: Good prefixes are hard to find these days. ;)

14:42 chouser: what else has sexpbot used? -> and now & ?

14:43 Raynes: -> "still works"

14:43 sexpbot: ⟹ "still works"

14:43 chouser: ah, cool.

14:44 Raynes: I added & because, as I mentioned before, everybody hates two character prefixes.

14:45 fliebel: woot, using transients cut my map-hammer-time in half :)

14:46 * Raynes runs off to eat soup while watching horrible movies.

14:47 fliebel: but I'm still limited by the speed the one core I'm using :(

14:49 ubii: fliebel: one core, why?

14:50 fliebel: ubii: because I haven't figured out how to use the other one yet.

14:51 ubii: fliebel: dumb question, is that due to how you coded things or due to your OS?

14:51 ariejan: Hello. I'm new. My name is Ariejan. Any one worked with aleph here? How can I print the user-agent string?

14:52 fliebel: ubii: because of how I coded things.

14:53 ariejan: I don't know, but I think you'll find the answer in Ring.

14:53 alpheus: chouser: Not sure if I'm getting what you're showing me, but in (defn f [] (f)) the call to f is ultimately an arg to fn*

14:54 chouser: alpheus: yes. and f is defined by (fn f ...), which is shadowing the outer (def f ...)

14:54 ubii: fliebel: ah, ok

14:54 alpheus: ok, that makes sense

14:55 jarpiain: hmm isn't the recursive call in (def f (fn [] (f))) also compiled to this.invoke() ?

14:55 chouser: alpheus: so, could do (declare f) (def f (fn [...] ... (f ...)))

14:55 jarpiain: with or without previous declare

14:56 chouser: forcing that inner f to refer to a var instead of a local

14:58 alpheus: I see. I'll have to think about that for a while.

14:59 chouser: ah, and formulated that way still works fine in 1.3

15:01 alpheus: Naturally, I'm starting to wonder what's really going on with recur.

15:02 chouser: recur compiles to a goto, I believe

15:03 kotarak: alpheus: are you the "hanging defmethod" guy?

15:03 chouser: jarpiain: I don't think the compiler knows f is this in (def f (fn [] ...))

15:03 alpheus: kotarak: No, I don't think so.

15:03 kotarak: alpheus: ah. ok. never mind.

15:05 alpheus: This is a pretty great channel. But I guess you all knew that already.

15:05 jarpiain: chouser: right, just checked. The 'f is used to name the generated class but not as a this-label

15:05 chouser: jarpiain: huh! I didn't realize the name was propogated in at all. interesting.

15:06 kotarak: (def f (fn f ...))?

15:06 jarpiain: that's the only thing the third argument of analyze() is used for

15:06 chouser: kotarak: no, without the inner name

15:07 (class @(def my-name-is-here (fn []))) ;=> user$eval267$my_name_is_here__268

15:07 kotarak: chouser: I meant with (fn f ...) the function knows itself as f.

15:08 chouser: kotarak: yes, but even without that the outer def passes the name in such that the generated class includes it. jarpiain knew this, but I'm just learning.

15:15 rata_: hi all

15:16 fliebel: hi

15:16 kotarak: chouser: you didn't know?

15:16 o.O

15:17 rata_: which profiler do you guys use?

15:17 hiredman_: it's wasn't always the case that defn propagated the name like that

15:17 kotarak: I was wondering what happens if I have something like (defn foo ...) + somehwere else (let [f (fn foo [] ...) ...) Do I get a clash in class names?

15:18 hiredman_: no

15:18 fliebel: rata_: I just toyed with visualVM, but I don't *use* it.

15:19 rata_: fliebel: ok.. how was it?

15:20 fliebel: rata_: Like stacktraces.

15:33 In Python there is glob to mach certain files. What is the best way I can do this in Clojure? file-seq coms closest I think. Should I just do regexes on that and filter?

15:35 amalloy: fliebel: i haven't looked for a clojure-specific way, but java.io.File has a list(FilenameFilter) method

15:36 fliebel: amalloy: But that doesn't do recursion I think. that is more like ls | grep

15:37 amalloy: yeah, and it's kinda gross anyway, i guess

15:41 fliebel: i don't see any better way than file-seq/regex, unless you want to use the shell's globbing

15:43 though it's still going to recurse into directories whose children you know you won't want

15:44 implementing filtered-file-seq yourself would be a trivial modification of http://bit.ly/bHsvOu

15:44 fliebel: amalloy: I already figured out the regex.

15:46 amalloy: you understand what i meant about recursing into uninteresting subdirs though, right? you can't fix that with just a regex

15:47 if that doesn't matter to you, and it might well not, then go for it

15:47 fliebel: amalloy: I realize that. I'll think about it.

15:47 amalloy: There are some 2000 files in a sub dir I'd like to avoid.

15:49 amalloy: well then, time to implement filtered-file-seq :)

15:50 fliebel: amalloy: Yea… You're right.

15:53 chouser: (tree-seq #(and (.isDirectory %) (not (re-find ... (.getName %)))) #(.listFiles %) (File. ...))

15:54 amalloy: chouser: no cigar. you need to filter the children, not the branches

15:55 chouser: hm, I suppose you're right

15:55 fliebel: but, how does this work? listFile only returns the files, not the directories, if I'm corect.

15:56 amalloy: fliebel: you're not correct, though :)

15:57 fliebel: amalloy: Which part of my assumtion is wrong?

15:57 amalloy: it returns all the File objects, and directories are Files

15:57 fliebel: amalloy: java.io is strange...

15:57 amalloy: http://download.oracle.com/javase/1.4.2/docs/api/java/io/File.html#listFiles%28%29

15:58 yes, it's a dreadful mess

15:59 ubii: I still can't get use to seeing oracle associated with java, instead of sun

16:01 amalloy: fliebel: http://download.oracle.com/javase/1.4.2/docs/api/java/io/File.html#listFiles%28java.io.FileFilter%29 could be used to return just the files or just the directories

16:02 fliebel: amalloy: Hav you seen how I am to create a FileFilter?

16:03 amalloy: fliebel: well, if you were going to do it i'd use reify. but FileFilter is a hack around java's lack of HOFs like (filter)

16:03 fliebel: amalloy: I was also thinking reify.

16:06 chouser: amalloy: one of many

16:06 amalloy: fliebel: (seq (-> (java.io.File. ".") (.listFiles (reify java.io.FileFilter (accept [this f] (.isDirectory f)))))) is how you could do it with reify

16:06 ohpauleez: ubii: me too

16:06 every time I see the docs, I freak out a little

16:07 fliebel: amalloy: I know :) (thanks to chouser)

16:08 clojurebot: Why are you asking *him*

16:08 ubii: having been a Sun sysadmin, in my previous life, I find it painful to now see Oracle pasted on everything :(

16:09 technomancy: it would be good to make it easier to navigate between the wiki on dev.clojure.org and the ticket tracker

16:09 I only found http://dev.clojure.org/jira by some random poking around

16:18 fliebel: which of all those 508 functions does the opposite of filter? I can do use not of course but I know it's there.

16:19 chouser: rmove

16:19 remove

16:19 fliebel: yay!

16:19 chouser: fliebel: http://clojuredocs.org/clojure_core/clojure.core/filter

16:20 kotarak: (filter (complement your-predicate) ...) for another road to Rome

16:20 fliebel: ooh

16:22 ubii: wait, clojuredocs is written using Rails, what happened to eating our own dog food? :)

16:23 technomancy: ubii: at least it's not closed-source anymore =\

16:23 ubii: technomancy: what was it before?

16:23 meant to say, what was it using before?

16:23 technomancy: I guess they had "unique scalability requirements".

16:23 no, I mean it's always been rails, but at least now it's open to community improvement

16:23 ubii: ah

16:24 wait, rails can scale, when did that happen? :)

16:25 chouser: I'm so happy to have a site like that -- if having it written with rails is what it took, so be it.

16:25 ubii: sorry, being a ruby guy, I have to bash a bit on rails

16:26 of course, even though I do ruby, I haven't touched rails in years

16:26 chouser: I agree, the tools used to build it are much less import than the fact that it exists

16:27 I was just being a smarta$$, since I knew technomancy was a fellow ruby convert

16:28 chouser: I've done a fair amount with ruby myself, though only one (attempted) rails projects.

16:28 ubii: I will shut up now and get back to reading JoC :)

16:29 technomancy: I was just a little put off by the way they brushed off compojure as "not ready" without providing constructive criticism. I think it's good that the site exists.

16:30 chouser: If I had the time to contribute to a such a project, their choice of tools would matter to me more, I'm sure.

16:33 * ubii continues to avoid taking care of several client requests, so he can focus on learning Clojure, in the hopes of expediting his transition from Ruby to Clojure

16:35 ubii: I really should be working on implementing the necessary reporting capabilities for the Sinatra app that I wrote last week, which does email campaign monitoring

16:37 * ubii wonders how difficult it would be to port this app to Clojure, using ring and compojure

16:38 LauJensen: ubii: Only slightly more difficult than doing the same using ring and Moustache

16:38 At least for me :)

16:38 bobo_: im starting to prefer moustache aswell

16:38 mabes: ubii: yeah, it wouldn't be too hard unless you are relying on a lot of gems (e.g. for openauth)

16:38 bobo_: noticed that compojure 0.5.x was released recently though, dont know what changed

16:39 ubii: LauJensen: actually, someone else suggested that combo, so I will look at that as well

16:40 bobo_: and dont forget to look at enlive if you want templating!

16:41 LauJensen: Yea, Moustache/Enlive is a winning combo

16:42 ubii: thx, I will check them both out

16:42 * Raynes uses hiccup.

16:43 ubii: unfortunately, due to time constraints, I will need to finish up the reporting capability, using Sinatra

16:43 then I can go back and look at porting it

16:43 Raynes: The only thing keeping me from really liking Compojure is the furious lack of documentation.

16:43 ubii: still learning Clojure, so it is probably premature to try and port it right now

16:44 apgwoz: isn't compojure more or less just a url mapping framework at this point? ring handles pretty much everything else as far as i can tell.

16:44 raek: it seems so

16:44 ubii: then again, I never touched Sinatra before I wrote this app, but at least I knew Ruby

16:44 danlarkin: I've never heard a lack of something be called furious

16:44 apgwoz: (well, compojure + hiccup (or something like it) + ring)

16:46 drewr: you can read compojure's src quicker than an equivalent how-to

16:46 rlb: Can you create a class instance when the class is stored in a variable, i.e. (def x Integer) (??? x 5)?

16:46 new won't work

16:47 I can easily work around it -- mostly just curious.

16:48 pjstadig: ~suddenly

16:48 clojurebot: CLABANGO!

16:49 cemerick: danlarkin: along the lines of "violent agreement", perhaps :-)

16:49 danlarkin: welcome back to irc ;-)

16:50 alpheus: vehement apathy

16:50 lrenn: rlb:

16:50 mabes: rlb: you can use .newInstance.. However, that doesn't seem to work on Integer.. Here is an example:

16:50 ,(let [x java.util.Date] (.newInstance x))

16:50 clojurebot: #<Date Tue Nov 02 13:51:49 PDT 2010>

16:50 lrenn: ->(let [c java.lang.String] (.newInstance c))

16:50 sexpbot: java.lang.IllegalArgumentException: No matching method found: newInstance

16:50 danlarkin: cemerick: ahoyhoy

16:50 _seanc_: What is the best way to iterate over a seq and create a new collection with the values from the first? (Does that make sense?)

16:50 lrenn: oddly, that works in my repl.

16:50 hiredman: _seanc_: you mean map?

16:50 cemerick: outlandish asceticism

16:51 _seanc_: hiredman: I tried map, it gave me an error

16:51 kotarak: "an error" means....?

16:51 _seanc_: I cleared the terminal :X

16:51 let me get it ahain

16:51 hiredman: _seanc_: well you did it wrong

16:51 duncanm: why is ^int not allowed as a type hint? is it useless to hint that?

16:51 _seanc_: again*

16:51 hiredman: that much I've come to expect :D

16:51 clojurebot: hiredman is lazy

16:52 kotarak: ,(map identity [1 2 3])

16:52 hiredman: clojurebot: I'll replace you with a very small shell script

16:52 clojurebot: (1 2 3)

16:52 clojurescript is Chouser's baby

16:53 tonyl: what's up with clojurebot and its random quips? somebody logged in like it?

16:53 they are funny though lol

16:53 rata_: has anybody used profiler4j?

16:53 danlarkin: tonyl: it's NLP

16:53 amalloy: clojurebot: clojurescript?

16:53 clojurebot: clojurescript is Chouser's baby

16:54 amalloy: tonyl: ^^ he just overeagerly matches "regular" chatter as a question directed at his info database

16:54 tonyl: foo hahaha

16:54 i thought it was just for an instant repl in the chat

16:54 hiredman: overeagerly?

16:55 kotarak: rata_: I used jvisualvm with success. But YMMV.

16:56 amalloy: hiredman: well he piped up with a quote about clojurescript just because your message to him ended with "script"

16:56 clojurebot: script

16:56 _seanc_: hiredman: where did I go wrong http://pastie.org/1267706

16:56 hiredman: amalloy: saw your link to the horrible code you wrote to limit the number of threads running a task, I still don't see why you just don't use a threadpool

16:57 _seanc_: doseq returns nil

16:57 map is lazy

16:57 amalloy: hiredman: yes, i agree it's pretty horrible

16:57 hiredman: so do it right

16:57 I pasted you a link to the pool docs

16:57 _seanc_: I guess that's where I'm lost. The tutorial on SQL (wikibooks) has them using doseq

16:58 amalloy: hiredman: i'm trying to improve thread-safety in the current code without changing its semantics

16:59 hiredman: if the semantics are garbage they should be changed

17:00 amalloy: hiredman: fixedthreadpool queues up pending requests; currently sexpbot discards them. i don't see any particular reason to prefer queueing them instead of discarding them

17:01 hiredman: you can easily write a custom threadpool

17:02 you wouldn't even need a custom threadpool

17:02 amalloy: hm, okay, i'm looking at ThreadPoolExecutor

17:03 _seanc_: hiredman: since map iterates over the coll, how do you access the current value within the function?

17:03 Ah ha! I figured it out

17:03 tonyl: _seanc_ is the parameter passed to the fn

17:03 _seanc_: it's the combination of #(%) - right?

17:03 tonyl: or (fn [parameter] parameter)

17:04 _seanc_: granted, while it works, I still don't fully understand #

17:04 tonyl: cool! That's awesome thanks for the tip

17:04 amalloy: _seanc_: then i suggest not using #(...) yet. it's really shorthand for (fn [...] ...)

17:05 _seanc_: amalloy: oh, well that's a really straightforward explanation. You need to write a blog so I can read it :D

17:05 bobo_: you can also just use defn and create a function if you want to name it.

17:05 amalloy: haha, maybe i'll start collaborating with Raynes, since I Don't Blog either :P

17:06 _seanc_: I try to look all of this stuff up ClojureDocs, but for instance they don't have # on there

17:06 amalloy: _seanc_: # isn't limited to this usage - it's not a function, so to speak

17:07 # is a trigger character that the reader treats specially depending on what character is next

17:08 for example:

17:08 &(map class [#(inc %) #{1} #".*"])

17:08 sexpbot: ⟹ (net.licenser.sandbox.box5691$eval5848$fn__5849 clojure.lang.PersistentHashSet java.util.regex.Pattern)

17:09 _seanc_: Ah, very cool

17:11 bobo_: http://clojure.org/reader has more info on it

17:11 _seanc_: Just arrived there!

17:11 thanks bobo_

17:11 bobo_: :-)

17:13 amalloy: ah right, #' and #_. i knew i'd forgotten a couple

17:14 Raynes: amalloy: I really don't. Now that the conj is over, I doubt I'll find things worthy to blog about. I don't make many interesting discoveries on my own.

17:14 amalloy: Raynes: i know. i don't either. but i found your blog title very amusing

17:15 ubii: damn, I will be happy when the elections will be over tonight, as my phone has been ringing non-stop for days, with automated campaign messages from various candidates and election pollers calling

17:16 that is the disadvantage of working from home

17:18 technomancy: ubii: disadvantage of having a land-line more like =)

17:18 ubii: true, the only reason I have it is associated with my DSL

17:19 pjstadig: i just never answer my phone when the caller-id is an 800 number

17:19 or "Unavailable"

17:19 ubii: it is supposed to be a freaking business line, but somehow it is still listed as a residential line, which is why everyone and the brother calls it

17:20 yet, I can't get it added to the do not call list, because it is a business line

17:20 go figure

17:20 damn, catch 22

17:20 sorry, didn't mean to vent, just tired of hearing that damn phone ring

17:21 amalloy: ubii: get a call-screening device? or google voice?

17:21 bobo_: or just mute the phone

17:22 ubii: I should, but that would make too much sense :)

17:22 bobo_: or move to sweden and get a dsl connection without a phone!

17:24 pjstadig: or vote for people who will change campaign laws

17:24 Nafai: I'm so glad I don't have a landline

17:29 LauJensen: Good night to everybody in #landline

17:42 fliebel: Dang! The Python version of my parser does in seconds what takes my Clojure version minutes…

17:44 Raynes: Make it faster.

17:44 fliebel: Raynes: I've been doing that all day :(

17:44 apgwoz: what does the parser do?

17:44 err, what does it parse

17:45 fliebel: apgwoz: Read a bunch of NBT files and plot frequencies.

17:46 Raynes: Stop. Hammock time.

17:46 fliebel: ?

17:47 Raynes: I keep forgetting that not everybody was at the Conj.

17:47 Rich talked about 'hammock' time in his second talk at the Conj. It's become a bit of a meme.

17:48 danlarkin: http://p.hagelb.org/hammock.jpg

17:48 fliebel: danlarkin: Oh, well, that explains it all...

17:49 raek: is it only in my language a hammock is one of these? http://randomfunnypicture.com/wp2/wp-content/uploads/2010/04/meanwhile-in-finland.jpg

17:49 (modulo the snow and the finnish guy)

17:49 fliebel: I guess (not= Hammock Hammer)?

17:50 Raynes: But what did you mean to say?

17:51 Raynes: It was actually completely random and entirely unrelated to what you were saying before it.

17:51 Like a clojurebot message.

17:52 fliebel: Raynes: Okay :( I was hoping you had some smart insight on how Python can outperform Clojure.

17:53 apgwoz: Raynes: in all actuality, i took your comment to mean, "fliebel should stop and think about the problem for the night. the solution will come to him"

17:53 which relates back to rich's talk

17:53 :)

17:53 Raynes: apgwoz: Right. We'll go with that. fliebel: ^ That's what I meant to say.

17:53 apgwoz: haha

17:54 fliebel: okay, good night all ;)

17:54 Raynes: Good night. May the Rich be with you.

17:55 fliebel: Maybe tomorrow someone can explain me how to profile and improve my code.

17:56 amalloy: raek: i think we'd call that a swing bench or something silly like that, but it's close to a hammock. hammocks are tradionally more like http://www.hammocks.com/hammocks/fabric-hammocks/textalinehammocknavystripe.cfm

17:56 raek: ah, a "hängmatta"

17:59 apgwoz: Raynes: woah, you have an affect on people :)

17:59 Raynes: I do?

17:59 apgwoz: well, fliebel left.

18:00 presumably to go think about the problem.

18:03 Raynes: hiredman: ping

18:05 hiredman: I'm terribly sorry that I am not the perfect coder, but I *do* accept patches and advice, but I don't respond well to flat out insults.

18:06 If you'd like to talk about anything, assuming you get these messages, let me know. I'd love to discuss whatever reason you have for despising me so, and I'd certainly like to resolve any issues.

18:12 danlarkin: he has you on ignore, just fyi

18:12 Raynes: I figured.

18:12 Any clue as to why?

18:13 I mean, he's welcome rub me in the dirt all he wants, but surely he isn't going to insult everybody with an association to sexpbot now. That would be unfortunate. :\

18:14 I suppose this isn't the place to discuss such things though. I'll leave it be.

18:18 angerman: how do i have to understand (.instanceMember Classname args*)?

18:18 ahh so that's a constructor.

18:18 or not? ... yikes

18:19 duncanm: hmm, what's an idiomatic way to remove some entries out of a map based on its val?

18:20 (into {} (remove #(pred? (val %)) my-map)) ?

18:20 angerman: filte?

18:20 clojurebot: ,(let [testar (fn [x y] (cond (= (reduce + (filter odd? (range 0 x))) y) (str y " is a")) )] (testar 11 25))

18:20 angerman: filter?

18:20 clojurebot: filter is not map

18:20 gfrlog: ,(deref (future (+ 7 8)))

18:20 clojurebot: 15

18:22 gfrlog: am disappointed that partition can drop elements off the end of your list

18:22 ,(partition 3 (range 5))

18:22 clojurebot: ((0 1 2))

18:22 scgilardi: gfrlog, see partition-all

18:22 gfrlog: awesome, thanks :)

18:22 scgilardi: angerman: see http://stackoverflow.com/questions/2753874/how-to-filter-a-persistent-map-in-clojure

18:23 amalloy: &(.length "10")

18:23 &(.add (ArrayList.) 10)

18:23 sexpbot: ⟹ 2

18:23 java.lang.IllegalArgumentException: Unable to resolve classname: ArrayList

18:23 amalloy: &(.add (java.util.ArrayList.) 10)

18:23 sexpbot: ⟹ true

18:23 amalloy: angerman: ^^

18:23 raek: angerman: (.method object arg1 arg2) is java object.method(arg1, arg2);

18:24 angerman: (.method SomeClass arg1 arg2) is java SomeClass.method(arg1, arg2);

18:25 angerman: raek: so a class can have nonstatic methods. hmm...

18:25 scgilardi: whoops, http://stackoverflow.com/questions/2753874/how-to-filter-a-persistent-map-in-clojure was for duncanm

18:25 raek: "(.instanceMember Classname args*)" does not make much sense, since instances (objects) and classes are different things

18:25 amalloy: angerman: do you have java experience?

18:25 angerman: scgilardi: wasn't bad for me to review that either :D

18:26 raek: angerman: static=class, instance=object

18:26 angerman: raek: but that's precicely how it's on the clojure.org/java_interop page stands

18:26 raek: so my thinking was right. But the confidence was too low.

18:26 amalloy: angerman: poorly written, then

18:27 angerman: to me the 1st 3rd and 4th line make sense

18:27 raek: yes, how unfortunate...

18:27 angerman: the 2nd one doesn't.

18:27 amalloy: &Boolean/TRUE

18:27 &(. Boolean TRUE)

18:27 sexpbot: ⟹ true

18:27 java.lang.IllegalArgumentException: No matching method found: TRUE

18:28 * raek adds this to his list of things to mention in that clojure.org review mail thread

18:28 amalloy: ugh, i can never remember how to get at static fields using . notation

18:29 raek: angerman: yes, your thinking was right

18:29 rata_: amalloy: is it that possible? I thought / was the way

18:29 raek: the / way expands to the dot form

18:30 but the / way is considered more ideomatic

18:30 amalloy: &(macroexpand 'Boolean/TRUE)

18:30 sexpbot: ⟹ Boolean/TRUE

18:30 amalloy: &(macroexpand '(. Boolean TRUE))

18:30 sexpbot: ⟹ (dot Boolean "TRUE")

18:31 amalloy: raek: the interup section angerman is talking about seem to suggest that (. Boolean TRUE) should work; do you know what was wrong with my example?

18:32 gfrlog: (dot toString true)

18:32 ,(dot toString true)

18:32 clojurebot: java.lang.Exception: Unable to resolve symbol: dot in this context

18:32 raek: I think 'dot' is something in the implementation of clj-sandbox

18:33 amalloy: gfrlog: also, booleans are primitives, which don't have a toString method. use (String/valueOf true) instead

18:33 gfrlog: silly primitives!

18:33 ,null

18:33 clojurebot: java.lang.Exception: Unable to resolve symbol: null in this context

18:33 amalloy: gfrlog: yeah

18:34 &nil

18:34 sexpbot: ⟹ nil

18:34 gfrlog: is nil null, or is it an object?

18:34 amalloy: it's null

18:34 &(String/valueOf nil)

18:34 sexpbot: java.lang.NullPointerException

18:34 amalloy: really?

18:35 gfrlog: &(println "java.lang.NullPointerException")

18:35 sexpbot: ⟹ java.lang.NullPointerException nil

18:35 gfrlog: dang it lets you tell the differenc

18:35 raek: amalloy: (. Boolean TRUE) works in a normal repl

18:35 amalloy: raek: thanks

18:36 Chousuke: or just Boolean/True

18:36 er

18:36 TRUE

18:37 amalloy: Chousuke: sure, of course that's the "right" way; but i was confused that . didn't work

18:38 Chousuke: ah, right.

18:39 wsimpson: why is one less right?

18:40 gfrlog: because it is left

18:41 or more left at least

18:41 wsimpson: touche.

18:41 Chousuke: wsimpson: The sugared form is prettier :P

18:42 therefore better.

18:44 kotarak: if rich says that one form is to be prefered over this other, this is enough "right" for me.

18:45 amalloy: wsimpson: my suspicion is because String/valueOf makes it look like a first-class function, while (. String valueOf) makes it look like something else

18:46 wsimpson: Ah. That makes sense.

18:46 Chousuke: String/valueOf also makes it clear that it's a static field/method

18:47 wsimpson: Duly noted.

18:48 Thanks. :)

18:50 zencobras: Just getting starting with clojure and emacs (tough combo, but fun). Anyone willing to answer a couple of questions? I am trying the labrepl exercises, and when I run 'slime-connect', get the following : "Versions differ: nil (slime) vs 20100404 (swank). Continue? (y or n)". The REPL seems to run OK - but how to I resolve this version issue?

18:52 arohner: zencobras: add (eval-after-load 'slime '(setq slime-protocol-version 'ignore)) to your .emacs

18:52 zencobras: Package list shows slime 20100404, slime-repl 20100404 and swank-clojure 1.1.0.

18:52 arohner: thanks!

18:54 arohner: worked like a charm

18:59 rickmode: I keep wanting to know if an object is a single object, or some sort of sequence, but *not* a map. I'm tending to use coll?, and when I control the type of object, I use seq?, but I really want something like c.c/seqable? that doesn't allow nil. Basically I want (at least) non-nil lists, vectors, and ArraySeq's to pass. Perhaps I'm attacking the problem wrong?

18:59 arohner: ,(doc sequential?)

18:59 clojurebot: "([coll]); Returns true if coll implements Sequential"

19:00 arohner: rickmode: does that do it for you?

19:00 cemerick: rickmode: there's a seqable? in clojure.contrib.core, but it's a fundamentally flawed concept

19:00 rickmode: cemerick: how so?

19:01 raek: rickmode: what will you use this function for?

19:01 a macro?

19:01 rickmode: arohner: perhaps sequential? is what I want

19:01 cemerick: rickmode: Because seq is polymorphic beyond what can be representable by the JVM's type system. Protocols will fix this, but there's not yet a Collection protocol or somesuch that would provide a proper seqable? fn that collection implementations could implement.

19:02 s/can be/is

19:03 rickmode: raek: I'm thinking of things similar to how "The Little Schemer" attacks atoms and lists. Basically I want various functions to all one or more items, and I'd like the caller to pick any sort of sequence. E.g. (foo (list :a :b)), (foo [:a :b])

19:03 cemerick: rickmode: until then, we're left with things like clojure.contrib.core/sequable?, which is just a bunch of instance? checks essentially.

19:03 rickmode: raek: seems wrong somehow to force a particular sort of sequence

19:04 raek: maybe you could do a cond with the map? test before the coll? test

19:04 rickmode: raek: I don't usually allow either a map or coll, but ya - that works in those cases. Perhaps sequential? is the right forward-compatible beast?

19:06 cemerick: does sequential? cover all cases where an object can behave list-like? (that is, supports first and rest/next)?

19:06 cemerick: rickmode: no, sequential? tests for (instance? Sequential x). That only includes seqs, vectors, and lists.

19:07 rickmode: cemerick: what other listy things are there?

19:07 cemerick: which leaves out strings, maps, and java.util.Lists, to name some others that work with first/rest/next

19:07 tonyl: &(supers Sequential)

19:07 sexpbot: java.lang.Exception: Unable to resolve symbol: Sequential in this context

19:08 cemerick: &(supers clojure.lang.Sequential)

19:08 sexpbot: java.lang.NullPointerException

19:08 cemerick: ,(supers clojure.lang.Sequential)

19:08 clojurebot: nil

19:08 cemerick: ach, not supers

19:08 clojurebot: http://haacked.com/images/haacked_com/WindowsLiveWriter/IConfigMapPathIsInaccessibleDueToItsProt_1446B/works-on-my-machine-starburst.png

19:08 cemerick: tonyl: you want "descendents", except it doesn't exist ;-)

19:08 rickmode: cemerick: so it's OK for clojure-only code, but doesn't generalize. Perhaps it's ok for my cases though. - ya I look at Seqeuential... it's a type-marker.

19:09 (empty interface)

19:09 tonyl: yeah, i was looking in the docs :P

19:09 clojurebot: Huh?

19:09 raek: I know I have had the same thought as rickmode about finding something similar to listp and atomp

19:09 but for some reason, it has not been a problem for me

19:09 rickmode: raek: ya that's why i was wondering if am attacking the problem wrong

19:10 raek: maybe I tend to treat one data structure specially in the fn, and leave everything else as-is

19:10 like in http://gist.github.com/633049

19:11 in common lisp, it's mostly black and white. either something is a list or an atom

19:11 in Clojure, there's lots of data structures

19:11 rickmode: raek: your gist makes sense... but what if you want to allow single objects too.. then you hit my scenario.

19:11 raek: one of the aspects that make it non-lispy

19:12 ,(coll? "foo")

19:12 clojurebot: false

19:12 raek: yeah...

19:12 rickmode: raek: indeed. clojure (correctly) adds sets and maps to the list. It has not (yet) unified all possible sequences though

19:13 raek: I'm afraid I don't have any good answer

19:13 rickmode: the list meaning, the list of fundamental data structures

19:13 hiredman: coll? checks to see if it's an ipcollection

19:14 which a string certainly isn't

19:14 neither are many Collections

19:14 raek: ah,

19:14 ,(coll? (java.util.ArrayList.))

19:14 clojurebot: false

19:14 rickmode: I *think* I'm ok with sequential? for these clojure functions (i'm not worried about java interop). I'm hoping callers can do (foo :a) (foo (list :a :b)) (foo [:a :b]) and (fn [& rest] (foo rest))

19:14 raek: sounds resonable to me

19:15 rickmode: but *not* (foo {:a 1, :b 2})

19:16 makes me think this "one or many" idiom is somehow flawed

19:19 amalloy: rickmode: why not allow maps? if the caller wants to treat their map as a list of pairs, who are you to stop them?

19:19 if you somehow managed to exclude maps, they could just (foo (seq {:a 1 :b 2}))

19:20 rickmode: amalloy: in this particular case, the caller is passing in one or more keywords... a map wouldn't make sense, but just about anything else would. (The keywords are parameter names for form validation like, :first-name, :last-name).

19:21 raek: rickmode: you wouldn't be using ring.middleware.params?

19:21 rickmode: amalloy: I think I'm still getting over my OO/strong-typing hangover. coll? will do the trick, i think. a map will cause a barf on first usage, so that's good enough

19:22 amalloy: rickmode: it will barf on (foo [[:a 1] [:b 2]]) too, so coll? isn't really helping

19:22 rickmode: raek: right. (though I don't feel like using ring.middleware.keyword-params - I'm sticking with (name :first-name) since I have only about 3 usages of name.

19:22 raek: rickmode: I think it is simpler to let the user pass the single thing in a collection of size 1, unless there is any compelling reason

19:23 amalloy: you could do like: (and (coll? x) (not-any? coll? x))

19:23 raek: I don't like the way wrap-params handles multiple values of the same key

19:24 I think it should split into two variants: one that always store a single value per key (last one wins) and one that has a vector for each key

19:24 Raynes: raek: Made any interesting progress on your message parser lately?

19:24 rickmode: raek: oh... i'm not doing that. I'm rolling (yet another) form validation system. I'm allowing something like (validator [:password :password2] #(= %1 %2) "passwords don't match")

19:25 hiredman: surely you mean (validator [:password :password2] =)

19:25 raek: looks very much like something I started to work on once... :)

19:25 rickmode: raek: as well as (validator :first-name #(not (str/blank? %) "first name required")

19:26 raek: Raynes: well, I think the vocabulary is starting to crystallize

19:26 rickmode: http://gist.github.com/586836

19:26 amalloy: rickmode: oh. so more like (or (not (coll? x)) (not-any? coll? x))

19:26 Raynes: raek: Irclj is attention starved. If it doesn't get new code soon, I fear it'll begin gnawing on sexpbot an any other bot it can get it's parentheses around.

19:27 and*

19:27 raek: rickmode: also http://github.com/Kaali/pour

19:28 which that was a remix of

19:29 Raynes: you will love the abstractions that are in my mind currently

19:30 Raynes: raek: :D

19:30 * raek mutters because "message" means so many things in the context of IRC

19:30 rickmode: raek: heh.. ya it's kinda like that... though I'm reading up on monads and it seems like validation... and perhaps the entire response cycle, can be recast / simplified with compossable m-state.. er .. thingies

19:31 raek: rickmode: I know very little about monads, but I have a hunch that they might be a good fit

19:38 rickmode: raek: is your weby stuff in a github project?

19:39 raek: not yet

19:39 this will eventually be a lib, but I haven't had much time to work on it, unfortunately

19:40 Raynes: raek: By the way. We have to change the name of Irclj to (apply str (distinct (str "irc" "clj"))). Only difficult thing will be the namespaces. :P

19:44 raek: I should get some sleep

19:44 but I don't wanna

19:44 Clojure is way too fun

19:44 gn

20:38 ymasory: is there a function that makes a seq of n elements by applying the provided function n times and collecting its results?

20:38 i can do this with a comprehension or map but i would need a range too

20:39 tonyl: ,(range 10)

20:39 clojurebot: (0 1 2 3 4 5 6 7 8 9)

20:40 ymasory: tonyl: hm?

20:42 amalloy: &(doc repeatedly)

20:42 sexpbot: ⟹ "([f] [n f]); Takes a function of no args, presumably with side effects, and returns an infinite (or length n if supplied) lazy sequence of calls to it"

20:42 amalloy: ymasory: ^^

20:42 &(repeatedly 10 rand)

20:42 sexpbot: ⟹ (0.23348923774335106 0.8732098324061308 0.582779226332408 0.9926034362933805 0.9522604963670783 0.5401583818751448 0.3418314042183209 0.15130219536490885 0.5458508576119281 0.241182907854135)

20:43 amalloy: that what you were looking for?

20:43 ymasory: amalloy: thank you yes

21:44 fbru02: hey guys ... so Leiningen uses ant to run right ?

21:46 amalloy: fbru02: maven

21:47 fbru02: amalloy: did this change recenly ? from the doc For the actual task execution cycles it uses Ant under the covers via Lancet. ????

21:49 brb

21:49 amalloy: okay. i wouldn't be astonished to find out that that's true, i guess, but i thought it used maven for everything. if technomancy were around i'd say ask him

21:50 fbru02: amalloy: thanks !

21:51 tonyl: I thought it uses maven for dependencies and for alternative building with a pom file instead of project.clj

21:51 but i've been out of the leiningen for a while

21:52 amalloy: tonyl: it looks like that's true. lein and cake both use ant for actual compilation

22:24 gfrlog: ,(apply * (range 500))

22:24 clojurebot: 0

22:25 amalloy: &(apply * (range 1 500))

22:25 tonyl: &(apply * (range 1 500))

22:25 sexpbot: ⟹ 244027365198222013740247757084609385250714868560638568438482717677169074630776399521099289500440656372602723295429640716832675744415635440096157041031865857095581514387866120754592171817254085834909576484982545268861134034654153892212560462090528843775757893150955429972698873556207528854806765473079... http://gist.github.com/660719

22:25 ⟹ 244027365198222013740247757084609385250714868560638568438482717677169074630776399521099289500440656372602723295429640716832675744415635440096157041031865857095581514387866120754592171817254085834909576484982545268861134034654153892212560462090528843775757893150955429972698873556207528854806765473079... http://gist.github.com/660718

22:25 tonyl: lol

22:25 amalloy: lol

22:25 tonyl: that was weird

22:25 gfrlog: that was weird

22:25 * amalloy is hacking your brain

22:26 gfrlog: I was remarking to myself how you both came up with the number 500....

22:26 * tonyl is wondering if he's been watched

22:26 amalloy: notice the gists came out of order?

22:27 tonyl: yeah

22:27 lag

22:27 amalloy: yeah, presumably latency on github's end

22:29 gfrlog: presumably the designers of github forgot to include the library that determines what order numbers come in

22:29 amalloy: #include <reality.h>?

22:30 gfrlog: import org.apache.integers.comparison.*;

22:30 tonyl: i think it's built in ruby

22:31 gfrlog: ,(ruby-eval "660718.is_less_than?(660719)")

22:31 clojurebot: java.lang.Exception: Unable to resolve symbol: ruby-eval in this context

22:31 gfrlog: unacceptable

22:31 ymasory: where does autonomous code go in clojure considering agents don't have a loop? in a java thread?

22:32 amalloy: ymasory: autonomous? do you mean asynchronous, maybe?

22:33 ymasory: amalloy: autonomous. as in autonomous threads/actors

22:33 agents you pass functions to from the current thread of control. they don't have an independent thread of control, from what i understand

22:33 or my bad, yes they do, to run the function

22:34 i guess i could just pass the agent the looping function (i.e. the "run" method of a java thread)

22:34 amalloy: ymasory: every clojure function is a java object that implements Runnable. if you want, you can pass them to a thread

22:34 &(supers (class (fn [])))

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

22:35 ymasory: amalloy: pass them to a thread or to an agent?

22:35 amalloy: either will take them; what you should do depends on your goal

22:36 ymasory: what is the guarantee i get from an agent over the same code running in a thread?

22:38 amalloy: agents are basically an object that queues up actions, and passes them to a thread one at a time

22:38 if you create ten threads and start them all, they run in parallel; if you create an agent and send it ten functions, they run in series

22:40 ymasory: so the main benefit of agents is that they manage the thread pool for me?

22:40 hiredman: agents provide an identity for a series of values over time

22:40 amalloy: they also have a value

22:40 hiredman: just like refs and atoms

22:41 ymasory: right, i guess this is mind-shock for me trying to integrate threads and value-holders into one useful entity

22:41 amalloy: right. if you just want threads, use clojure futures, and/or java threadpools

22:42 tonyl: is there a clojure construct for threadpools?

22:42 cemerick: tonyl: threadpools are a fundamentally hosty concept

22:42 amalloy: but to perform a series of actions that are conceptually related and need to share state, agents are perfect

22:42 tonyl: even for the jvm?

22:42 cemerick: of course

22:43 see java.util.concurrent

22:43 hiredman: well the jvm is the host

22:43 cemerick: .NET/CLR has something equivalent

22:44 tonyl: ok

22:44 i guess i need to learn more about the parallel concepts than just the summaries

22:44 good, thanks

22:44 cemerick: and then Clojure hosted on some platform that has no threadpool abstraction (probably javascript, for example) just won't be able to support e.g. futures

22:45 tonyl: got it

22:46 ymasory: are agents supposed to fall off like java threads, or is it safe to terminate them directly?

22:46 amalloy: ymasory: fall off?

22:47 cemerick: ymasory: agents are lightweight reference types whose values change asynchronously *via* threads

22:47 so talking about "terminating" them doesn't really make sense

22:47 ymasory: cemerick: well in my case i'm passing them a looping function, like you would the run function in a java thread

22:48 i guess i'm not supposed to do that

22:48 cemerick: ymasory: you mean a fn that never returns?

22:48 amalloy: ymasory: yeah, that's covered in Agent Abuse 101 :)

22:49 ymasory: yeah it's a total abuse of an actor too (coming from a scala background here)

22:49 amalloy: it sounds like you want a direct analog to java threads

22:49 in clojure that's a future, not an agent

22:49 cemerick: ymasory: just a future will do fine

22:50 amalloy: ymasory: the idea with sending agents functions is that they take the function's return value and store it as their new state

22:51 if the function never returns, that is a huge warning signal that you shouldn't use agents; for one thing, all agents share a limited threadpool, and you're monopolizing one of their threads

22:51 ymasory: oh i see. instead of an actor sending back a reply

22:51 amalloy: ymasory: maybe. i don't have any real background in scala or erlang

22:53 hiredman: you can use send or send-off inside an agent to loop

22:54 ymasory: hiredman: send a message to yourself?

22:54 hiredman: it's not a message

22:54 it's a function

22:54 but yes

22:54 ymasory: ah

22:55 cemerick: ymasory: *agent* is bound to the current agent

22:55 ymasory: very nice

22:56 so i think the last part of this puzzle is figuring out how i can schedule a function to be sent to an agent in the future

22:56 that what a future is?

22:57 hiredman: send or send-off is scheduling an action to be run in the future

22:57 cemerick: A future simply runs some code asynchronously, retaining the result, and blocking on derefs until that value is available.

22:58 ymasory: hiredman: i meant how can i delay the send call

22:58 hiredman: why?

22:58 clojurebot: why not?

22:58 hiredman: clojurebot: buzz off

22:58 clojurebot: Titim gan éirí ort.

22:58 ymasory: hiredman: because it's a modeling project, the model only allows a function every so often

22:59 cemerick: ,(print "I can't do that, Dave.")

22:59 clojurebot: I can't do that, Dave.

22:59 amalloy: ymasory: (future (Thread/sleep 5000) (inc 1))

22:59 hiredman: ymasory: use a scheduledthreadpool

23:00 cemerick: we should be able to get parameterization of threadpools into send, send-off, and future for the 1.3.0 cycle

23:00 tonyl: what is the meta :once true for?

23:00 ymasory: &(future (Thread/sleep 5000) (println "hi!"))

23:00 sexpbot: ⟹ #<core$future_call$reify__5500@f84033: :pending>

23:01 hiredman: cemerick: has rich indicated interest in that?

23:02 amalloy: &@(future (Thread/sleep 5000) (inc 1))

23:02 sexpbot: ⟹ 2

23:03 cemerick: hiredman: yes, indicated that is was a semi-safe bet for "release.next" just prior to the 1.2.0 release IIRC

23:03 s/is/it

23:04 tonyl: is the future object just a reified object done on the fly?

23:05 cemerick: future is a macro that creates an anonymous fn that is run on a dedicated threadpool

23:06 tonyl: i meant on future-call

23:06 amalloy: &(macroexpand '(future (Thread/sleep 5000) (inc 1)))

23:06 sexpbot: ⟹ (clojure.core/future-call (fn* [] (dot Thread "sleep" 5000) (inc 1)))

23:07 cemerick: tonyl: future-call does that dispatch of any fn, returning a java.util.concurrent.Future that also happens to implement IDeref

23:08 hiredman: I had a patch once that, if I recall, let you pass in something on agent creation (it was something out of Agent.java that you could proxy if you wanted to) with the idea of being able to create agents that would have their actions run on the EDT

23:08 that did not go over well

23:09 maybe I should have just offered the patch without mentioning my envisioned use

23:09 cemerick: yeah; IIRC, Rich said he'd be looking to parameterize the send itself

23:09 hiredman: oh

23:09 interesting

23:10 cemerick: My general impression is that there are deeper rearchitecting that are on the table though…which is why I never offered up a patch. ;-)

23:10 * cemerick sucks at English tonight for some reason :-(

23:11 hiredman: I must say I never use agents though

23:20 ymasory: hiredman: what do you use?

23:25 amalloy: ymasory: whatever tool is suitable for the job, i imagine

23:26 agents sound deceptively useful, because they incorporate both mutability and concurrency, which are tricky problems in general

23:26 but most of the time, you want something else

23:26 hiredman: lots of futures and promises

23:27 ymasory: i guess i was perfectly happy with actors

23:34 cemerick: There's no reason to generalize about which construct is better than another; they all have their uses for different types of problems.

23:45 amalloy: cemerick, ymasory is right: i use a fork to eat everything because it's just the best eating utensil. sometimes soup is a little tricky, and i wish campbells would fix that bug, but otherwise i'm very happy with my fork

23:46 cemerick: heh

23:46 ymasory: all i said was that i was happy. but i guess happiness is an offensive idea in a developer's life :)

23:47 cemerick: ymasory: don't worry, I'm sure amalloy was sending nothing but <3 ;-)

23:47 ymasory: yeah he's the man

23:49 Raynes: amalloy has magic in him. Magic, I say.

23:49 amalloy: Raynes: shhhhh, you'll let all the magic smoke out

Logging service provided by n01se.net