#clojure log - Jan 20 2010

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

0:09 replaca: new rule proposal: projects written in Clojure may not have the letter "j" in their names

0:10 technomancy: replaca: yes please!

0:11 that cocoa bridge had a name that just made me cringe

0:12 defn`: i like the ji thing

0:12 like djirk

0:15 technomancy: personally I'm naming all my projects after literary characters from now on

0:17 alexyk: technomancy: how about I sing praises for leiningen every day for 5 days if you add host to lein swank in addition to port tmrw? :)

0:17 replaca: I think I'll go for the dullest possible names

0:18 starting with "autodoc"

0:18 technomancy: alexyk: you could spend the time you would potentially spend singing praises to write the code. =)

0:18 replaca: which would be pretty cool if it took out your appendix, but less so with the whole html generation thing

0:18 alexyk: technomancy: I don't know where to begin, macros scare me

0:19 plus I don't know swank and where the host would need to be stuck/plucked from

0:19 I'd rather stick to my core competency of singing and let you add it :)

0:19 technomancy: heh

0:19 defn`: my core competency is witchcraft

0:20 technomancy: alexyk: the swank server binds to more than just localhost for me

0:20 alexyk: defn: don't you have to be a witch to practice it?

0:20 technomancy: did you want to limit it to *just* localhost?

0:20 alexyk: technomancy: no, I don't see it binding to the external IP. Hmm.

0:20 I actually wanted to have a host to explicitly tell it to bind there.

0:20 defn`: alexyk: i havent gotten that far yet

0:21 alexyk: defn: I never heard of male witches either

0:21 technomancy: alexyk: binding to should work for all active interfaces

0:21 replaca: technomancy: is the sonian crew going to brave the tsunami and come to functional alcoholics tomorrow?

0:22 alexyk: technomancy: does it try to bind to by default?

0:22 technomancy: replaca: that's the plan

0:22 alexyk: seems to here

0:22 alexyk: hmm

0:22 replaca: technomancy: cool. looking forward to it.

0:23 it'll be fantastic not to be the only clojure guy there

0:23 technomancy: replaca: we should outnumber the scala guys this time. =)

0:23 replaca: how many attend total normally?

0:23 replaca: technomancy: especially since we seem to be converting al3x

0:23 30-40

0:23 technomancy: wow!

0:23 seafunc is 5-6

0:23 alexyk: say I'm carrying around a tortured Java object. To mimic FP, I have defns like, (defn doGraph [graph] ... graph). Will it copy the graph, or, it being a Java object, pass references around?

0:23 replaca: we take our tech seriously by the bay :-)

0:24 does seafunc involve beer?

0:24 alexyk: replaca: it used to

0:24 technomancy: it varies. I'm sure that affects things.

0:24 replaca: that seems to be what brings them out

0:24 technomancy: also it only happens 4 or 5 times a year, which is lame

0:25 alexyk: you've been?

0:25 alexyk: technomancy: yep

0:25 replaca: there used to be bayfp, too, which was more serious. But I don't think they've had one in a while

0:25 technomancy: alexyk: you in the area?

0:25 alexyk: a series of bearded and unbearded folks, the great FP ones, in University City or Capitol Hill... a couple years ago, alas.

0:26 wooby: anyone ever run across clojure jobs in the bay area?

0:26 technomancy: I'm thinking about having a Seattle Clojure meeting next month

0:26 got 5 already interested

0:26 alexyk: I visit when giving a talk at MSFT once in a while

0:27 or visiting my friends in the area

0:27 technomancy: amazing, for clojure

0:27 so what about accepting and returning a Java object in a defn, does it copy or hopefully not?

0:28 technomancy: it won't copy unless you explicitly do it

0:28 alexyk: good

0:28 replaca: technomancy: I think I may have had the honor of hosting the biggest pure clojure meetup ever

0:28 (to date that is)

0:29 when Rich came to SF and we had the bay area group meeting

0:30 technomancy: replaca: yeah, I made it for that one

0:30 very exciting

0:31 joegg: technomancy: what you mean "explicity do it", regarding the copy?

0:32 As in (.clone foo)? Or am I missing something?

0:32 technomancy: joegg: that's what I meant, yeah

0:32 there's no auto-immutablize

0:32 replaca: technomancy: I remember - a good crowd, but too much for the space

0:32 technomancy: standing room only

0:32 joegg: technomancy: Thanks, just wanted to make sure I hadn't missed something big.

0:34 alexyk: I'm running clojure under rlwrap and suddenly see rlwrap at 100% CPU all the time, and Java at 50-150% (8 cores). Is there a reason why rlwrap would hog CPU?

0:40 TheBusby: is there an easy way to rebind *in* to a file for testing in slime?

1:42 rikthevik_: i want to write a pipeline function . it takes functions a, b, c and an initial value then calculated (c (b (a initial)))

1:42 thoughts?

1:42 i did it lisp-style using pop and peek, but it's not working great when the list of functions is a seq

1:46 TheBusby: rikthevik I think there is already something similiar, like ->>

1:46 or -->

1:46 one of the arrows I believe

1:47 good luck googling for it though...

1:50 ,(doc ->>)

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

2:20 konr`: What's the best way to represent a file? Is it a good idea to stick with Java's IO classes, or it's fine to create some convention for my function, like a PATH starting with @ denotes a file?

2:25 technomancy: konr`: I generally represent it as a string until I need to call file-related functions/methods on it

2:26 konr`: c.c.java-utils/file is great for that; it will turn its argument into a file whether it's a string or already a file object

3:19 quizme: if you make something a ref, does that mean it's going to use another thread when possible?

3:21 technomancy: quizme: refs just have values; they don't represent computation

3:21 maybe you're thinking of agents?

3:21 quizme: conversely, if you don't use a ref, atom, etc., does that mean it's NOT going to use another thread?

3:21 um

3:21 i dunno

3:21 just general confusion i think

3:22 i guess i'm wondering: what is it about clojure that makes it inherently more multi-CPU friendly?

3:23 defn`: it's functional

3:23 no side effects

3:23 quizme: and: are there any language constructs that let you control the threads.... (ok agents is one)

3:23 functional => all CPUs will be used?

3:23 defn`: agents, refs, atoms

3:24 quizme: no. http://en.wikipedia.org/wiki/Functional_programming

3:24 quizme: what does function programming have to do with multi-CPU friendliness?

3:24 defn`: functional as in, functions are first class

3:24 quizme: functional*

3:25 defn`: quizme: watch http://www.vimeo.com/8426709

3:25 quizme: i'm just trying to make the connection between the language and being able to use all the CPUs

3:25 defn`: quizme: you're not going to do it by making wild guesses

3:26 it's false in the first place to say "use all the CPUs"

3:26 because A.. we're talking about cores, and B.. you can use all of the CPUs in any old language

3:27 cores

3:27 quizme: ok cores

3:29 defn`: quizme: what other languages have you worked with?

3:30 quizme: scheme, c, c++, java, ruby, php, as3, javascript

3:30 defn`: and you don't understand how functional programming solves many of the problems of concurrency?

3:31 quizme: no

3:31 defn`: have you written applications with locks in c?

3:31 quizme: no

3:31 no to both questions

3:32 defn`: what does functional programming mean to you?

3:33 quizme: function behavior only depends upon the arguments

3:33 defn`: which means...no side effects

3:34 quizme: yah

3:34 defn`: which makes concurrency easier

3:34 quizme: so what does that have to do with cores ?

3:34 defn`: in a non-functional style you have to be worried about what other objects any given function/method is touching

3:36 quizme: ok

3:37 defn`: quizme: do you see how that makes scaling cores easier?

3:38 quizme: if two cores are processing the same data at the same time, you know that the action of one function won't affect the behavior of another function?

3:40 defn`: let's call them threads

3:41 quizme: so

3:41 defn`: quizme: the software transactional memory is important here

3:41 quizme: if you want to increment x

3:42 like in Lau's vimeo link you gave me

3:42 defn`: mmhm

3:42 quizme: actually

3:42 it's better to use a lazy sequence instead of atoms and all that ?

3:42 defn`: they're for different things

3:42 quizme: cuz a lazy sequence is immutable

3:42 defn`: ,(doc atom)

3:42 clojurebot: "([x] [x & options]); Creates and returns an Atom with an initial value of x and zero or more options (in any order): :meta metadata-map :validator validate-fn If metadata-map is supplied, it will be come the metadata on the atom. validate-fn must be nil or a side-effect-free fn of one argument, which will be passed the intended new state on any state change. If the new state is unacceptable, the validate-fn should return

3:42 quizme: yes? no?

3:43 defn`: you need to read more before you will have a clear picture

3:43 atoms and lazy seqs aren't even close to related for the purposes of this discussion

3:47 quizme: let's say you didn't have any mutable data

3:48 how do you know if you program is going to use multiple cores or not?

3:48 just because your program is functional and processing immutable doesn't mean it's parallelizable.

3:49 immutable data i mean

5:32 lpetit: clojurebot: seen cgrand

5:32 clojurebot: cgrand was last seen quiting IRC, 274 minutes ago

5:35 esj: clojurebot you stalker

5:39 pao: clojurebot: (take 1 (filter zero? (concat (take 10 (repeat 1)) [0] (repeat 1)))

5:39 hmmm

5:39 why does this doesn't terminate?

5:43 clojurebot: (first (filter zero? (concat (take 10 (repeat 1) [0] (repeat 1))))

5:43 esj: i think because of the filter

5:43 pao: esj: missing parens

5:44 clojurebot: (first (filter zero? (concat (take 10 (repeat 1)) [0] (repeat 1))))

5:44 esj: it never gets a non-zero value

5:44 pao: esj: there a zero value

5:44 *there is

5:44 (first (filter zero? (concat (take 1000 (repeat 1)) [0] (repeat 1))))

5:44 esj: after an infinite number of 1s, no ?

5:44 pao: clojurebot: (first (filter zero? (concat (take 1000 (repeat 1)) [0] (repeat 1))))

5:45 esj: no, after 10 1s

5:45 esj: hmm....

5:45 pao: 1000 in this case

5:45 esj: to you know how to query clojure version?

5:45 it was a parenthesis problem, now on my machine it runs

5:46 esj: when the REPL starts it says

5:46 pao: esj: I was wondering about clojurebot's clojure version

5:46 esj: dunno :)

5:46 pao: esj: no prob :-)

5:47 clojurebot: (take 10 (repeat 1))

5:47 clojurebot: > (+ 1 1)

5:47 clojurebot: help

5:47 clojurebot: http://www.khanacademy.org/

5:48 unfo-: not the khan i was expecting

5:48 pao: > (+ 1 1)

5:48 esj: you expecting designs for a nuke ?

5:48 unfo-: nope

5:48 pao: (+ 1 1)

5:48 clojurebot: 2

5:49 pao: (take 10 (repeat 1))

5:49 esj: hahahah, missing parens !

5:49 pao: I guess it doesn't print seq...

5:49 (first (take 10 (repeat 1)))

5:49 unfo-: esj, http://www.khaaan.com/

5:49 esj: (take 1 (filter zero? (concat (take 10 (repeat 1)) [0] (repeat 1))))

5:49 ,(take 1 (filter zero? (concat (take 10 (repeat 1)) [0] (repeat 1))))

5:49 clojurebot: (0)

5:50 pao: esj: what's the comma for?

5:50 esj: to ask clojurebot to execute the command :)

5:50 pao: esj: ah ok :-)

5:50 esj: np

5:50 pao: ,(take 10 (repeat 1))

5:50 clojurebot: (1 1 1 1 1 1 1 1 1 1)

5:50 pao: nice :-)

5:51 esj: clojurebot is very friendly, for a stalker.

5:51 pao: esj: LOL

6:03 talios: Morning

6:04 AWizzArd: Hi tal

6:05 talios: mm been ages since I've fired up linkinus and lurked on IRC

6:07 Chousuke: ,*clojure-version*

6:07 clojurebot: {:interim true, :major 1, :minor 1, :incremental 0, :qualifier "master"}

6:07 Chousuke: hmmh.

6:25 esj: now I know, thanks.

6:47 vu3rdd: given a sequence, is there a way to extract the elements from the first to last-but-one and the last?

6:47 that is, first/rest but on a reversed list?

6:47 (doc reverse)

6:47 clojurebot: "([coll]); Returns a seq of the items in coll in reverse order. Not lazy."

6:48 cypher23: (doc butlast)

6:49 clojurebot: "([coll]); Return a seq of all but the last item in coll, in linear time"

6:49 cypher23: (doc last)

6:49 clojurebot: "([coll]); Return the last item in coll, in linear time"

6:49 cypher23: vu3rdd, ^

6:49 vu3rdd: cypher23: thakns

6:49 thanks

7:26 dabd: I don't see much use for the predicate empty? since (not (empty? is discouraged as it involves a double negation. So why not remove it and simply use (not (seq and (seq insted?

7:33 LauJensen: dabd, empty? for testing true/false, seq and not-empty for nil/coll

7:56 dabd: what is the alternative for the #^ reader macro?

9:20 kiuma: hello

9:20 is there a library to print html code ?

9:20 chouser: kiuma: hi!

9:20 (println "<html></html>") ;-)

9:20 LauJensen: kiuma: Compojure is a good bet

9:20 kiuma: :/

9:21 LauJensen: (html [:h1 "Hello Html"])

9:21 chouser: kiuma: I guess it depends on what you're starting with.

9:22 If you have designer-created html that you want to adjust, I'd recommend enlive

9:22 kiuma: chouser, I created CLAW that is in common lisp

9:23 a claw html renderer is similar to cl-html

9:24 it transforms something like (div> (span> "foo")) to <div><span>foo</span></div>

9:24 does already exist something similar in clojure ?

9:25 chouser: kiuma: ah. yeah, compojure has a lib for doing things roughly like that. something roughly like that has be written several times in clojure

9:25 cemerick: ouch

9:25 kiuma: give enlive a try http://wiki.github.com/cgrand/enlive/

9:25 kiuma: ok htx

9:25 chouser: usually the clojure ones use keywords and vectors, so something like [:div [:span "foo"]]

9:25 * cemerick is peeing into the wind

9:28 kiuma: chouser, so I only should implement a parser, right ?

9:29 cemerick: kiuma: are you aiming to create another templating library?

9:29 chouser: kiuma: an html parser? there are good ones available already.

9:30 kiuma: Id like something that is the most similar to html

9:30 dabd`: if the ^ read macro is deprecated in 1.1 what will substitute #^ ?

9:30 chouser: dabd`: eventually, yes.

9:30 cemerick: dabd`: I think with-meta will be required

9:31 chouser: oh, sorry, misunderstood. #^ has not been deprecated

9:31 cemerick: oh, I thought it was :-/

9:31 kiuma: it's worth using existing libs unless there's something compelling to build separately.

9:31 some compelling reason, I mean

9:32 cgrand: kiuma: enlive is so similar to html that it's html ;-)

9:32 chouser: there's nothing else that will work in place of #^, though I guess ^ will eventually

9:32 dabd`: so only ^ will be deprecated

9:32 cemerick: cgrand: I've been trying to soft-pedal it ;-)

9:32 seths: kiuma: if you need to generate Javascript easily consider http://github.com/arohner/scriptjure/

9:32 Hali_303: hi! In Emacs/SLIME, when I try it the repl or do a compilation it hangs. how to find out what is the trouble?

9:33 cgrand: cemerick: I noticed your efforts :-)

9:33 seths: Hali_303: can you switch to the *inferior-lisp* buffer?

9:33 Hali_303: seths, yes

9:33 seths: you should hopefully see something like

9:33 user=> user=> Connection opened on local port 49318

9:33 #<ServerSocket ServerSocket[addr=,port=0,localport=49318]>

9:33 kiuma: seths, javascript must be done in javascript

9:33 Hali_303: seths: yes, that is there

9:34 kiuma: and not in html pages

9:34 dabd`: sorry to repeat the question but what is the use of the empty? predicate if (not (empty? is discouraged because of the double negation? Why not remove empty? and simply use (not (seq and (seq instead?

9:34 Hali_303: seth: also, below that: user=> user=> WARNING: reader macro ^ is deprecated; use meta instead

9:34 WARNING: reader macro ^ is deprecated; use meta instead (

9:34 kiuma: this beacause it avoid compression in any other language

9:34 cemerick: dabd`: (not (empty?)) is discouraged?

9:35 seths: kiuma: sure, but Scriptjure is pretty slick: (js (alert "hello world")) => "alert(\"hello world\")"

9:35 chouser: dabd`: (not (seq x)) is less clear than (empty? x)

9:35 cemerick: cgrand: I'm *almost* to the point of knowing what I'm doing with enlive :-) It's quite pleasant.

9:35 seths: Hali_303: hmm, it sounds like swank is running then

9:35 dabd`: cemerick if you read the documentation it recommends avoiding (not (empty? and use the idiom (seq instead

9:36 Hali_303: seths, when I type (+ 1 2) I can see that parentheses-matching is also working, but if I press enter after that, it hangs

9:36 cgrand: cemerick: I'm happy to hear that!

9:36 dabd`: chouser: but (seq x) is also less clear than (not (empty? x)). At least for me...

9:36 cemerick: dabd`: I'd say either is fine -- many people (myself included) like a 'literate' style, where the semantics of empty? are helpful

9:36 kiuma: seths, compression -> http://www.wingstech.it/claw/dojotoolkit/dojo/dojo.js

9:36 dabd`: cemerick: yes. I appreciate that too

9:38 seths: Hali_303: hrm.

9:38 chouser: mutliple negatives are more difficult to think about than simple positives.

9:38 cemerick: cgrand: the only thing I need to figure out is how to structure things properly. "normal" templating languages allow you to segment code pretty naturally based on one's layout -- that not being available means one has to figure out how to compose various transformations for each page, etc.

9:38 seths: Hali_303: how was swank-clojure installed?

9:38 fogus: chouser: That is not not not not true

9:38 * ordnungswidrig prefers seq over (not (empty?))

9:39 ordnungswidrig: (def full (comp not empty?))

9:39 cemerick: chouser: empty? is a predicate, and doesn't imply a negation.

9:39 dabd`: chouser: but when you use (not (empty? x)) the multiple negative is hidden in the implementation of empty? right?. For the user there is only one negation.

9:39 chouser: cemerick: right. so say (empty? x) instead of (not (seq x))

9:40 cemerick: but also, say (seq x) instead of (not (empty? x))

9:40 Hali_303: seths: checked out into a directory as described here: http://riddell.us/tutorial/slime_swank/slime_swank.html

9:41 cemerick: chouser: the fact that empty? is implemented using a negation is an implementation detail, IMO, and shouldn't influence coding style *shrug*

9:41 ordnungswidrig: cemerick: hehe

9:41 chouser: sorry, let me amend my statement. *any* negation is harder to think about that simple positive statements

9:41 cemerick: consider an alternate universe where seq returns an ISeq instead of nil for empty, and provided an .isEmpty() method.

9:42 even more to the point, what about if/when empty? becomes a protocol, totally divorced from seqs?

9:42 somnium`: (when-let [s (seq arg)] ...) seems more elegant than (when-let [s (not (empty? arg))] ...)

9:42 fogus: chouser: I !disagree

9:43 cemerick: heh

9:43 seths: Hali_303: another option is to use leiningen

9:43 cemerick: fogus: go away with your algolisms! :-P

9:43 fogus: cemerick: (not :))

9:43 ordnungswidrig: offline...

9:44 Raynes: fogus. He disagrees.

9:44 seths: create a project, add [leiningen/lein-swank "1.0.0-SNAPSHOT"] to the :dev-dependencies

9:44 and then run swank-clojure-project

9:44 has been the smoothest process for me

9:44 Hali_303: seths: ok, I'll look into that, thanks

9:44 seths: g/l

9:50 cgrand: cemerick: I've been experimenting with layout as middlewares. In such a setting the :body of the response is a map whose vals are html fragments.

9:51 seths: does anyone know if clojure-mode has been updated for deftype?

9:51 when I'm defining a method inside a deftype, clojure-mode indents like I'm calling the function

9:52 since there is no defn or similar keyword

9:52 AWizzArd: at least jochu’s repositories were not updated for months

9:53 cemerick: cgrand: I'm afraid I can't visualize that right off the bat.

9:53 cgrand: I've been toying with identifying + looking up transformations based on element id's in the template/snippet.

9:53 Hali_303: seths: it seems that slime was also installed as an ubuntu package and that did not like the one installed manually. working now, thanks!

9:54 seths: Hali_303: glad to hear it's working, not that I did anything really :-)

10:07 * angerman hates his macbooks IO performance with postgres.

10:09 seths: ,(with-meta "foo" {:bar 'baz})

10:09 clojurebot: java.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.IObj

10:09 seths: :-(

10:09 I'm being idealistic I suppose

10:10 angerman: seths: there's nothing that keeps you from adding meta support to your own string type

10:12 cemerick: where do plans stand w.r.t. require? Typing [foobar :as foobar] all over the place is getting just a little old. :-)

10:14 fogus: ,(let [x (with-meta (lazy-seq (seq "foo")) {:bar 2})] [(class x) (meta x) (apply str x)]) ;; total hackery

10:14 clojurebot: [clojure.lang.LazySeq {:bar 2} "foo"]

10:15 seths: fogus: woah

10:15 why wrap (seq) in a lazy-seq?

10:16 fogus: something to attach metadata to. But mostly just to be playful

10:16 * angerman wonders if there's a transparent way to add meta data to an object in clojure while, when comunicating with anything outside of clojure just the bare object is retained.

10:18 seths: I noticed that deftype says it only works for interfaces, e.g. String is rejected, but Object works fine

10:18 wonder why the special case? maybe since Object is the top of the Java food chain?

10:19 fogus: seths: For a string-like deftype, I would consider CharSequence

10:19 seths: hmm

10:19 chouser: that'll at least work with regex

10:19 iirc

10:26 seths: chouser: I think deftyping CharSequence would work with regex, but it would be painful

10:27 have to expose all the methods that are invoked on CharSequence by the regex code

10:27 * chouser nods

10:30 seths: anyways, just to wrap up the thought experiment with meta on a string

10:30 this technically works but is really gross

10:30 ,(deftype MyStringType [a-str] CharSequence (toString [] a-str))

10:30 clojurebot: java.lang.Exception: Unable to resolve symbol: deftype in this context

10:30 seths: alas

10:31 (str (with-meta (MyStringType "abc") {:foo 'bar}))

10:31 Chousuke: seths: I guess Object methods are overrideable because you're forced to derive from it in any case and not being able to override things would just be limiting

10:36 dabd: a very basic question: I thought the following would not work (let [a (ArrayList.)] (.add a "1") a) because the ArrayList would be immutable. Only Clojure data structures are immutable? If you create a Java data structure it is mutable? thx

10:37 Chousuke: dabd: the reference "a" is immutable, not the data structure itself

10:37 dabd: Clojure can't make Java's mutable things suddenly immutable :)

10:38 dabd: but if a was a ref to a Clojure map the map itself would be immutable (and also the ref)?

10:39 Chousuke: yes.

10:39 dabd: thx

10:44 angerman: I've created a pretty stupid ascii-progress chart i though I'd share: http://ideone.com/LU8RUJCD

10:47 dabd: (second [1 2])

10:48 ,(second [1 2])

10:48 clojurebot: 2

10:51 seths: cemerick: what's the latest on the string interpolation code?

10:51 cemerick: seths: sitting right over here :-) I suppose I should open a ticket for adding it, but I haven't heard much in the way of demand.

10:52 seths: I'm getting a little tired of (str x y z)

10:52 wouldn't mind using it, not sure if there is any licensing on it yet?

10:53 tolstoy: seths: You mean something like Groovy's "some ${nice} interpolation?"

10:53 seths: tolstoy: exactly

10:53 http://muckandbrass.com/web/display/~cemerick/2009/12/04/String+Interpolation+in+Clojure

10:54 cemerick: seths: feel free to use it. Wouldn't have posted it otherwise.

10:54 seths: great, thanks

10:54 joegg: Is there a single function that will build an infinite sequence from a single item, or should I just "(cycle (list 4))"? Basically, I'm looking for "constantly" except for sequences.

10:55 angerman: joegg: repeatedly

10:56 Chousuke: repeatedly is for functions

10:56 repeat is for items

10:56 tolstoy: seths: I kinda with that was in contrib. ;)

10:57 joegg: I guess you can clean it up a bit with (cycle [4]) instead of calling list.

10:57 Chousuke: ,(take 5 (repeat 4))

10:57 clojurebot: (4 4 4 4 4)

10:58 * angerman though repeat depended on a int n

10:58 joegg: Chousuke: That looks perfect.

10:58 Chousuke: it's optional :)

10:58 angerman: has it always been optional?

10:58 Chousuke: I don't think so.

10:58 angerman: hmm. so maybe my memory is just too old :)

10:59 Chousuke: there were two functions at some point

10:59 but then someone realised that repeat is enough :P

10:59 joegg: Okay, so: (constantly 4) will build a function that always returns 4, (repeat 4) builds an infinite sequence of 4, and (repeatedly somefn) will build a lazysequence based on the results of calling some function. Let's not even get into iterate. :)

11:00 And if I said something wrong there, please do correct me.

11:00 Chousuke: you're correct.

11:01 seths: tolstoy: cemerick is the author

11:01 Chousuke: iterate is not that difficult either. it just keeps calling the function on its return value

11:01 seths: I agree with you, would be nice to have around

11:01 joegg: Amazing. The only thing that worries me about clojure so far is that I'm bet I'm doing a lot of stuff like (cycle [4]) because I haven't yet internalized (for instance, (repeat 4).

11:02 cemerick: I guess that makes four 'seconds' on the notion of adding it to contrib. I suppose I'll have to open that ticket now. :-)

11:02 Chousuke: ,(take 5 (iterate / 9))

11:02 clojurebot: (9 1/9 9 1/9 9)

11:02 Chousuke: :P

11:03 tolstoy: cemerick: Do you think there's room in it for adding formatter type things? Like ~0,2{num} for zero padding, or some such thing? Or would that be too much.

11:03 cemerick: I'm thinking that if you need more than simple interpolation, format works, but, I don't know, would be kinda cool for that once in a long while use case.

11:04 cemerick: tolstoy: yeah, there's lots of room for stuff like that. I haven't thought about it at all, though.

11:04 Chousuke: tolstoy: for that you probably want to take a look at cl-format in clojure.contrib

11:04 seths: cemerick: whatever you do, don't make it as painful as formatting std::cout is in c++

11:04 cemerick: I suppose I would like to reuse what java's Format provides.

11:04 tolstoy: cemerick: The danger is it becomes yet another embedded DSL. (like cl-format.... )

11:05 cemerick: yeah, I definitely would stay away from anything approaching CL's FORMAT.

11:05 java.text.Format is just fine. Beyond that, go write a function, please.

11:05 tolstoy: Yes, String.format works for me.

11:06 But, I'd find it useful for logging. (log/info (<< "some ~{value} and another ~{thing}"))

11:06 But then I'm a "printf" debugger type. ;)

11:06 seths: tolstoy: there's a FaceBook fan page for that

11:06 printf debugging

11:06 cemerick: I use << for logging all the time :-)

11:07 * cemerick ponders c.c.logging using << and eliminating five characters from all of his logging invocations ;-)

11:08 tolstoy: seths: debuggering? I'm not even going to try and picture that.

11:09 seths: lol

11:09 cemerick: oh, yeah, -?>> would be helpful

11:09 tolstoy: cemerick: maybe (log/info<< "the ~{a}'s have it")

11:09 seths: you could have special macros for logging

11:10 like this for really bad errors (>_< "inconceivable!")

11:10 tolstoy: the smilification of logging, eh?

11:10 (; "it worked!")

11:11 seths: tolstoy: I see what you did there

11:11 tolstoy: (-( "error!"))

11:17 wooby: seths: LOL

11:17 (8-o "oh no!")

11:20 chouser: ,'(T_T "Oh dear")

11:20 clojurebot: (T_T "Oh dear")

11:20 chouser: ,'(x_x "failed completely")

11:20 clojurebot: (x_x "failed completely")

11:20 somnium`: http://www.lrde.epita.fr/~didier/software/smilisp.php << maybe there's something to this

11:21 the-kenny: Implementing smilisp is a bit hard because it isn't possible to define your own reader-macros in cloure code

11:21 tolstoy: And now we know why.

11:26 Can you use deftype/reify to, say, create a custom exception class in clojure? Dynamically?

11:27 Chousuke: hmm.

11:27 aren't they limited to interfaces?

11:27 tolstoy: That's what I was thinking (from what I read).

11:27 AWizzArd: Well, then there is still (proxy ...)

11:28 tolstoy: But that's not named, is it? You can't (catch CustomException ...), right?

11:28 stuartsierra: proxy won't create a named class that you can use in a try/catch

11:28 chouser: but you can't really rely on the name of the class ... right, whatever everyone is saying.

11:29 stuartsierra: If you want named classes, you must compile ahead-of-time.

11:30 tolstoy: I sometimes have a use case (web requests which in turn call other remote services), where I'd like to create an exception that has several attributes. I can throw it, and at the top I can just catch the exception, formulate an error response, and return.

11:30 chouser: defprotocol now creates named interfaces without AOT

11:30 tolstoy: look at clojure.contrib.condition

11:31 tolstoy: chouser: Ah, hm. I bet that's exactly what I need.

11:34 LauJensen: Is there something nice in contrib for downloading binary files?

11:34 tolstoy: Downloading from the web? http-agent works.

11:34 the-kenny: clojure-http-client should support this

11:35 LauJensen: k thx

11:36 angerman: Does anyone know how to figure out the iowait statistics on os x?

11:39 CalJunior: ,(defstruct foo :bar)

11:39 clojurebot: DENIED

11:39 CalJunior: (defstruct foo :bar)

11:39 (def map1 (struct foo nil)

11:40 (assoc map1 :bar 1)

11:40 returns {:bar 1}

11:40 however if I call map1

11:40 it returns {:bar nil}

11:41 the-kenny: CalJunior: Clojure is a functional language with immutable data structures

11:41 CalJunior: Yes I know it's immutability.

11:41 fliebel: The assoc did not actually change anything...

11:41 It only returned the changed struct

11:41 CalJunior: How do I get it to return {:bar 1}

11:41 ?

11:42 ohpauleez: use an atom or a ref

11:42 the-kenny: CalJunior: try a ref or atom

11:42 fliebel: Why would you need that?

11:42 ohpauleez: fliebel's answer is the one to go with

11:42 you really should ONLY do that if you have to

11:42 CalJunior: I only need to do it once at program start-up.

11:43 chouser: then why not (def map1 (struct foo 1)) ?

11:43 ohpauleez: maybe you just need to define one (def ...) that you need.

11:43 the-kenny: alter-var-root is propably what you want.. or (def) it with the right value

11:43 CalJunior: I need to map 'identities' to their place in a vector.

11:44 rather their index in vector.

11:45 the-kenny: ,(hash-map (zipmap [:foo :bar :baz] (iterate inc 0))

11:45 clojurebot: EOF while reading

11:45 the-kenny: ,(hash-map (zipmap [:foo :bar :baz] (iterate inc 0)))

11:45 clojurebot: java.lang.IllegalArgumentException: No value supplied for key: {:baz 2, :bar 1, :foo 0}

11:46 the-kenny: (zipmap [:foo :bar :baz] (iterate inc 0))

11:46 ,(zipmap [:foo :bar :baz] (iterate inc 0))

11:46 clojurebot: {:baz 2, :bar 1, :foo 0}

11:48 the-kenny: uhh switch the arguments of zipmap

11:49 CalJunior: thanks the-kenny, but I'll try the atom idea first.

11:49 the-kenny: CalJunior: An atom slow compared to a simple "def"

11:50 too much overhead

11:50 CalJunior: speed is not a issue in this case

11:50 the-kenny: It also isn't the "Clojure Way" ;)

11:50 CalJunior: I thought atoms were quite zippy though.

11:51 chouser: using an atom except to coordinate multiple threads is best avoided.

11:51 hiredman: the-kenny: what would you know about it?

11:51 alter-var-root is certainly not to be recommended

11:52 the-kenny: hiredman: I think that isn't a good problem for an atom. It looks like he doesn't really need mutable state here, as he only wants to do something while initializing the program

11:52 CalJunior: I timed the atom on a vector at 0.025 ms.

11:52 chouser: CalJunior: if you could more completely describe your input and desired output, we can probably give better advice.

11:53 the-kenny: hiredman: I'm absolutely not the haskell type (wtf, please, no state anywhere), but I think it should be avoided where it doesn't needs to be

11:54 CalJunior: chouser: I def a maps of values for a number of symbols.

11:54 most of these values a fixed and don't change ever.

11:55 chouser: it seems unlikely to me that any reference type needs to be updated.

11:55 CalJunior: however, one of them is set at the start-up of the program (daily).

11:55 chouser: CalJunior: "maps of values" still doesn't tell me much. Perhaps an example?

11:55 the-kenny: CalJunior: So you want to update a value later in the program?

11:55 CalJunior: yes.

11:55 the-kenny: Oh sorry

11:56 I misunderstand you.. an atom is the best way for this, of course.

11:56 Maybe a ref, if there needs to be some coordination etc. while setting from different threads

11:56 hiredman: CalJunior: is there a reason you can't just do (def map’ {:a 1 :b 2 :c (init-stuff-here)})

11:58 CalJunior: I think the atom is the obvious solution. So I'll let it rest.

11:59 chouser: love the book. as you can tell: I need it.

11:59 jcromartie: Would it make sense to use an agent with a nil value to handle saving data to disk?

11:59 I

11:59 DeusExPikachu: what is a fixnum and what is its purpose?

12:00 jcromartie: Or should the agent represent the data being saved?

12:00 Chousuke: jcromartie: I think it's okay to have a "serializing agent"

12:00 chouser: jcromartie: nil is probably fine. I've sometimes put the filehandle in there, but you have to be careful to always return it from your action functions

12:00 Chousuke: so that you can just do (send someagent write-to-disk whatever)

12:01 chouser: CalJunior: glad you like it.

12:01 CalJunior: thanks from fogus as well. :-)

12:02 DeusExPikachu: I think that usually refers to an efficient way to store numbers that know their own type, that's not supported by the JVM yet.

12:02 CalJunior: fogus: love your book too :-)

12:03 hiredman: if have the agent hold the data to be saved you can use a watch to write

12:03 jcromartie: hiredman: that's a good idea

12:03 Chousuke: hiredman: hmm, what if the data changes while the watcher is writing it?

12:03 jcromartie: so I send things like conj or assoc or dissoc

12:03 but the writes have to be in order

12:04 hiredman: ,(doc add-watch)

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

12:04 chouser: "The watch fn will be called synchronously"

12:04 jcromartie: ok

12:04 great!

12:05 now... is this so "experimental" that I shouldn't use it for production code?

12:05 otherwise I can just use a serializing agent

12:05 and call it a day

12:05 send-off would do the trick

12:05 chouser: jcromartie: that usually has more to do with the chances of the api changing than the code breaking.

12:06 jcromartie: I see

12:07 DeusExPikachu: chouser, thanks, now the jvm talk makes sense

12:09 chouser: DeusExPikachu: sure. the details are interesting too, if you're into that kind of thing.

12:10 DeusExPikachu: chouser, I'm watching "Fast Bytecodes for Funny Languages" and Cliff is talking about why clojure is close speed to java, and what it needs to do to close the gap

12:10 chouser: ah, yep. fixnums would be great for clojure.

12:10 meanwhile, rhickey's doing what he can to work around the problem. :-)

12:16 * lypanov wonders if the clojure video is worth it if he's already seen the devoxx talk

12:19 DeusExPikachu: chouser, I dont' know if you've watched the talk, but do you know if Escape Analysis is typically performed at the JIT level, or the clojure compiler level?

12:20 chouser: The Clojure compiler doesn't do much optimization at all. Post-1.1 it's now doing some fine-grained locals clearing, but any escape analysis is being done by the JVM.

12:21 Hm, I guess Clojure's also now doing some clever things with method caching at call sites, and some explicit (macro-style) inlining.

12:22 hiredman: that would be for deftype and protocols?

12:23 chouser: hiredman: yes, where (:foo bar) can be as fast as a direct field lookup, like a type-hinted (.foo bar)

12:23 I think that's the only place the call-site caching is done, but I may have forgotten something.

12:24 hiredman: do protocol fn call sites do some caching?

12:24 chouser: hm, perhaps that too. I haven't tried to read the implementation for any of that yet.

12:27 seths: cemerick: hey, email me if you are unhappy with http://bitbucket.org/seths/pokerepl/src/39b5efb4e905/src/com/muckandbrass/interpolate.clj

12:33 tayssir: Hi! I'm trying to search for the reasoning why add-classpath's deprecated... any pointers? (To get add-classpath's dynamicity, am I supposed to unzip the .jar into my classpath or something?)

12:37 hiredman: add-classpath was only ever supposed to be used in a very limited set of circumstances, since the visibility (scope) of classes loaded that way cannot be guaranteed

12:38 tmountain: is there a way to write this with the arrow operator? (get (get x "foo") "bar")

12:38 or some better way to write it?

12:38 hiredman: it's deprecated generally because people were unable to keep themselves from using it only for experimental repl sessions

12:38 (-> x (get "foo") (get "bar"))

12:39 tmountain: thanks hiredman

12:39 hiredman: the real solution appears to be a custom classloader as the system classloader durring developement

12:40 but this has yet to be codified

12:40 (honestly it's a fairly simple bit of code, so it should be)

12:40 Chousuke: isn't there a get-in as well?

12:41 hiredman: (doc get-in)

12:41 clojurebot: "([m ks]); returns the value in a nested associative structure, where ks is a sequence of keys"

12:41 hiredman: Yes

12:41 tmountain: ahh, that's what I was looking for

12:41 I was browsing clojure categorized... I see it's under structs rather than maps on there

12:42 tayssir: hiredman: Ah, cool, thanks.

12:45 lypanov: gen-in is cute

12:46 Chousuke: update-in and assoc-in are also neat :)

12:46 Norrit: hi, I am looking for some kind of "flat" operation, is there something available?

12:46 Chousuke: Norrit: flatten? clojure.contrib.seq-utils

12:46 Norrit: ah .. thx :-)

12:47 Chousuke: contrib contains a lot of stuff

12:47 konr`: is it safe to assume that a randomly generated string does not occur in a file?

12:48 the-kenny: ,(doc gen-in)

12:48 clojurebot: It's greek to me.

12:48 the-kenny: Oh, get-in?

12:48 Chousuke: konr`: depends how good your PRNG is :P

12:49 also on the length of the string :)

12:49 hiredman: konr`: no

12:49 a file is random collection of strings

12:49 Chousuke: mmh

12:49 most often not random

12:50 but still, nothing would prevent anyone from looking up one of your randomly generated strings and putting it in a file.

12:50 lypanov: the-kenny: aye, sorry. fingers are tired :D

12:50 hiredman: Chousuke: unless you know the contents of the file, it is random

12:50 the-kenny: lypanov: I was just asking because I never heard of gen-in

12:51 lypanov: maybe i should invent it

12:51 Chousuke: konr`: What are you you trying to accomplish?

12:51 hiredman: but unless you have actually checked to see if a random string exists in a file, it is not safe to assume it isn't in the file

12:51 lypanov: man this parleys thing uses a ton of cpu.. wonder where the vids are

12:51 Chousuke: hiredman: the contents of the system files on my hard disk are definitely not random, though I don't know it :)

12:52 I guess the issue here is about probability

12:52 I mean, it's not safe to assume that a hash does not collide with anything in the future

12:53 by your logic.

12:53 konr`: Chousuke: I want to generate a Boundary string to a multipart POST request, and I'm a little confused. In Drakma's source code, the string is random, but here: http://www.ietf.org/rfc/rfc2388.txt it says that the string should not appear on the content

12:53 Chousuke: drakma, the CL equivalent

12:53 Chousuke: konr`: generate a UUID or something

12:53 konr`: those are designed not to collide with each other :P

12:54 or you could hash the content that you're separating

12:54 then use /hash/

12:54 or whatever

12:56 It's rather unlikely that any good hash function would generate output A from content that contains A :P

13:05 ohpauleez: konr`: you want to use HtmlUnit and interop + enlive

13:05 that's what I've been doing

13:09 konr`: ohpauleez: "GUI-Less browser for Java programs" - hmmm, I didn't knew about this one

13:09 I'm going to try it out, thanks guys!

13:10 ohpauleez: totally welcome, I've been working on ripping parts of htmlunit out, and wrapping it a more functional way

13:11 hiredman: htmlunit is pretty nice

13:11 ohpauleez: agreed

13:12 the-kenny: http://kvardek-du.kerno.org/2010/01/how-common-lisp-programmer-views-users.html Clojure is Picard as a Borg :/

13:14 wilig: technomancy: did you have a chance to look at clojure/repl? I tried the simple approach but didn't get far.

13:15 vu3rdd: I am trying to write an insertion sort routine.

13:15 as a first step, I created an insert routine, which takes an integer and a sorted sequence as parameters.

13:16 it works except when the number to be inserted in greater than all the elements in the list.

13:16 The code is here: can someone help find the problem?

13:16 http://paste.lisp.org/+2099

13:17 cemerick: Good for a laugh, if folks haven't seen it yet: http://kvardek-du.kerno.org/2010/01/how-common-lisp-programmer-views-users.html

13:17 hiredman: vu3rdd: first (seq key) is most likely not what you want

13:18 for the empty case

13:18 (seq [key]) or (list key)

13:19 infact

13:19 vu3rdd: ok

13:19 hiredman: that might be the actually problem, since it is the base case

13:19 so do that and try again

13:20 vu3rdd: hiredman: thanks. yes indeed.

13:20 I was struggling with it for a long time today! :-(

13:21 hiredman: seq is not like list or vector

13:21 seq returns a seq on a collection, it doesn't create a collection

13:22 vu3rdd: ok.

13:22 so, any collection can be converted to sequences and can be thought of as a logical representation of any collection? is that a fair statement?

13:25 tmountain: anyone know any existing libs for downloading binary data using something like InputStream and OutputStream?

13:26 Chousuke: vu3rdd: seqs are logical views to a collection, yes.

13:27 vu3rdd: Chousuke: thanks

13:28 Chousuke: vu3rdd: seqs are also persistent, ie. once you have realised (accessed) a part of a seq, that part is immutable. this means weird things can happen if you make a seq on a mutable array and then modify the array afterwards

13:30 vu3rdd: Chousuke: thanks. But aren't vectors, maps and lists also persistent? I guess by Arrays, you mean the Java Arrays?

13:30 Chousuke: yes

13:31 ,(let [a (into-array [1 2 3 4 5]) s (seq a)] (println (first s) ".") (aset a 0 42) (println (first s) ".") (println (aget a 0) "."))))

13:31 clojurebot: 1 . 42 . 42 .

13:31 Chousuke: hmm.

13:32 I guess not cached in that case :/

13:32 chouser: I think lazy seqs cache, not all seqs.

13:32 vu3rdd: ok

13:32 Chousuke: chouser: might be.

13:33 ,(let [a (into-array [1 2 3 4 5]) s (doall (seq a))] (println (first s) ".") (aset a 0 42) (println (first s) ".") (println (aget a 0) "."))))

13:33 clojurebot: 1 . 42 . 42 .

13:45 hiredman:

13:46 jkdufair: Anyone played with Alice? I see it's Java. Might be fun to bolt clojure on top of it somehow.

13:46 LauJensen: Guys - I had a thought earlier. Previously when there's been a challenge like prime-finding, Lucas-Lehmann, Hamming numbers etc, I've joyfully used lazy-seqs to get the data I want. Now with chunked-seqs do I still dare? I imagine that with Mersenne Primes for instance the computations run for 8+ hours once you get beyond the 10.th number or so, so wont a seq representation effecually be impossible because the CPU will burn out trying to get the

13:47 chouser: LauJensen: you may need to be careful, yes. But many seqs are still not chunked.

13:47 LauJensen: many?

13:47 chouser: many

13:47 hiredman: anything using range is chunked

13:48 LauJensen: hehe

13:48 chouser: anything you build manually using lazy-seq and cons is not chunked

13:48 LauJensen: Aah ok

13:48 Thats good news

13:48 chouser: anything using iterate is not chunked.

13:48 LauJensen: Preferably it would just be made explicit somehow if you want chunks or lazy seeing they're 2 different things

13:49 chouser: any of the seq library functions that consumes a non-chunked seq, produces a non-chunked seq.

13:49 Chousuke: it is kind of explicit right now.

13:49 there's just no function to convert from a chunked seq to a non-chunked one

13:49 chouser: we could use a seq1 fn. Not sure why we don't have one yet.

13:49 LauJensen: You dont me literally seq1 ?

13:50 Chousuke: seq1 is not a bad name. :)

13:50 chouser: yes, a seq1 that accepts a collection (or chunked seq) and returns a guaranteed non-chunked seq

13:50 rhickey: http://paste.lisp.org/display/90536

13:50 Chousuke: I wonder if you can guarantee that for nested chunked seqs though? :/

13:50 rhickey: just a rough draft

13:51 chouser: iterate, for example, could potentially be faster producing a chunked seq, but if there were code written relying on it being non-chunked, that could be considered a breaking change. :-/

13:52 if we had an idiomatic seq1, then seq-returning things in generally could be considered potentially chunked, and code that *needed* non-chunked would explicitly use seq1

13:53 hiredman: bleh

13:54 chouser: considering how little complaints we've heard about chunked seqs, I would imagine use of seq1 would be pretty rare.

13:54 Chousuke: I think it would serve as documentation too

13:54 chouser: yes

13:55 hiredman: bleh

13:55 Chousuke: hiredman: do you have a better solution?

13:55 chouser: hiredman: do you have an alternative you'd like to propose? :-)

13:55 heh

13:55 Chousuke: or should we call seq1 "bleh"?

13:56 hiredman: I like it when map, filter, etc were lazy

13:56 liked

13:56 chouser: you would prefer to not have chunked seqs at all?

13:56 technomancy: wilig: not yet unfortunately

13:57 hiredman: I have to run catch a bus, but I would prefere explicit chunking to explicit seq-1

13:57 Chousuke: the non-chunkedness will propagate though won't it?

13:57 technomancy: wilig: I ordered a nexus one and have been distracted by the android emulator. =)

13:59 Chousuke: so if you have (map ... (filter ... (map expensive-op (generate-chunked-seq)))) then you should be able to make the whole thing non-chunked by just wrapping the map operation in seq1

13:59 chouser: the inner map, yes

14:00 well

14:00 no

14:00 (seq1 (generate-chunked-seq))

14:00 ,(first (map prn (range 10)))

14:00 clojurebot: 0 1 2 3 4 5 6 7 8 9

14:01 Chousuke: hiredman: I think having seq1 as the non-default op makes sense, because otherwise you'd need a lot of ceremony just to get the performance benefits.

14:02 hiredman: and in the vast majority of cases it makes no difference whether a seq is chunked or not

14:02 except that the chunked seq is faster, of course

14:04 but I guess if chunked seqs ever turn out to have been a *really* bad idea, the whole mechanism can just be removed :/

14:08 hiredman: well, the bus drove away while I was running along side it yelling and pounding on the side of the bus trying to get the driver's attention

14:08 chouser: :-(

14:08 wait -- is that a metaphore for chunked seqs?

14:08 hiredman: could be

14:09 Chousuke: heh

14:09 you just need to make a convincing enough case against chunked seqs

14:10 hiredman: I like lazy seqs

14:10 Chousuke: yes, and chunked seqs are still lazy.

14:10 only less lazy than before.

14:10 wilig: technomancy: excellent. enjoy. I'm tempted to finally succumb to the smart phone itch. It's not the price of the phone that gets me, it's the recurring costs.

14:10 hiredman: yes, and less is less

14:10 Chousuke: and if (when) seq1 is introduced, you have an explicit way of getting back to the old semantics

14:11 so what is there not to like?

14:11 that you might need to wrap some seqs in seq1 sometimes? :/

14:13 hiredman: chunked sequences basically go back on http://groups.google.com/group/clojure/browse_thread/thread/88d9fdb5bcad36a , so nil punning is gone for nothing

14:14 lisppaste8: fogus pasted "seq1 -- for my version of clojure" at http://paste.lisp.org/display/93650

14:15 Chousuke: hiredman: except seq1 rectifies that too

14:16 LauJensen: I prefer the speed that the chunks come with, so thats a good default, but it does change the way you can think about seqs a little bit

14:16 Chousuke: hiredman: and lazy sequences are still there. chunked sequences are just another, less lazy type of seq :P

14:16 rhickey: hiredman: no, they don't, as a chunked seq does nothing until something is asked for. When asked, it does more. And given some seq1-style source for seqs, it will be exactly as before

14:17 hiredman: but you haven't proposed an alternative. Explicit chunks, linke chunk-map, chunk-filter etc? 2 versions of everything?

14:18 once a seq is single, existing fns will process one-at-a-time

14:19 or a (chunked-seq x) to start the chunked chain?

14:19 technomancy: wilig: yeah, with Google voice being able to fall back to wifi for calls means 95% of my voice usage will be free

14:20 rhickey: just saying bleh doesn't move the dialogue forward, and people want the perf benefits. As is now obvious, people aren't suffering much from the theoretical problem

14:21 slava: it just occurred to me that inserting usage of transients is something the compiler could do, at least in simple cases

14:22 Chousuke: slava: possibly, but that would be complicated

14:22 slava: also, what happened to 'persistent data structures are fast enough for everything' :-)

14:22 Chousuke: slava: even for simple cases :)

14:22 stuartsierra: slava: the core functions, like "into", already do.

14:22 Chousuke: slava: was that ever claimed?

14:23 technomancy: "everything" is a tricky term. =)

14:24 Chousuke: Clojure is developed kind of incrementally.

14:25 transients are just one new tool in the box :P

14:25 technomancy: slava: nobody wants to work on the compiler right now since it's going away with self-hosting around the corner. but it's certainly an interesting idea.

14:25 angerman: technomancy: is that look and feel issue going into lein soon?

14:25 technomancy: angerman: are you getting it on the latest version? or is it just a problem with the release?

14:26 angerman: technomancy: using the latest release, lein pulles on self-install (from yesterday)

14:26 technomancy: angerman: oh, I thought that had been fixed

14:26 angerman: unfortunately it only manifests on OS X, so all I can do is accept patches

14:27 slava: transients are an interesting optimization. its not safe if you have multi-shot continuations

14:27 angerman: yes, I had it hand compiled for me. but then lein from the checkout was screweing with the classpath too much, so i cleared all of lein I had and pulled the version from the net.

14:28 Chousuke: I somehow doubt that Clojure will ever gain features that break transients (might deprecate some usage patterns) but amusingly enough it should be easy to remove them, too.

14:29 just make persistent! and transient no-ops and maps the ! ops to regular assoc etc. :P

14:32 angerman: technomancy: lein swank still crashes. Let's see if i find the patch that fixed it for me the last time

14:32 patrkris: hey... i'm looking for a quote that says something along the lines of "object-oriented design patterns were made to solve the deficiencies of OOP"

14:32 for some reason, I think it might have been rhickey who said it

14:33 or maybe he was quoting someone else

14:40 angerman: technomancy: I'm sure it was this patch: http://github.com/swannodette/leiningen/commit/9d79d631a9faa870a9347992f50a4312170fdf97

14:41 wooby: angerman: is the OS X bug mentioned in the commit msg the OS X java runtime stuff not being on classpath?

14:42 angerman: wooby: that might be the case. It only happens with lein swank though

14:42 technomancy: angerman: right, that slows every execution down for everyone

14:42 everyone else shouldn't have to be affected by a workaround for an OS X bug

14:42 angerman: technomancy: hmm ok, didn't know it caused slow down

14:45 Raynes: http://www.reddit.com/r/programming/comments/artiq/clojure_11_12_and_beyond_what_is_clojure_in/c0j3c8e :>

14:46 wooby: maybe lein swank could just sniff if OS X and include JavaRuntime.jar in -extra-classpath if necessary

14:46 i'll take a stab at it

14:51 angerman: wooby: (defn osx? [] (= (System/getProperty "os.name") "Mac OS X"))

14:51 wooby: if that helps :D

14:51 wooby: angerman: there 'tis :)

14:52 Raynes: ,(System/getProperty "os.name")

14:52 clojurebot: java.security.AccessControlException: access denied (java.util.PropertyPermission os.name read)

14:52 Raynes: :<

14:52 jasapp_: I was about to try the samething

15:07 ts00000: so, is technomancy's clojure-http-client the canonical way to do REST-type stuff these days?

15:08 e.g. http post.

15:10 the-kenny: Okay.. how do I merge two (or more) lists: (f [1 3] [2 4]) -> [1 2 3 4]

15:10 somnium`: concat

15:10 chouser: those are vectors

15:10 you want to keep them in order?

15:10 sorted order, I mean?

15:11 the-kenny: chouser: Yes

15:11 chouser: and you promise the input seqs are already in order?

15:12 the-kenny: I get one from a [& foo

15:12 ] function argument

15:12 chouser: if they're not already sorted, I don't think you can do better than (sort (concat c1 c2))

15:13 wooby: interleave would work, at least in that case

15:14 the-kenny: I think I'll stick to (seq (zipmap ...)), the order of the interleaved pairs isn't very important, just that they're pairs

15:15 chouser: I don't see how that's at all similar, but if you've got something that works, then great.

15:17 the-kenny: chouser: (fun ['foo 'bar] [:foo :bar]) should return either [foo :foo bar :bar] or [bar :bar foo :foo

15:17 +]

15:23 ohpauleez: the-kenny: that's different from the orginal goal, in that case, zipping is what you want to do

15:27 chouser: ,(interleave ['foo 'bar] [:foo :bar]) ; ?

15:27 clojurebot: (foo :foo bar :bar)

15:28 chouser: zipmap returns a map collection, not a vector or sequence.

15:28 ohpauleez: right

15:29 and I suppose if you really wanted a vector, just toss a into [] in front of the interleave

15:29 chouser: yes, or 'vec' :-)

15:29 ohpauleez: that would work too :)

15:38 CalJunior: I have: (def foo { :bar ( atom { } ) } )

15:38 how do I swap the atom?

15:39 for example to 1

15:39 chouser: (update-in foo [:bar] swap! assoc :a 1)

15:39 hm.

15:39 no

15:40 CalJunior: returns {:a 1}

15:40 I would like it to return 1

15:40 chouser: (swap! (:bar foo) assoc :a 1)

15:44 CalJunior: chouser: thanks

15:45 I guess I have to change the atom from a map to a vector to just get 1

15:45 chouser: an atom can hold a single number instead of a collection if you'd like

15:46 CalJunior: that's what I would like

15:46 chouser: ,(let [a (atom nil)] (reset! a 1) a)

15:46 clojurebot: #<Atom@192caa9: 1>

15:48 chouser: I continue to doubt that an atom is the best solution for you

15:49 CalJunior: I know what you mean.

15:49 (atom nil) was the key for me here.

15:49 works

15:50 I'll try to find a different solution later.

15:53 wilig: technomancy: New version of swank-clojure pushed to github. This one proxies LineNumberingPushbackReader. It's a small step on the path toward clojure.main/repl

16:07 ts00000: there is no deliberate slowdown

16:08 wrong chan

16:13 doesn't swank-clojure-project autoload everything in ~/project/lib?

16:13 in terms of classpath?

16:23 stuartsierra: Hey Maven fans (& not). I'm working on a Maven-based build for contrib.

16:25 lpetit: cool

16:26 stuartsierra: It's SO much simpler than the Ant build.

16:27 chouser: why's that?

16:28 stuartsierra: No test script needed, far fewer exclusions needed when compiling, no need to manually define how to find/compile .clj sources, ...

16:30 Basically, all the complexity of the Ant script is moved to the Maven plugin.

16:30 chouser: ah

16:31 stuartsierra: And the plugin is published in the central repository, so we don't need to distribute it.

16:34 Check it out: http://github.com/richhickey/clojure-contrib/tree/maven

16:37 No need to specify where to find clojure.jar on the command line...

16:38 zakwilson: I just set up a new machine with a new install of swank-clojure and an old .emacs file. It's saying java.lang.NoClassDefFoundError: clojure/main

16:39 and swank-clojure-jar-path is set to a real working clojure.jar

16:39 lpetit: stuart, are you a new convert, or did you know/use maven for a long time ?

16:40 stuartsierra: lpetit: I've been advocating Maven for Clojure projects for a while now. I wrote several blog articles on the subject.

16:40 lpetit: ok, was just wondering :-)

16:41 stuartsierra: http://stuartsierra.com/tag/maven

16:41 lpetit: I'm currently starting a project with GWT. Was wondering whether I would use ant or maven for it, just today :-). But I would really have loved being able to work with clojure full stack with GWT :-(

16:42 chouser: I think Clojure is less compatible with GWT than it is with C++ libs

16:43 jcromartie: ouch

16:43 stuartsierra: GWT is a Java source compiler, not much to be done about that.

16:43 chouser: *and* GWT can't compile Clojure's java sources

16:43 or couldn't last I tried, anyway.

16:43 lpetit: guessed so :'(

16:44 chouser: the only hope would be after cinc to write a java-source backend specifically designed to stay compatible with GWT requirements.

16:46 lpetit: yes. Some guys also reused the java->js compilation mechanism to extend it to their own classes. Depends on the size of the stuff to do, as always (e.g. a guy created QWT, qooxdoo widget toolkit, based on the google's compiler, AFAIK)

16:51 ts00000: this is really bizarre

16:51 swank-clojure-project isn't adding my ~/project/lib to classpath

17:06 heow: Just fired up the latest NetBeans and Enclojure, getting an NPE when creating a new project. is this a known problem?

17:11 Anybody use the [theoricicly user-friendly] NetBeans?

17:13 lpetit: I've just read interesting things about zippers, and will tend to become a zipper fan very quickly. So ... before I over abuse the tool, what are the limitations of zippers I don't see right now ? Where should they be avoided, for instance ? If not theoretically, at least given the current implementation in clojure.zip ...

17:14 technomancy: ts00000: it should add all the jars in $PROJECT_ROOT/lib to the classpath

17:14 dabd: how the see the value of classpath from a project REPL in netbeans 6.8?

17:14 chouser: zippers are pretty amazing, but they're not amazingly fast, and the way I used them in zip-filter turned out to be unexpectedly limiting.

17:14 stuartsierra: Simplifying contrib build with Maven: http://groups.google.com/group/clojure-dev/browse_thread/thread/cd807a1e5d7ce77d

17:17 lpetit: I thing I'll use them with the parsetree of the code of paredit.clj, to go to the node corresponding to the caret, and then from it find the parent, the previous siblings, etc. A limited number of operations, mostly navigational

17:17 heow: dabd: Oh hey, yeah the REPL's sig changed in 1.1. Bet that's it, thanks!

17:19 lpetit: But I'm currently "reinventing the wheel" in the parser code. I browse the code from first to last char, creating events as I go: entering a () , entering spaces, quitting spaces, entering an atom, quitting an atom, etc. So I keep a stack of the parents, and when I quit node, I "close" the node with the info I've gathered on it so far, peek the parent from the stack, update it with the...

17:19 ..."closed" node by adding it as last child, and replace the parent on the stack.

17:20 dabd: heow: I'm still running clojure 1.0 with netbeans (because I cannot get 1.1 to work with the latest enclojure). I'm puzzled by this. It thought starting a proj REPL would take care of setting the classpath correctly

17:20 lpetit: So, basically, I guess I've reinvented a specialized version of a zipper with a limited subset of operations on it, and without the need to maintain an "after focus point context", just a "before focus point" context

17:21 But I'm pretty sure my solution is efficient since I can see no superfluous (no non-essential) task in it.

17:22 jasapp_: say I've got my.ns.foo, and my.ns.bar, which have similar functions, but are different internally

17:22 lpetit: But the question remains : will I also use zippers for the construction phase, or will I suffer a penalty I can't afford ?

17:22 jasapp_: and I want my other code to be able to switch back and forth between them, interface-like

17:22 what's the best way to do that?

17:22 ts00000: technomancy: if it's not, where should I start to debug?

17:22 lpetit: chouser: what do you thing about it ? (and please don't tell me it will be in chapter xX of joc :-) )

17:23 chouser: lpetit: hehe

17:23 ts00000: technomancy: if it's in ~/.swank-clojure it's fine, if it's in the lib directory it doesn't work

17:23 chouser: lpetit: I'm afraid I don't grasp your whole context sufficiently to say. You're talking about parsing a stream of bytes into some kind of tree?

17:23 ts00000: chouser: is there a way I can play with require without redeclaring my entire ns? I tried (require 'clojure.contrib.zip-filter) which works, but I can't seem to access any of the xml-> things

17:24 technomancy: ts00000: check the elisp value of swank-clojure-classpath with C-h v

17:24 ts00000: technomancy: I did that, it's not there

17:24 technomancy: but it's definitely in my lib directory

17:25 stuartsierra: ts00000: require does not 'refer' symbols into the current namespace

17:25 ts00000: stuartsierra: but shouldn't I be able to do (clojure.contrib.zip-filter/func ...) ?

17:25 technomancy: ts00000: I've never heard of that failing on a project that's laid out according to the directions in the swank-clojure-readme

17:25 stuartsierra: ts000000: yes, you should

17:25 In that case the problem is somewhere else.

17:26 ts00000: technomancy: http://pastie.org/787307

17:26 lpetit: chouser: I'm the 100tiest guy to rewrite a clojure source code parser manually. For my purpose I'm just interested in a parsetree of the clojure code, and for the moment not interested in anything else than structural nodes (parens, square brackets, round brackets, strings, regexps, comments) and just 3 kinds of atoms: literal chars, spaces and the rest

17:26 ts00000: technomancy: did I miss something?

17:27 lpetit: chouser: this should give you ideas of the size and depth of my tree. clojure/core.clj is used for tests, since I see it representing an upper limit :-)

17:27 technomancy: ts00000: when you do M-x swank-clojure-project, you input the directory containing lib/ ?

17:27 ts00000: technomancy: yessir

17:27 chouser: lpetit: I think zippers will only be useful to you if you produce a tree of some kind from the parsing, and then keep it in memory while using the zipper api to navigate it.

17:28 lpetit: chouser: so too heavy for massive edit operations ?

17:28 chouser: lpetit: if I understood your description correctly, you're currently not holding the whole thing in memory, just keeping a stack representing your nested context?

17:28 ts00000: technomancy: SLIME 20091016, emacs, osx

17:29 technomancy: ts00000: is that slime from elpa?

17:29 ts00000: technomancy: yes

17:29 chouser: lpetit: you'll have to determine that yourself, I'm just saying it has to be in memory, at least ... well ... hm.

17:30 lpetit: chouser: well, the core function is just interested in navigating the code beginning-to-end, keeping a stack of the parents of the current node, and call hof arguments that do whatever they want in the process (they are called for each character, and given the current stack, offset, line, column context)

17:30 chouser: lpetit: this is for paredit-like functionality?

17:30 lpetit: i'm currently implementing a version of the hof arg which will write the complete parsetree

17:31 for other simpler cases, i'll implement less heavy hof args to just peek what I want on the fly

17:31 chouser: did I forget to mention that i also reinvented SAX in the process ? :-)

17:31 chouser: hm...

17:31 ts00000: technomancy: also, I seem to have to declare the (require 'clojure.http.resourcefully :as resourcefully) inside a namespace - is that normal, I assume so

17:31 technomancy: ts00000: what do you get evaling this elisp? http://p.hagelb.org/classpath.html

17:31 lpetit: chouser: yes, it's my "paredit.clj" project

17:31 chouser: lpetit: you didn't use that word, but I guessed so.

17:31 lpetit: SAX, I mean.

17:32 technomancy: ts00000: that's fine for resourcefully, though it's better to keep it inside the ns form with (:require [clojure.http.resourcefully :as resourcefully])

17:32 chouser: lpetit: so do you know where the cursor is and what kind of operation the user's trying to do?

17:33 ts00000: technomancy: i'm saying I can't seem to declare it outside the ns, e.g. in a repl. also, evaling your lisp gave the right classpath results, but for some reason it's like your function doesn't get called when I do swank-clojure-project

17:33 if I just call it directly that doesn't show up in the classpath var

17:33 lpetit: chouser: sure. it's easy to go to the right node from the offset of the cursor by elimination, given that I currently store the offset and length of each node. I have no doubt concerning the navigational part : I'll user zippers. It's the creational part where I was pondering the overhead of using zippers.

17:34 technomancy: ts00000: you could (setq swank-clojure-classpath [the code I pasted]) for now and use M-x slime instead of swank-clojure-project

17:34 chouser: lpetit: oh, once you've built a whole tree, making a zipper of it is very fast

17:34 ts00000: technomancy: yeah, I can edit the classpath manually so i'm not too concerned, just surprised it didn't work is all

17:34 jcromartie: a little bit off-topic, but what color-theme are you using in Emacs?

17:34 technomancy: but I can't reproduce your problem, so not much else I can do

17:35 jcromartie: that would be zenburn

17:35 it's not a built-in theme

17:35 ts00000: technomancy: is there a way to trace what's being done when I swank-clojure-project?

17:35 technomancy: ts00000: you could add calls to message in the function

17:36 the output goes to the *Messages* buffer

17:36 given the correct project root, the classpath seems to be calculated correctly

17:36 lpetit: chouser: FYI, I'm writing paredit.clj in an IDE agnostic way, purely clojure of course (and as idiomatic as I'm capable of, given that I've just sacrificed modularity over premature optimization in the main loop), and not just a port of paredit, but will be tailored for clojure (will know literal sets so that when selecting them you also have the leading sharp in the selection, etc.)

17:36 jcromartie: I have tried light-on-dark themes and it doesn't work well with OS X's LCD font smoothing. Light-on-dark ends up making the text heavier.

17:38 ts00000: technomancy: using trace-function, the path seems to be set correctly, but even when I fully qualify the path, the classpath only shows what's in ~/.swank-clojure

17:38 chouser: lpetit: I wonder if it would be faster and more robust in the face of incomplete code files to start at the cursor and word backwards/forwards just as much as needed to complete the user's operation

17:38 * chouser did this once. For C files, in perl, running in vim. :-P

17:38 ts00000: technomancy: in fact, if ~/.swank-clojure is empty, nothing on the classpath at all.

17:38 weird.

17:38 technomancy: ts00000: oh, I realized it's done a little differently now. the swank-clojure-classpath elisp var is only modified inside a let binding

17:39 so once the repl session is launched, it goes back to its root binding

17:39 so try messaging it right before the call to (slime) at the end

17:40 joegg: Is there any plan to make the various clojure launcher scripts a part of clojure generally, or is it up to individuals and package maintainers to keep rewriting them? (I ask because I just found what I think is a bug in the macports clj script.)

17:40 technomancy: joegg: sooner the better, but I don't know of any concrete efforts to do so unfortunately =\

17:41 ts00000: technomancy: what, just (message "%s" swank-clojure-classpath) or something?

17:41 lpetit: chouser: I've considered this possibility, and rejected it, for two reasons : I wanted to please myself by writing a parser manually, which I had never made before, and I hope that Christophe will quickly release a workable version of parsley, which, with its incremental parsing feature, will be unbeatable

17:42 technomancy: sure

17:42 chouser: lpetit: ok. so building a tree that can be used by a zipper should cost essentially no more than building a tree.

17:42 lpetit: or are you asking about using the zipper api to build the tree itself?

17:43 lpetit: chouser: yes, asking about the added overhead of using the zipper api for building the tree (edit and al) too

17:46 chouser: lpetit: I think building using insert-left, insert-child, replace, etc. will only be a small constant factor slower than building a plain persistent tree

17:47 ts00000: technomancy: I have something interesting to report. inside your function, everything is declared normally

17:47 technomancy: it's almost as if the classpath gets reset after slime

17:47 chouser: lpetit: so, not an unreasonable thing to try, I think.

17:47 ts00000: technomancy: path is correctly specified, and your code is correctly expanded

17:47 lpetit: chouser: ok, so worth considering a zipper as my state, will avoid me some boiler plate code. Will try this , thanks!

17:48 chouser: lpetit: sure, good luck.

17:48 hm. (seq-zip (read foo))

17:49 technomancy: ts00000: yes, since the classpath is set inside a let form, the changes are localized to that function call

17:49 but since elisp doesn't have lexical scope but dynamic only, the call to slime sees the new value.

17:50 joegg: technomancy: What would a standardized clj script require? Pretty much just writing one and asking someone to pull from a branch? Or, if you know, what has prevented this from already being done? This seems like something I could roll up my sleeves and do.

17:50 Unless there's massive problems that I'm just too ignorant to see. :)

17:50 ts00000: technomancy: ok, I see what you're saying, so how do I fix it so the command is useful again :-)

17:51 technomancy: let me rephrase that

17:51 technomancy: joegg: I think rich just hasn't made it a priority because he assumes everyone's going to get set up with Emacs or Netbeans or whatever.

17:51 ts00000: technomancy: I know how to fix it on my side, but how can I fix it so that rather than setting this manually on a per-project basis, it's dynamically set within swank-clojure-project and passed correctly

17:52 technomancy: ts00000: well because of the way dynamic binding works, it *does* get passed correctly from swank-clojure-project's let binding into the call to slime

17:53 ts00000: oh, I see what you're saying

17:53 you're saying slime does see the right classpath

17:53 but it's cleared after i've entered slime

17:53 so that when I look at the variable it's wrong

17:53 technomancy: yes, when you inspect it, you're outside of the let

17:54 which is a different scope from what slime was seeing

17:54 ts00000: ah, I got it

17:54 well, this is the problem though

17:54 the reason I investigated this in the first place was because I couldn't load clojure.http.client

17:54 technomancy: ts00000: did you add the jar after launching the session?

17:54 ts00000: no

17:54 :)

17:54 but let me see if it works now

17:55 wow, how fantastically convenient

17:55 it's there

17:55 :-)

17:56 technomancy: now, you were saying that I should be able to require resourcefully inside a repl, with the :as but without the namespace, although of course the namespacing is the preferred way to do it, right?

17:57 but the syntax for that doesn't seem to be (require 'clojure.http.resourcefully :as resourcefully) - what is the right syntax?

17:57 technomancy: try wrapping everything after "require" in []

17:58 ts00000: well, if I do it with the ', it says unable to resolve symbol resourcefully in this context, if I do it without the ', it can't find the class

17:59 technomancy: ts00000: should be: (ns eveloci.core (:require [clojure.http.resourcefully :as resourcefully]))

17:59 ns is a macro, so you don't need to quote anything

18:00 ts00000: if I want to do it without changing the namespace, can that be done?

18:00 like I just want to mess around with it in the repl.

18:00 technomancy: right, if you want to do it in the repl, you'll also need to quote the final resourcefully

18:00 ts00000: ah, ok

18:00 that's what I was missing

18:00 technomancy: otherwise it treats it as a variable and tries to look up the value

18:00 ts00000: thanks so much :)

18:00 technomancy: but you want the symbol itself

18:00 np

18:00 hiredman: uh

18:00 jcromartie: what is this all about? http://gist.github.com/282385

18:00 [B ?

18:00 hiredman: you were missing the whole vector

18:01 ,(class (make-array Byte/TYPE 1))

18:01 clojurebot: [B

18:01 lpetit: chouser: yes, but has no story to handle incorrect input, and no story to handle comments, literal metadata, etc.

18:01 hiredman: jcromartie: you need to call .getBytes on the string

18:01 jcromartie: hmm

18:02 public static byte[] decodeBase64(String base64String)

18:02 so what's the problem, the return value?

18:02 hiredman: jcromartie: no idea

18:02 jcromartie: .getBytes works, by the way... I'm just confused as to why the String method doesn't

18:02 hiredman: the string method wasn't being called

18:03 jcromartie: yeah

18:03 hiredman: possibly you have an old version of the library without it

18:03 what library is that?

18:03 jcromartie: Apache Commons Codec

18:03 ts00000: ah: and so when I try to access (clojure.contrib.zip-filter), I also have to use the symbol to get at the functions

18:03 ('clojure.contrib.zip-filter/xml-)

18:03 right?

18:04 hiredman: ,(import 'org.apache.commons.codec.binary.Base64

18:04 clojurebot: EOF while reading

18:05 hiredman: ,(import 'org.apache.commons.codec.binary.Base64)

18:05 clojurebot: java.lang.ClassNotFoundException: org.apache.commons.codec.binary.Base64

18:05 hiredman: bah

18:05 ,(doc show)

18:05 clojurebot: "clojure.contrib.repl-utils/show;[[x] [x selector]]; With one arg prints all static and instance members of x or (class x). Each member is listed with a number which can be given as 'selector' to return the member object -- the REPL will print more details for that member. The selector also may be a string or regex, in which case only members whose names match 'selector' as a case-insensitive regex will be printed. Finall

18:08 jcromartie: ooh

18:08 that's awesome

18:12 technomancy: jcromartie: that's nothing... in slime use C-c S-i to pull up the inspector

18:12 it's hyperlinked

18:12 alexyk: how do I access a static field of a class?

18:13 Java's

18:15 ts00000: is there any way to get at private documentation from the repl?

18:18 joegg: alexyk: (BigDecimal/ZERO)

18:19 Is that what you mean?

18:19 alexyk: joegg: yeah... for some reason I get an error, Unable to find static field, on a class which must have it

18:20 how can I use reflection to see what's inside a class in repl?

18:20 it's a public static final int BLAH = 8

18:29 joegg: ,(sequence (.getFields (class "")))

18:29 clojurebot: (#<Field public static final java.util.Comparator java.lang.String.CASE_INSENSITIVE_ORDER>)

18:29 joegg: alexky: That might help, I guess.

18:29 Oops, sorry for typoing your handle.

18:30 You can also just use the name of the class:

18:30 ,(sequence (.getFields BigInteger))

18:30 clojurebot: (#<Field public static final java.math.BigInteger java.math.BigInteger.ZERO> #<Field public static final java.math.BigInteger java.math.BigInteger.ONE> #<Field public static final java.math.BigInteger java.math.BigInteger.TEN>)

18:30 joegg: Is that helping?

18:31 Also, if someone knows a better way, please correct me, as I'm just a beginner.

18:32 alexyk: will try, thx!

18:35 dabd: I'm trying to pass java HashMap to a clojure function and I get the following error: java.lang.ClassCastException: java.util.HashMap cannot be cast to clojure.lang.IPersistentCollection

18:36 what type of Map should I pass to the Clojure function?

18:36 arohner: dabd: try a PersistentMap

18:36 dabd: arohner: thx

18:36 arohner: hrm, that might have been bad advice

18:37 can you paste what you're trying to do?

18:39 dabd: arohner I'm trying this invoke(PersistentHashMap.create(map));

18:39 and map is a Java HashMap

18:39 arohner: invoke? are you calling from java?

18:39 dabd: the invoked Clojure function excepts a Clojure Map

18:39 yes I am calling from Java

18:40 I am implementing a Web Service that uses Java API for RESTful WS and unfortunately since it relies on Java annotations I have to write some Java code, so I need to invoke Clojure from Java

18:41 arohner: I know (into {} (seq map)) will work. Looking for a better way now

18:42 jcromartie: dabd: invoke takes a function, PersistentHashMap.create(map) returns a new PersistentHashMap

18:42 invoke takes IFn

18:42 so your map is being cast to an IFn and called

18:43 the equivalent clojure would be ((map m))

18:43 hiredman: jcromartie: un

18:43 invoke is a method on a fn

18:43 jcromartie: dur

18:43 hiredman: it may or may not take a function

18:43 jcromartie: sorry

18:44 * jcromartie hangs head in shame

18:44 arohner: dabd: I think the java equivalent of (into {} (seq your-map)) is your best bet

18:45 dabd: arohner: I think that Java equivalent might be PersistentHashMap.create(map) where map is a Java HashMap

18:45 arohner: oh yeah, I missed that

18:45 yeah, that looks better

18:47 can you paste the whole of your invoke() line?

18:47 dabd: invoke seems to accept a number of Java Objects which are the arguments to pass to the Clojure function

18:47 hiredman: correct

18:47 dabd: arohner: Object result = groupbytf.invoke(PersistentHashMap.create(map));

18:47 where groupbytf is a clojure.lang.Var

18:47 hiredman: ~def c.l.PersistentHashMap

18:48 and you still get the exception?

18:49 dabd: no I'm past that. Now I have to debug the next error :-) thx

18:55 raz__: Does anyone know if the clojure compiler can be used to generate the AST or some other representation of clojure source code? I know there are classes like DefExpr or AssignmentExpr and so on but it looks like the compiler just keeps those to itself and does not expose the AST. I'd like to build a toy refactoring tool and a model of the source code would be very useful

18:59 * lypanov would like to build a clojure -> java converter and is also interested

19:00 lypanov: chouser: (and the other author) man joy of f'n rules.

19:01 ctdean: You could use a tool like jad to decompile the .class file that clojure generates

19:02 lypanov: ctdean: i've heard that thats not a great way of trying to use gwt to go from clojure to js

19:02 various complications mean it sounds like its easiest to take the ast and translate directly

19:03 ctdean: lypanov: sounds like you know more about this than me already :)

19:04 I used jad when I was working on one of the Scheme to jvm compilers. It was a useful debugging tool, but that's all I ever used it for

19:06 fiatmoney: (println "hello clojurebot")

19:06 raz__: try with a comma before it

19:06 ,(println "like this?")

19:07 clojurebot: like this?

19:07 fiatmoney: ,(println "hello clojurebot")

19:07 clojurebot: hello clojurebot

19:07 fiatmoney: ah, cool, thanks

19:07 raz__: guess it pays of to read #clojure logs instead of learning for exams

19:07 off*

19:07 lypanov: hehe

19:21 raz__: lypanov: there seems to be a parser in the 'La Clojure' Intellij plugin. Check the parser namespace. It uses the apache 2 license. The repository is here: git://git.jetbrains.org/idea/clojure-plugin.git

20:05 arohner: Raz_: why do you need a separate AST than (read)'ing source?

20:06 chouser: Raynes: you can indeed get at the analysis tree, which has richer semantic information than just what 'read' returns

20:07 sorry, that was for Raz_

20:07 oh. actually, raz__, but he's gone

20:07 Raynes: chouser: It's okay. I understand. You love my name so much, you can't help but say it every chance you get. <3

20:17 ts00000: chouser: do you have any idea what 'Unable to resolve symbol: text in this context' might mean while using zip-filter?

20:17 I have some xml with an attr of name, could it be getting hung up on that?

20:32 chouser: ts00000: it probably means you're using the symbol 'text' someplace where it isn't defined

20:32 zip-filter.xml defines a fn named text I believe. are you :use'ing it?

20:38 ts00000: chouser: i figured out where I went wrong by directly qualifying it; but now if I have some random xml def'd that has a foo attr with a value of bar, and I try to xml-> thexmlvar :foo, the repl tells me a string can't be cast to an iobj

21:08 i'm really close to figuring this out. I have a function that returns a map (it comes from http.client). i'm trying to parse it but I think xml/parse isn't accepting the map because an illegalargumentexception is thrown. how do I get it into something parseable?

21:09 hiredman:

21:09 have you read the docstring on xml/parse?

21:09 does it say anything that would lead you to believe it takes a map?

21:11 ts00000: obviously not, but when I try to feed it a string, it does something I don't expect.

21:11 like (xml/parse (str (:body-seq testfunc)))

21:11 hiredman: ,(doc clojure.xml/parse)

21:11 clojurebot: "([s] [s startparse]); Parses and loads the source s, which can be a File, InputStream or String naming a URI. Returns a tree of the xml/element struct-map, which has the keys :tag, :attrs, and :content. and accessor fns tag, attrs, and content. Other parsers can be supplied by passing startparse, a fn taking a source and a ContentHandler and returning a parser"

21:11 hiredman: "or String naming a URI"

21:12 ts00000: ok, so can I somehow smash my already-retrieved stuff into an inputstream?

21:12 hiredman: .getBytes and java.io.ByteArrayInputstream

21:14 ctdean: ,(doc with-in-str)

21:14 clojurebot: "([s & body]); Evaluates body in a context in which *in* is bound to a fresh StringReader initialized with the string s."

21:17 Raynes: ts00000: (ByteArrayInputStream. (.getBytes stuff "UTF-8"))

21:20 hiredman: #/. is like window 11, so escape+number key doesn't find it

21:20 erp, mischan

21:24 ts00000: i've got to be making this out to be far more complex than it should be :/

21:27 in my map, the body of the returned xml is a sequence

21:31 dabd: is anyone able to inspect/watch values when debugging Clojure code with netbeans?

21:41 alexyk: how do you translate this into clojure: collection.find( query ).skip( 1000 ).limit( 100 ).toArray()

21:41 is it what .. are for?

21:42 chouser: sure. or ->

21:42 hiredman: (-> collection filter drop take)

21:42 chouser: (-> collection (.find query) (.skip 1000) (.limit 100) .toArray)

21:43 alexyk: and what .. would look like?

21:43 chouser: (.. collection (find query) (skip 1000) (limit 100) toArray)

21:43 alexyk: hard to tell what's nicer

21:43 chouser: that is, it suddenly becomes less clear if find is a method or a fn, and samke with skip and limit

21:44 and you can no longer include regular clojure fns in the pipeline.

21:45 alexyk: oh, I need further trickery: if skip or limit parameters are nil, the whole skip or limit call must be avoided. How can I account for it?

21:45 chouser: you want to just return nil then instead of doing the rest of the chain?

21:46 alexyk: no -- find is always done; skip or limit should be simply skpped over if their arg is nil

21:46 cemerick: dabd: inspect, yes -- you can't set clojure watches though, AFAIK

21:46 alexyk: teh final toArray is also always done

21:47 chouser: if their arg is nil instead of 1000?

21:47 alexyk: yep

21:48 is it a use case for a macro?

21:50 chouser: (-> c (.find q) (#(if n (.skip % n) %)) ...)

21:50 ick

21:50 dabd: cemerick: say u have a breakpoint on a Clojure line. How do you inspect a value?

21:50 alexyk: yackety-yack

21:50 or yuckety-yuck

21:51 cemerick: dabd: open the 'variables' tab and dig around

21:52 alexyk: never wrote a macro; but perhaps one can be used for (#(if n (~method % n) %)) ?

21:52 dabd: cemerick: thx

21:53 cemerick: dabd: np -- FYI, make sure you have a tostring column in your variables table -- that should print out nicely-formatted representations of standard data structures, etc.

21:55 dabd: cemerick: thx for the tip!

21:55 alexyk: chouser: makes sense? what would the macro look like?

21:56 chouser: hm.. yes, a macro might work there.

22:02 alexyk: I'd appreciate a sample macro as an example

22:03 would be a starting point!

22:04 chouser: well, the recipe is: first write the output by hand

22:07 alexyk: ok

22:07 ts00000: any ideas where i'm going wrong? http://pastie.org/787642

22:08 alexyk: chouser: to that's essentially (method coll n) or nil

22:09 ts00000: testfunc returns something like {:body-seq ("<?xml version='1.0' encoding='UTF-8'?>" "<name>xxx</name>")}

22:09 but I can't seem to get at the text of <name>

22:10 chouser: alexyk: (let [a nil] (-> 5 ((fn [x] (if a (+ x a) x)))))

22:10 alexyk: chouser: something like this? (defmacro methornil [coll method n] `(#(if ~n (~method ~coll ~n) ~coll)))

22:10 I

22:10 '

22:10 ve made it up

22:11 so it doesn't work yet :)

22:12 chouser: I don't think you can use #() in a macro expansion

22:13 somnium`: maybe smthing like (defmacro ?#&! [arg pred f] `(if ~pred (~f ~arg) ~arg))

22:13 every time I use clojure.walk I seem to write something similar

22:14 chouser: we're skipping a step. The next step is an example usage.

22:14 somnium`: my bad :)

22:14 chouser: :-)

22:14 (let [a nil] (-.

22:15 (let [a nil] (-> 5 (foo + a))) perhaps?

22:17 so, (defmacro foo [fnname & args] ...) right?

22:17 alexyk: yep

22:18 which will then expand to the icky (#(if...)) thing

22:20 chouser: hm.. actually, looking at that example usage, I don't think it needs to be a macro at all

22:22 alexyk: I want this form: (-> [1 2 3] (methornil take 2))

22:22 if 2 is not nil, take is applied to [1 2 3], otherwise the original is returned

22:22 methornil is "method or nil"

22:22 a patented medication against macrophobia

22:23 chouser: (defn foo [x f a] (if a (f x a) x))

22:24 alexyk: so no need for macros at all

22:24 chouser: :-)

22:24 sorry

22:24 alexyk: pity

22:24 methornil expired

22:24 chouser: (let [a nil] (-> 5 (foo + a)) ;=> 5

22:24 (let [a 9] (-> 5 (foo + a))) ;=> 14

22:25 alexyk: indeed

22:25 I'll call it methornil anyways :)

22:25 chouser: sure

22:26 alexyk: I stylistically prefer ->> to ->, is there any logic here to pick ->?

22:26 I can reorder methornil's arg order

22:26 chouser: heh. yep.

22:26 oops. I'm not writing.

22:27 alexyk: ?

22:27 chouser: the book

22:27 alexyk: ah

22:28 somnium`: alexyk: how about <-??->

22:28 alexyk: what's that?

22:28 somnium`: (its shorter than methornil)

22:28 alexyk: but it's not medicinal-sounding

22:28 somnium`: I've tried to pick up mongo-specifics in the separate chat, so you see that?

22:32 ts00000: wow, how counterintuitive, finally got it to work

22:33 what a pain in the royal ass :/

22:37 chouser: now I have one that should be very easy to answer: why doesn't the root tag need to be declared when you're accessing an attribute with zip-filter.xml? I can't even get at the root tag

22:37 defn: Ask your Dr. of Computer Science if Methoril is right for you.

22:38 chouser: there's always one root, so you can just skip it

22:38 ts00000: what if there are attrs on the root I want to get at?

22:38 e.g. <s3-api version="2"> ....body.... </s3-api>

22:38 chouser: oooh! hmph!

22:38 ts00000: this is one of the things that has been confusing me all night and just had the eureka moment

22:39 by removing the root element all of a sudden all my blanks actually had data

22:39 :)

22:44 Error Message %ADJ-5-PARENT: Midchain parent maintenance for [chars] - [chars]

22:44 Explanation A midchain adjacency failed to stack onto an output chain because a loop was detected. Traffic through the adjacency will be dropped until the adjacency is restacked. This condition is typically transient and is resolved by the control plane that drives the stacking. For example, if an IP tunnel destination resolves through the tunnel transiently this message will appear. The situation would be resolved either by learning the tunnel destination t

22:44 sorry :/

22:44 chouser: ts00000: oh, you can still pull attrs from the root element

22:44 ts00000: ts00000: how?

22:44 chouser: when you put a tag like :foo, it descends a level an looks for a tag there.

22:46 ts00000: chouser: in my case, i'm trying (xml-> blah :s3-api (attr :version)) - wrong way?

22:46 s3-api is the root of the tree

22:47 chouser: just drop the :s3-api

22:47 you're already at the root of the tree

22:47 ts00000: ah!

22:48 I got it now

22:48 perfect

22:49 thanks so much for being patient

22:49 i think it does rescan and walk it after the timers are done

22:49 alexyk: ,(letfn [(methornil [x f a] (if a (f x a) x))] (methornil [1 2 3] take 2))

22:49 clojurebot: java.lang.ClassCastException: clojure.lang.PersistentVector cannot be cast to java.lang.Number

22:50 chouser: sure. I actually find zip-filter fragile to use as well. I'm not sure how to fix it though. :-/

22:50 alexyk: why error?

22:50 ts00000: i don't think it needs to be fixed

22:50 it's just the most rapid way to prototype what I want to do, when what I should be doing is going deeper with just parsing out the tree itself

22:51 if I were to offer only one suggestion as a complete newbie coming to clojure, i'd say that in the absence of more error messages, there needs to be a more obvious way to trace and figure out why things are going wrong. the repl is great but it is unforgiving.

22:51 chouser: yeah, zip-filter just give you nils, and you're left flailing around

22:51 ts00000: let me rephrase that; slime+repl is great but unforgiving

22:51 alexyk: ts00000: I saved a defn into a file, load-file it, boom -- printStackStrace prints the actual file:line, not no-source-file:0 :)

22:51 ts00000: yes, there is a lot of flailing around in clojure I have noticed, it lets you do things that are not otherwise correct

22:52 hiredman: tree-map + filter works pretty well

22:52 ts00000: alexyk: the no-source-file:0 is actually helpful to me when determining what's going on int he repl versus the file

22:52 alexyk: ts00000: unless you pasted 25 lines

22:52 chouser: alexyk: your args to 'take' are backwards

22:52 ts00000: alexyk: but look at it this way, as a newcomer, your choices of IDEs are limited, and none of them are particularly helpful, and a great many newcomers are left choosing emacs, which is even more of an issue

22:52 alexyk: good point

22:52 alexyk: chouser: doh

22:53 ts00000: newbies should stay away from IDEs

22:53 wasting time on Emacs unless you know it or some GUIs is silly... raw text editor and repl and forge ahead!

22:53 ts00000: yes, but developing without one, especially for someone new, is difficult :-)

22:53 alexyk: my take at least

22:53 hiredman: http://github.com/hiredman/clojurebot/blob/master/src/hiredman/clojurebot/clojars.clj <-- clojurebot scraping for the recently on clojars notices

22:55 alexyk: hiredman: how about capturing outcries "clojars search is broken" and forwarding it to the clojars-ers? :)

22:56 hiredman: *shrug*

22:57 alexyk: chouser: is there a "flip" adatper on things like take?

22:57 adapter

22:58 so I'd have only one methornil and call it with (flip take) or something

22:58 chouser: #(foo %2 %1))

22:59 alexyk: ah

23:00 chouser: ,(-> [a 5] (let a))

23:00 clojurebot: 5

23:00 * chouser giggles

23:01 arohner: chouser: that's a little crazy

23:03 alexyk: what's (let a) ?

23:03 arohner: alexyk: (let a) doesn't work, but the macro turns that into (let [a 5] a)

23:05 alexyk: don't show it to the scala people :)

23:06 arohner: yeah

23:06 ,(macroexpand '(-> [a 5] (let a))

23:06 clojurebot: EOF while reading

23:07 arohner: (macroexpand '(-> [a 5] (let a)))

23:07 ,(macroexpand '(-> [a 5] (let a)))

23:07 clojurebot: (let* [a 5] a)

23:07 chouser: ,((->> (+ a b) (fn [a b])) 4 5)

23:07 clojurebot: 9

23:08 arohner: ok now you're scaring me

23:08 ,(macroexpand '((->> (+ a b) (fn [a b])) 4 5))

23:08 clojurebot: ((->> (+ a b) (fn [a b])) 4 5)

23:08 chouser: ,(->> (inc a) (let [a 5]))

23:08 clojurebot: 6

23:09 chouser: actually, it would be better to show this to nobody at all.

23:09 ,(->> a (+ 5) (let [a 5]))

23:09 clojurebot: 10

23:10 joegg: ,(->> "Ooh, me too!" (println))

23:10 clojurebot: Ooh, me too!

23:10 joegg: YAY!

23:10 chouser: if there's only one thing, you don't even need parens

23:11 joegg: Ah, because of the "makes it a list" part...

23:11 Sweet.

23:12 arohner: I need a random arrow. Takes your form and stick the first argument in a random place in the list...

23:13 wraps it in try catches, and tries again, until you make a form that doesn't throw an exception

23:13 alexyk: arohner: or even into a random orifice of the programmer

23:14 "an arrow of doom"

23:14 ts00000: where is the ->> better explained/documented?

23:14 i've looked at the doc string and in programming clojure but that doesn't cover that very well

23:15 chouser: do not look at the examples I was just giving.

23:15 alexyk: chouser: too late

23:15 chouser: they're a horrible abuse

23:15 ts00000: <- eyes covered

23:15 chouser: I apologize for even mentioning them

23:15 ts00000: i'm just curious, want to learn more

23:15 chouser: and then tweeting

23:15 ,(->> (range 30) (filter even?) (drop 10))

23:16 clojurebot: (20 22 24 26 28)

23:16 chouser: that's a better example

23:16 each form is inserted as the final argument of the next form

23:16 so the above is the same as (->> (filter even? (range 30)) (drop 10))

23:16 alexyk: every time a crooked ->> is used, a frog dies in the Amazon

23:16 chouser: which is the same as (drop 10 (filter even? (range 30)))

23:17 ts00000: why would you want to use that as opposed to the (drop 10 ...) ?

23:17 chouser: this will be explored in detail in chapter 7

23:17 :-)

23:17 ts00000: of your new book?

23:18 joy of closure meap?

23:18 chouser: ts00000: it allows you to read it left-to-right, instead of inside-out. Can also help reduce nesting levels. Mostly a matter of taste.

23:18 ts00000: yep. http://joyofclojure.com/

23:18 ts00000: it's on the list for this weekend actually :)

23:19 chouser: except the TOC there will be revised next time the MEAP is updated

23:19 the version that's available now is undergoing major surgery by fogus's deft hand

23:20 alexyk: since clojure is lisp-2, function literals mean themselves, right? so I could call (methornil coll take 2). Now what if instead of take it's (methornil obj .method n) -- can I still invoke with literal method name .method?

23:20 arohner: clojure is not a lisp-2

23:20 alexyk: lisp-1 I meant

23:20 my understanding of the first part of my own utterance is infirm

23:20 that's the gist I gathered from the past here :)

23:21 arohner: lisp-1 means that variables and functions live in the same namespace

23:21 in lisp-2s, you can have a variable foo, and a function foo, and they don't step on each other

23:21 alexyk: right; does it affect the fact that you can supply a function as a parameter by just writing its name?

23:21 arohner: yes

23:22 alexyk: ok, that's solved. Now about .method?

23:22 chouser: .foo is not a function

23:22 unfortunately

23:22 alexyk: arrgh

23:22 chouser: it's a special form

23:22 alexyk: methornil's just become obsolete

23:22 chouser: but this is actually a good thing!

23:22 because now you have an excuse to write methornil as a macro

23:23 arohner: you're wanting to pass a java method around to clojure functions?

23:23 alexyk: yep

23:23 chouser: yay! let's do it

23:23 back to the macros

23:24 so I need to write a macro methornil, equivalent to the defn: (defn methornil [x f a] (if a (f x a) x)), which takes java methods as f

23:25 chouser: (defmacro methornil [x f a] `(if ~a (~f ~x ~a) ~x))

23:25 except that expands a and x twice each, which could potentially cause problems

23:26 alexyk: chouser: is there like a macro val which stores the single expansion for reuse?

23:26 arohner: alexyk: your friend 'let' will do that

23:26 chouser: you just have your macro expand to something like (let [x-val x] ...)

23:27 arohner: (defmacro methodornil [x f a] `(let [a# ~a x# ~x] (if a# (~f x# a#) x#))

23:27 alexyk: right

23:27 what's a# and x#?

23:28 ah, just single expansions

23:28 * chouser leaves alexyk in arohner's capable hands and goes to bed.

23:28 alexyk: chouser: so how would you summarize why exactly we need macro for both methods and functions? :)

23:28 before you go...

23:28 arohner: nobody's ever told me I'm capable at clojure before

23:29 alexyk: you need a macro before java methods are not first class functions

23:29 alexyk: arohner: using # is a sign of maturity, also thwarts perl and ruby and python people into stupefaction :)

23:29 arohner: (.foo obj) is a special form; you use the macro to produce those

23:30 * somnium` suspects the perl community is pretty comfortable with #

23:30 alexyk: right

23:30 somnium`: perl people turn off like androids upon seeing #

23:30 and skip to the next line

23:32 ok, finally a case for macros. somnium`, consider this: I switched to clojure 'cause congomongo is better at mongo than scala for data; now it has lead me to learn macros. What else is in store?

23:33 the next application of congomongo is general relativity probably

23:34 somnium`: alexyk: once you get comfortable with macros, you may find any non-lisp to feel unpleasantly lacking in expressiveness

23:35 that, or general relativity I guess

23:36 joegg: alexky: one of the main things that macros allow you to do is to create new first class syntax, which I think you're already picking up on.

23:36 Darn, again, typo'd your name.

23:36 alexyk: np)

23:36 joegg: Anyway, (if...) is a macro that just calls (cond...), more or less.

23:37 (Also, I'm a beginner, so if I end up saying something wrong, anyone can feel free to correct me please.)

23:37 somnium`: ,(macroexpand '(cond true :foo))

23:37 clojurebot: (if true :foo (clojure.core/cond))

23:37 alexyk: how can you check what's a macro?

23:37 joegg: Now, one thing that I've always wanted in javascript/java/etc is a while/else.

23:37 arohner: alexyk: the metadata of the var

23:37 ,(meta (var cond))

23:37 clojurebot: {:macro true, :ns #<Namespace clojure.core>, :name cond, :file "clojure/core.clj", :line 400, :arglists ([& clauses]), :doc "Takes a set of test/expr pairs. It evaluates each test one at a\n time. If a test returns logical true, cond evaluates and returns\n the value of the corresponding expr and doesn't evaluate any of the\n other tests or exprs. (cond) returns nil."}

23:37 tomoj: it tells you in (doc cond) too

23:38 joegg: while(foo) { } else { }, where the else is executed only if the while was never executed.

23:38 arohner: oh, right

23:38 joegg: In javascript, I couldn't have that, unless I wanted to write my own implementation.

23:38 tomoj: macro? would have to be a macro, eh?

23:38 joegg: Or, fake it, horribly, using functions.

23:38 In clojure, *I can create while/else using macros.*

23:39 And it has the same (total lack of) syntax as everything else, it's not some second class thing.

23:39 defn: hi all

23:40 ls

23:40 joegg: alexyk: Does that make sense? (also, just found out I can tab-complete nicks.)

23:42 alexyk: yeah

23:43 defn: we just decided macro is a better nick

23:50 joegg: Ooh, while-else, implemented (crappily):

23:50 (defmacro while-else [test body else] `(if ~test (while ~test ~body) ~else)))

23:51 Can anyone tell me if I've done something wrong on that?

23:51 It appears to work fine here, but I would love to know if there's something I could do differently or better.

Logging service provided by n01se.net