#clojure log - May 12 2010

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

0:02 sids: technomancy: yea, please -- it's a pain to add it to every single project!

0:02 technomancy: sids: well you'd still have to add swank-clojure as a dev-dep

0:02 I don't think I'm quite ready to make that an automatic dep on every lein project. =)

0:02 as much as I'm tempted

0:03 sids: technomancy: oh. did you consider supporting a "template" project.clj that lein new uses? maybe pick it up from some standard location..

0:03 technomancy: sids: it's on the roadmap

0:03 I need to add user-level plugins first

0:03 since a plugin like that wouldn't make sense if it had to be activated on a per-project level

0:03 MadWombat: can someone point me to an example of a servlet using recent version of ring?

0:04 like a hello world servlet

0:04 sids: technomancy: cool, template project.clj would allow emacs users to add swank-clojure (or even lein-swank) as a dev-dependency to all projects easily

0:07 lancepantz: MadWombat: i have one i can put on github for you if you'd like

0:07 technomancy: sids: if you're interested in the functionality it might be a fun little hack to experiment upon

0:07 it'll probably be a while before I get around to it

0:07 sids: technomancy: sure, I'll give it a shot!

0:08 technomancy: sids: I guess there are a couple of things needed for that

0:08 MadWombat: technomancy: that would be nice, thanks, or maybe just a quick question, when I replace (run-jetty with (defservice I get an error, that I pass a wrong number of apps to routes function

0:08 technomancy: 0) plugins activated on a per-user basis, probably listed from a ~/.lein.clj file

0:09 1) being able to wrap built-in commands from plugins

0:09 2) the new-template plugin itself

0:09 lancepantz: MadWombat: the defroutes syntax is different now

0:09 MadWombat: heh

0:09 I don't use defroutes, should i?

0:10 lancepantz: oh, i do, its in compojure not ring though

0:10 MadWombat: yeah

0:10 at this point all I have is (defn routes [req] (handle-dump req))

0:11 sids: technomancy: have you done any work on per-user plugins? can't figure it out from the git log

0:11 technomancy: sids: only in my head

0:13 sids: the first step would be to hack the bin script to check for jars in (possibly something like) ~/.leiningen/plugins to add to the classpath

0:13 then maybe load ~/.leiningen/init.clj, which would contain calls to require all the plugins you want activated

0:14 sids: technomancy: that should be straightforward, I'll also pour through the leiningen codebase to understand it better

0:14 technomancy: not sure how you'd get the plugin jars into ~/.leiningen/plugins in the first place though; probably want to symlink them from ~/.m2/repo

0:14 there's not a lot of code there; I think it's only around 700 lines

0:14 lancepantz: MadWombat: it looks like your munging the syntax of the app and middleware

0:15 sids: technomancy: wouldn't it be better if the the plugins you want to use are also just specified in a .clj file? then they can just be added as dev-dependencies

0:15 MadWombat: lancepantz: ?

0:15 lancepantz: check out http://github.com/mmcgrana/ring/blob/master/example/wrapping.clj

0:15 technomancy: sids: they can't just be in a .clj file since you need to add them to the classpath before the JVM loads

0:16 lancepantz: your middleware is passed app, not a request

0:16 sids: technomancy: ok, got it, these are plugins for lein itself, not the projects

0:17 technomancy: sids: right, activated for all actions the user takes across all project

0:17 *projects

0:17 sids: got it

0:17 MadWombat: lancepantz: lemme check, it compiled after I removed all wrappers and passed the unchanged routes method to the defservice

0:18 lancepantz: Ah! Got it, thanks

0:22 sids: technomancy: thank you, I'll try to hack something up later today

0:22 technomancy: sids: lemme know if you run into any problems

0:22 here or on the lein mailing list

0:23 sids: will do

0:25 lancepantz: MadWombat: http://github.com/lancepantz/lein-war-example

0:25 MadWombat: lancepantz: thanks

0:26 dnolen: how do you pad a vector in clojure again? (1 2) -> (1 2 3 nil nil nil), since count is only 2 and I want 5 elements.

0:27 bmason: technomancy: http://hugoduncan.org/post/2010/swank_clojure_gets_a_break_with_the_local_environment.xhtml

0:27 sexpbot: "Hugo Duncan : Swank Clojure gets a Break with the Local Environment"

0:27 bmason: what version of swank will this be included in?

0:27 technomancy: bmason: it's in 1.2.0-SNAPSHOT, which will become 1.2.0 very soon

0:27 (couple days maybe)

0:28 bmason: I'm running snapshots of clojure and clojure-contrib... any reason not to do swank as well?

0:30 technomancy: bmason: not really, it'll make your "lein deps" runs take longer is all.

0:31 dnolen: ,(take 5 (concat [1 2] (repeat nil))

0:31 clojurebot: EOF while reading

0:31 dnolen: ,(take 5 (concat [1 2] (repeat nil)))

0:31 clojurebot: (1 2 nil nil nil)

0:31 bmason: cool, I'm gonna try it out then

0:31 technomancy: bmason: it's worth it. =)

0:31 also I just pushed out xref support

0:31 bmason: yeah, I burned two days trying to troubleshoot a stack trace

0:32 technomancy: so you can say "I want to see all the functions that call partial" and boom; there you go

0:32 bmason: debug tools are definitely welcome

0:32 nice

0:32 technomancy: (that was all tcrayford)

0:32 bmason: well great job on swank... I use that every day

0:33 technomancy: eh; I don't really do much these days

0:33 I'm mostly just the PHB who applies patches and decides when the release is going to happen =)

0:39 danlarkin: xref sweeeeeetness

0:39 bmason: technomancy: how's that open door policy working out?

0:40 technomancy: bmason: better than you'd think

0:40 the rubinius project actually gives full commit rights for anyone who has a patch accepted

0:40 I'm not quite that gutsy

0:40 bmason: wow

0:41 technomancy: yeah, I could totally just go in and delete half the implementation if I wanted to

0:41 bmason: well Ruby breaks backwards compatibility with every release anyway

0:41 people are used to it ;)

0:41 technomancy: reverting is cheap, and people respect it when you trust them

0:41 heh; that too

0:41 danlarkin: try it out! I am excited.

0:42 danlarkin: no more M-x rgrep! well, less

0:42 bmason: how does the xref stuff work?

0:43 I understand that in terms of XML... not sure what it means for clojure

0:46 technomancy: it's a little fuzzy; it just opens the original .clj file for every var and sees if the source includes the symbol that names the function in question

0:46 probably gets a lot of false positives

0:46 and is really slow for large projects

0:47 it's basically a brute-force search, but it works

0:48 bmason: so it takes you to the place the symbol was def'd?

0:50 technomancy: it takes you to the caller

0:51 bmason: ah right

0:52 apologies if it's a dumb question, but are there docs on this somewhere?

0:52 like a way to get recent release notes?

0:52 technomancy: I'll try to put together some when the actual release happens. for now it's just the git log.

0:52 bmason: k

0:52 what

0:53 oops

0:53 what's the syntax for actually using the xpath stuff?

0:53 technomancy: xref, not xpath

0:53 bmason: do you use M-x something?

0:53 technomancy: it's C-c C-w c

0:53 bmason: ah

0:53 technomancy: xref for cross-reference

1:09 ataggart: anyone know where the browse-url function used by c.c.repl-utils is defined? Or how c.c.repl-utils works without declaring a ns?

1:12 MadWombat: is there a way to make lein copy dependency jars from a local directory?

1:12 without doing ugly maven install commands?

1:14 bmason: lein install

1:15 MadWombat: hmm

1:16 bmason: works with clojure projects at least

1:16 I don't know what you'd do with regular jars that aren't in a repo

1:16 might be stuck with maven

1:17 lancepantz: i thiink you can manually put them in ~/.m2

1:17 MadWombat: :(

1:18 bmason: yeah it looks like inside my .m2 directory are just jars and poms

1:23 MadWombat: thanks

1:24 technomancy: MadWombat: you need to do mvn install:install-file, but if you just declare the dependency before running mvn install, lein deps will print out the necessary invocation as part of the error message

1:24 MadWombat: technomancy: cool

1:24 is there a way to use ant targets from lein?

1:25 or for that matter define your own lein targets?

1:26 I am trying to setup an environment to play around with GAE and clojure

1:27 but all the ready setups are sort of dated, so I am coming up with my own

2:11 seems like each additional leiningen task requires its own leiningen.* namespace, is this correct?

2:11 lancepantz: yes

2:17 MadWombat: lancepantz: thanks

2:54 how do you add new task to the list leiningen displays as help

2:54 ?

3:05 LauJensen: Morning team

3:33 MadWombat: http://blog.mitechki.net/2010/05/12/short-tutorial-on-extending-leiningen/

3:33 sexpbot: "Short tutorial on extending Leiningen « Angry UNIXoid’s Humble Abode"

3:41 tomoj: MadWombat: did you write that?

3:41 MadWombat: yup

3:41 tomoj: thanks a lot, that subject has always been a mystery to me

3:42 one strange thing is that you used "namespace" instead of "ns" in the second code block -- intentional?

3:42 s/second/third/

3:42 sexpbot: one strange thing is that you used "namespace" instead of "ns" in the third code block -- intentional?

3:42 tomoj: s/third/fourth/

3:42 MadWombat: tomoj: no, I iwll fix in a sec

3:42 sexpbot: s/second/fourth/

3:42 tomoj: it's so simple now that someone has explained it :D

3:43 MadWombat: tomoj: I am still looking for a reliable way to transfer code into wordpress, so I cut-paste and edit manually for now

3:43 Raynes: I love how people always double take when they discover that by accident.

3:43 MadWombat: Raynes: :)

3:44 tomoj: yeah, it was a mystery to me too, up to about 2 hours ago, when I figured I had some time and I might as well read some leiningen source :)

5:31 _exterm: hi everybody

5:32 I want to add a method to a class generated by gen-class, but I want to do it at runtime, and I don't know the prefix there

5:32 Is there a way to get the prefix from a class?

5:38 spariev: _exterm: you could name your class as you want, like (gen-class :name my.ns.ClassName)

5:49 _exterm: I need the prefix, e.g. (gen-class :name my.ns.ClassName :prefix "foo")

5:49 so I can define class methods outside of the gen-class

5:58 LauJensen: _exterm: gen-class is for AOT compilation.

6:08 _exterm: Isn't it possible to add methods add runtime to classes that were generated AOT?

6:17 tomoj: don't the methods really just proxy to clojure fns?

6:18 and clojure fns can be added at runtime?

6:23 LauJensen: tomoj: Clojure makes stubs for the classes. You can definitely override after the fact with proxy but Im just sure that you can add w/o using reify or something similar

6:30 SandGorgon: are s-expressions the same as clojure "forms" ?

6:31 Chousuke: I wonder. can s-expressions contain vectors and maps?

6:32 SandGorgon: Chousuke, would'nt that be implementation detail - I can argue that vectors are arbitrarily growable lists . Am I wrong ?

6:32 Chousuke: well, yeah

6:32 but clojure has both lists and vectors appearing in forms

6:33 tomoj: regular old lists aren't arbitrarily growable?

6:34 Chousuke: I suppose the set of all clojure forms it not equal to the set of s-expressions, but a superset

6:37 SandGorgon: Chousuke, ahh

6:38 tomoj, yes I worded it wrong - for me vectors are as defined by C++ STL

6:44 I have a question about internals - (def a) creates a var ... when I refer to :somesymbol is it being created ? So, if I do (def pp [:a :b :c]) - is clojure creating references to the symbols ?

6:46 tomoj: ,(class :a)

6:46 clojurebot: clojure.lang.Keyword

6:46 tomoj: that Keyword's gotta come from somewhere

6:46 or from nowhere, rather

6:47 I mean, :aoeuaoeuaoeuaoeuaoeu certainly isn't sitting around in every clojure jvm

6:51 not too different from the way 361 isn't sitting around in memory in every jvm, I think

7:18 jfields: do you guys have any favorite blogs that have a fair amount of clojure related content?

7:19 liebke: jfields: http://planet.clojure.in/

7:19 sexpbot: "Planet Clojure"

7:21 jfields: liebke: thanks.

8:37 Hodapp: maybe if I put some Lisp books on my desk at work I'll stop crying when I have to use C++...

8:46 chouser: I have a couple situations where I think I want to write macros that macroexpand their args before returning.

8:46 Does the desire to do this mean I'm thinking about the problem incorrectly?

8:46 I've not needed to do this before, so I'm suspicious.

8:47 jfields: chouser: example?

8:47 chouser: it's to apply static typing in a DSL (maybe that's the problem there...)

8:48 so for example I have a macro lookup: (lookup :foo an-obj)

8:48 it would expand to something like: #^{:mytype "FooType"} (:foo an-obj)

8:49 that is it would know at compile time that :foo of an-obj returns something of FooType

8:50 then I want an equality test that throws at compile time if it knows the types of its args don't match

8:50 (typed= (lookup :foo an-obj) (lookup :foo other-obj))

8:51 the knowedge exists at compile-time to verify both lookups will return the same type of object, but I'm failing to think of how to extract/apply that information

8:52 ...except to have typed= macroexpand its args, examine their metadata, throw (or not), and finally emit a regular =

8:57 mabes: hey all, who else is at the clojure training now?

8:58 clojurebot: pcl → clojure is http://blog.thinkrelevance.com/2008/09/16/pcl-clojure

9:02 _fogus_: ,Q

9:02 clojurebot: <-nil-<

9:03 jfields: chouser is :foo really a FooType? or are you defining your own "types"?

9:03 chouser: these are probably my own types

9:04 jfields: can you put a type as part of the metadata, and have (typed=) check and compare the metadata?

9:06 chouser: yes, but that requires knowing the (generated) metadata of the args when the outer macro expands. normally the outer macro only has access to the input metadata

9:06 mabes: if you are using defrecrod I think you can use isa?

9:07 Licenser_: ,A

9:07 clojurebot: java.lang.Exception: Unable to resolve symbol: A in this context

9:07 chouser: I want to do this type check at *compile* time, not runtime.

9:07 Licenser_: ,Q

9:07 clojurebot: <-nil-<

9:07 Licenser_: why is Q nil with an arrow?

9:07 jfields: chouser: gotcha. I'm definitely not the guy with the answer, I'm sure. But, I thought I'd try to help. :)

9:07 chouser: :-) thanks.

10:11 ArkRost: hi! Tell me please the way I can create thread-local var.

10:13 Plouj: ArkRost: http://java.ociweb.com/mark/clojure/article.html#Vars

10:13 sexpbot: "Object Computing, Inc. - Java News Brief - March 2009"

10:14 stuartsierra: ArkRost: Any (binding ...) of a Var will be thread-local.

10:18 technomancy: Licenser_: it's a fancy/awesome way for printing clojure.lang.PersistentQueue/EMPTY

10:22 The-Kenny: technomancy: How was this way of printing called? <something>-fish, if I remember correctly

10:25 spariev: ,(conj clojure.lang.PersistentQueue/EMPTY "°}))>")

10:25 clojurebot: <-("�}))>")-<

10:28 SynrG: cute

10:28 cemerick: I guess I don't get the joke.

10:31 spariev: I wanted it to print smth like <-°}))>-< , but parens and quotes ruined my ascii art :)

10:32 cemerick: No, I see what you were doing there, I just don't know the backstory behind fish ~ queues. *shrug*

10:33 technomancy: cemerick: in stock clojure queues are visually indistinguishable from lists

10:33 nice to spice these up a little

10:34 cemerick: but why fish?

10:34 technomancy: just a visual indicator of which end stuff goes onto and which it comes off of

10:34 "queued elements, please step right this way"

10:34 cemerick: oh, head and tail

10:35 * cemerick will try to lighten up a little :-P

10:36 technomancy: I think it's just a print-method hack hiredman tossed into clojurebot, dunno if it'll get mainlined.

10:36 _fogus_: it's in JoC though. ;-)

10:36 technomancy: nice

11:11 Licenser_: technomancy: ah thank you!

11:15 LauJensen: stuartsierra: I think http-agent might be broken, since its shadowing core/bytes

11:23 stuartsierra: it's not broken, it just needs a refer-clojure

11:23 but 'bytes' should probably be renamed

11:25 Licenser_: stuartsierra: I picked up your temp converter post and played around a bit with wrapping the stuff needed for it, interested to have a look?

11:26 stuartsierra: busy right now, but feel free to post

11:27 Licenser_: okay :)

11:31 dsop: is there a downloadable version of the complete clojure api?

11:31 of the documentation

11:32 ah got it

11:34 LaPingvino: http://github.com/richhickey/clojure/tree/gh-pages

11:34 great :)

11:35 jfields: what's the feeling on watches? I have some a simple application that gets messages, updates a total and publishes out the new total. I've implemented it by listening for a message, updating the atom and then publishing the new total. I guess I could add a watch to the atom and publish from the watch, but having no experience with watches I wasn't sure if that was a good route.

11:49 Licenser_: $doc writer

11:49 sexpbot: Command not found. No entiendo lo que estás diciendo.

11:49 Licenser_: $doc clojure.contrib.duck-streams/writer

11:49 sexpbot: Command not found. No entiendo lo que estás diciendo.

11:49 Licenser_: (doc clojure.contrib.duck-streams/writer)

11:49 clojurebot: "([x]); Attempts to coerce its argument into an open java.io.PrintWriter wrapped around a java.io.BufferedWriter. Argument may be an instance of Writer, PrintWriter, BufferedWriter, OutputStream, File, URI, URL, Socket, or String. If argument is a String, it tries to resolve it first as a URI, then as a local file name. URIs with a 'file' protocol are converted to local file names. Should be used inside with-open to ensure

11:55 mabes: jfields: I'm not an expert by any means, but I've used watches before with good success

11:57 hiredman: ,(doc writer)

11:57 clojurebot: "clojure.contrib.duck-streams/writer;[[x]]; Attempts to coerce its argument into an open java.io.PrintWriter wrapped around a java.io.BufferedWriter. Argument may be an instance of Writer, PrintWriter, BufferedWriter, OutputStream, File, URI, URL, Socket, or String. If argument is a String, it tries to resolve it first as a URI, then as a local file name. URIs with a 'file' protocol are converted to local file names. Shoul

11:59 jfields: mabes: thanks.

12:32 bmason: if I want to do (keys {:a :foo :b :bar}) and (vals {:a :foo :b :bar}) do I need to use a sorted map to ensure the order is the same?

12:43 ataggart: or you could seq the map

12:43 that'll give you key/value tuples

12:46 or you could get the keys, then build the value seq from the keys seq

12:47 or it could very well be that values returns the same order as keys

12:47 which would make sense

12:48 wlangstroth: bmason: out of curiosity - what are you trying to do?

12:49 bmason: (defn run-insert "Given a :table and {values}, insert values into table."

12:49 [table values]

12:49 (with-connection db

12:49 (transaction

12:49 (insert-values table (keys (first values))

12:49 (map vals values))

12:49 (last-created-id))))

12:49 oops :)

12:49 will use pastie next time...

12:53 chouser: 'keys', 'vals', and 'seq' on the same map will all return items in the same order

12:55 replaca: I'm implementing support for PersistentQueue in pprint. Should I do it fish-style?

12:59 I'm thinking just <-(1 2 3)-<. Anyone care?

12:59 technomancy: replaca: yeah!

12:59 Licenser_: replaca: sounds good

13:00 will (<- 1 2 3) return a new queue?

13:00 replaca: (I don't want extra parens and brackets cause that will throw off anyone navigating the results

13:00 technomancy: unless you can come up with an ascii-art version of this: http://i196.photobucket.com/albums/aa159/apashin/arrowed.jpg

13:00 replaca: no, this is just about pprint

13:00 hiredman: ,Q

13:00 clojurebot: <-nil-<

13:01 replaca: hiredman: my version would be <-()-<

13:01 clojurebot: hiredman is slightly retarded

13:01 technomancy: if queue-fish gains a widespread community following there will be more pressure for reader support. =)

13:01 Licenser_: heh

13:01 replaca: since there's a seq under there (sort of)

13:01 DuneMan: *wants blocking persistent queue*

13:02 hiredman: DuneMan: not possible

13:02 replaca: DuneMan: what does that mean? The queue is immmutab;e

13:02 DuneMan: wants it anyway!

13:02 Licenser_: a persistent queue?

13:03 DuneMan: replaca: DETAILS

13:03 Licenser_: DuneMan: you have that it's called list?

13:03 ataggart: is there any chance of getting a literal queue?

13:03 chouser: we have a blocking queue. we have a persistent queue. I don't see how a queue could be both.

13:03 DuneMan: actually what I really want is java's blockingqueue, which I'm using. carry on.

13:04 replaca: DuneMan: but look at fill-queue

13:04 hiredman: why are you missing it?

13:04 ,java.util.concurrent.LinkedBlockingQueue

13:04 clojurebot: java.util.concurrent.LinkedBlockingQueue

13:04 hiredman: it's right there

13:05 DuneMan: Right, which is why I said "Which I am using"

13:05 I just got to my desk and typed some shit, ignore me.

13:05 hiredman: right

13:05 I somehow misread that

13:05 as "I'm missing"

13:05 DuneMan: replaca: Yeah, I can see that being handy for some things in the future, but unfortunately not this exact thing.

13:06 I was happy to find fill-queue

13:06 it's that level of abstraction which I think will make me increasingly productive in clojure.

13:06 wlangstroth: bmason: so you know the order, but not necessarily the columns you're entering, and that's why you use insert-values?

13:07 DuneMan: Though I do wish LinkedBlockingQueue could push a buffer of messages with only grabbing the lock once.

13:08 replaca: (pprint (reduce conj e (range 10)))

13:08 gives:

13:08 <-(0 1 2 3 4 5 6 7 8 9)-<

13:08 where e is PersistentQueue/EMPTY

13:09 TakeV: So, with assoc, if the key already exists that I'm passing to the function, then the map that gets returned just has the new value for the key I pass?

13:09 chouser: TakeV: yep

13:09 TakeV: Cool.

13:09 chouser: ,(assoc {:a 1} :a 2)

13:09 clojurebot: {:a 2}

13:13 wlangstroth: bmason: (I only ask because the whole process seems more work than simply concatenating a sql string yourself)

13:14 bmason: sorry, got distracted

13:14 let me read up

13:16 wlangstroth: is there a more convenient way to insert a map into a table?

13:16 wlangstroth: I only saw insert-values, which takes vectors

13:18 wlangstroth: bmason: insert-rows takes a vector of the values in order, but I'm assuming you know the order of your columns (insert-rows is just a convenience wrapper around insert-values)

13:21 bmason: wlangstroth: this is for a RESTful API... I have a PUT request coming in, and values will be in the :params map of the Request object... I need to take that map and insert the values into the DB

13:22 wlangstroth: bmason: oh, okay - I wasn't sure why you didn't know the order coming in

13:23 bmason: ah, alright

13:23 does my approach make sense then?

13:23 wlangstroth: bmason: and you're using ... mysql? and that's why you have to programmatically insert the id, rather than having the database do it?

13:23 bmason: yes

13:23 I'm considering using clj-record instead

13:23 will probably do that long term

13:24 but atm I'm just using clojure.contrib.sql

13:30 wlangstroth: bmason: yeah, I suppose that's how you would have to do it.

13:31 It was only jarring to me because I'm a database guy, so having the transaction enforced by middleware, etc. looked weird to me

13:35 ataggart: regarding REST, query params really shouldn't be used as a substitute for the body on a PUT

13:36 wlangstroth: bmason: I forgot about clj-record - it looks pretty good - haven't used it yet, but thanks for reminding me

13:37 patrkris: what is the reason that

13:37 oops

13:37 bmason: yeah, I've seen how productive the Ruby ORMs are... I'm excited to try out clj-record

13:38 patrkris: what is the (probably very logical reason) that commutes after alter/ref-set are allowed in transactions but not vice versa?

13:39 wlangstroth: ataggart: do people do that?

13:40 ataggart: based on what bmason said, I guess so.

13:40 "this is for a RESTful API... I have a PUT request coming in, and values will be in the :params map of the Request object"

13:40 bmason: oh

13:41 yeah, I'm not particularly clear on where my values will be coming from I suppose

13:41 ataggart: query params are for querying, for narrowing the scope of the response representation

13:41 bmason: I haven't implemented that part yet

13:41 yeah, I didn't mean to use query params

13:41 ataggart: what lib are you using for the rest stuff?

13:41 bmason: what does the body look like?

13:41 compojure-rest

13:42 ataggart: the body of a PUt is whatever representation you want and that the server can handle, e.g., a json object, xml, whatever

13:42 bmason: gotcha

13:42 so I'd then have to parse that... that makes sense

13:42 ataggart: yeah

13:43 I have rest framework I worte in java for my company. been meaning to comjureize it

13:43 erm

13:43 wlangstroth: oh, haha

13:43 ataggart: clojureize

13:43 bmason: compojurize?

13:43 :-D

13:43 ataggart: <-- not a good typist

13:43 bmason: Shakespear invented words, we can too

13:44 ataggart: I'll check out compojure-rest

13:44 bmason: *Shakespeare?

13:44 ataggart: see ifI like it

13:44 'Twas brillig and the slithy toves did gyre and gimble in the wabe.

13:44 bmason: indeed

13:46 DuneMan: neat, compjure-rest, that will be useful shortly

13:46 This is the most helpful irc channel ever.

13:47 bmason: YES

13:47 DuneMan: and I spent 8 years of my life in #C++/EfNet ;-)

13:47 wlangstroth: oi

13:48 bmason: I'm doing a spike of CRUD operations for a RESTful API... I will probably post it up on github when I'm done to get some feedback and so other people can use it as an example

13:48 ataggart: meh, not a fan of compjoure-rest

13:48 Borkdude: Just wondering, is there a clip function in Clojure that returns n if it is between a and b, a if less than a and b if greater than b?

13:48 ataggart: Ilike my lib better ;)

13:48 Drakeson: is swank-clojure broken since yesterday?

13:48 bmason: ataggart: link?

13:48 ataggart: bmason: none yet. proprietary

13:48 will be opening it up shortly

13:48 wlangstroth: ataggart: translating from Java to Clojure can be disconcerting - the result is so much shorter

13:49 bmason: ataggart: send me an email or something, I'd like to check it out when you do

13:49 DuneMan: hah, agreed. the clojure implementation I have of this thing is even shorter than the python

13:49 and does more.

13:49 bmason: :)

13:49 ataggart: the parts I've rewritten in clojure are an order of magnitude more concise

13:50 wlangstroth: I was porting parts of Jetty as a learning exercise, and it turned out that so much of what they were doing was already in the contrib library that I started feeling silly

13:50 bmason: lol

13:50 that's a great sign

13:51 that means we could have a really light weight webserver done in clojure

13:51 ataggart: I thought there was one

13:51 ring

13:51 iirc

13:51 bmason: ring isn't a webserver, is it?

13:51 wlangstroth: ring uses jetty

13:51 clojurebot: the answer is 42

13:51 ataggart: ah

13:51 bmason: yeah

13:51 and compojure is based on ring

13:52 wlangstroth: and Jetty is ridiculous

13:52 bmason: well... correction would be ring *can* use jetty

13:52 it's one option

13:52 wlangstroth: it works, it's awesome, whatever - the code is ridiculous

13:52 ataggart: I'd guess my rest lib would obviate ring. Right now it's built to run on a servlet system.

13:52 wlangstroth: bmason: quite right

13:53 ring is often used with jetty

13:54 ataggart: defprotocol/deftype/defrecord are making my life a lot easier

13:54 bmason: http://github.com/mmcgrana/ring

13:54 httpcore (Apache?) is another built in option

13:54 ataggart: I really just wish I didn't hate git as much as I do.

13:55 bmason: and it's probably not difficult to add new adapters

13:55 wlangstroth: ataggart: are you used to something else?

13:55 ataggart: svn, but via the subclipse plugin. haven't had to mess with the commandline for ages.

13:55 the lack of tool support / visualization gets to me

13:56 bmason: git clone *some repo* is pretty easy

13:56 ataggart: yeah

13:56 everythign after that is a pain

13:56 DuneMan: lack of visualization?

13:56 GitX, sir.

13:57 ataggart: gitx fails

13:57 wlangstroth: I live in white-on-black - more work done that way (not for everyone, of course)

13:57 ataggart: for example: http://subclipse.tigris.org/servlets/ProjectProcess?pageID=rr1TIx

13:57 sexpbot: "subclipse: Screenshots"

13:57 DuneMan: I also live in a terminal and don't use an IDE for anything

13:57 an IDE is almost necessary for java

13:57 ataggart: it's not the ide that OI care about

13:58 DuneMan: but I never code in java.

13:58 ataggart: it's the lack of a visual diff

13:58 DuneMan: You can use any visual diff tool you want with git

13:58 ataggart: committing a file without first seeing the changes on the server is madness imo

13:58 DuneMan: I use vimdiff, but there are better 3-way diff tools out there

13:58 bmason: how would I take 'vec' and 'keys' and combine them to a single function?

13:58 would 'partial' work for that?

13:58 wlangstroth: git status?

13:58 ataggart: I've yet to find a tool that provides a visual diff for git that compares to what's available for svn

13:58 technomancy: ,((comp vec keys) {:a :b :c :d})

13:58 clojurebot: [:a :c]

13:58 bmason: it doesn't seem quite right...

13:59 ah comp

13:59 thank you

13:59 DuneMan: git status; git&fetch && git merge origin/branch

13:59 git diff

13:59 ataggart: clearly you and I have different definitions of "visual diff"

13:59 DuneMan: ataggart: Just pipe the output of git diff to your favorite 3-way diff tool.

13:59 sure, but I don't think that has anything to do with git.

14:00 Git gives you a raw diff, view it in the tool of your choice.

14:00 ataggart: it has to do with the immaturity of the git ecosystem

14:00 wlangstroth: that's an interesting way to say "the pictures aren't pretty enough"

14:00 DuneMan: And the type of people who work on the ecosystem.

14:00 ataggart: it's not just about pictures

14:00 wlangstroth: ataggart: I'm teasing - I know what you mean

14:01 ataggart: the feature set in subclipse is a high bar, which nothing in the git ecosystem even comes close to

14:01 bmason: I agree ataggart

14:01 DuneMan: I mean, I suppose it might be handy if there was a gui tool that had a built in 3-way diff viewer?

14:01 Though I never leave my terminal so I wouldn't use it.

14:02 wlangstroth: right

14:02 ataggart: plus I'm constantly annoyed by the useless multi-step dance one needs to do to update the repo

14:02 DuneMan: git fetch && git merge?

14:02 wlangstroth: which dance?

14:03 DuneMan: I work on stuff that makes heavy use of branching, and in that case there is much less dance than with svn/cvs. So, depends on how you're using things?

14:03 ataggart: I have a file on my system. I change it. I right-click the file and hit "Commit...". One logical step.

14:03 DuneMan: or you can git pull

14:04 Ah, yes, there's your problem

14:04 touching your mouse.

14:04 *runs*

14:04 ataggart: for git it seems I have to do a half a dozen command line incantations

14:04 DuneMan: you just have to do git commit -m "Message" file.

14:04 ataggart: but that doesn't put it in github

14:04 DuneMan: and then push that branch if you're ready to distribute that branch.

14:05 ataggart: yup, multi-step dance

14:05 DuneMan: Though not a useless one.

14:05 ataggart: in my day we called git's commit "saving a file"

14:05 DuneMan: Very useful

14:05 It's just a matter of being used to a different workflow

14:05 technomancy: ataggart: if you want to combine two distinct steps into one that's easy enough to do with a shell alias

14:05 ataggart: yep, more sutff I need to write and not have avaiable on other machines

14:06 technomancy: what, you don't keep your dotfiles in version control?

14:06 DuneMan: I have all my stuff availablwe on all my machines

14:06 git checkout git@github:pgebheim/config.git

14:06 er, git clone

14:06 ataggart: ha!

14:06 see...

14:06 bad names

14:06 DuneMan: That I can agree with

14:06 the git command line interface is poorly designed

14:06 ataggart: precisely

14:07 DuneMan: Maybe someone will get around to fixing that at some point

14:07 It was clearly designed as linus added features he needed

14:07 so it has some logic to it, its just not transparent if you're new to it.

14:07 ataggart: from what I've read of the history, it's first goal was to make patching easier

14:07 wlangstroth: oh, I see your objection. Yeah, I've already written short scripts around that

14:08 DuneMan: I almost always want to commit locally

14:08 and NOT push

14:08 I commit locally and do diffs on working sets constantly

14:08 ataggart: yeah, save a file

14:08 I do that too

14:08 technomancy: magit makes it easy to forget how bad the git CLI experience is

14:08 DuneMan: No,that's not saving a file.

14:09 wlangstroth: ataggart: you mean you want a daemon to monitor changes on the working branch and commit on each save?

14:09 ataggart: no I mean "commit" in my worldview means "push this change out to the canonical repo"

14:09 maravillas: simply saving a file doesn't keep the local history, whereas committing to your local repo in git does

14:09 ataggart: what git calls "commit" I call "saving a file locally"

14:09 DuneMan: Except it's different

14:09 because you can have vrersioned local saves.

14:09 ataggart: maravillas: that depends entirely on what you're using to edit

14:09 eclipse has local history

14:10 maravillas: on a per file basis, right?

14:10 wlangstroth: oh, I see - this is a distributed vs. centralized discussion

14:10 DuneMan: yeah, it is

14:10 just different workflows

14:10 I'm getting used to git's over time, and finding it useful

14:10 :-)

14:10 ataggart: wlangstroth: a distinction without a difference as everyone seems to use github anyway

14:11 Drakeson: technomancy:

14:11 oops!

14:11 technomancy: ataggart: not at all, see http://github.com/technomancy/gitjour

14:11 Drakeson: technomancy: the latest swank-clojure push does not work here

14:12 wlangstroth: ataggart: I dunno - I prefer to commit a bunch, then go over it, and maybe push to github once a day.

14:12 technomancy: Drakeson: the xref merge?

14:12 Drakeson: it nags about not being able to turn PrintStream to StreamWriter or something like that. it points at the fall-back flatten definition in util.clj

14:13 ataggart: wlangstroth: so do I, I just call it saving files a bunch, then go over it, and maybe commit to the repo once a day.

14:13 DuneMan: wlangstroth: Agree. I found that a weird workflow until I started using it.

14:13 technomancy: Drakeson: which Clojure version?

14:13 Drakeson: latest

14:13 technomancy: I'll take a look at it tonight

14:13 DuneMan: I also got used to being able to pull working sets to other machines

14:14 ataggart: in any case, my main problem with git is its ecosystem is less useful ot me than svn's

14:14 DuneMan: and do complex multi-branch merging

14:14 Drakeson: technomancy: thanks

14:14 DuneMan: ataggart: Part of that is just a workflow problem, of course. But yes, there's less developed tools.

14:14 wlangstroth: ataggart: but if you have a bunch of different branches, it's not just saving.

14:15 ataggart: wlangstroth: I have multiple branches on my machine right now. It's not an issue.

14:15 I will of course grant that svn's branch/merge feature isn't as nice as git's

14:15 maravillas: and i suspect if you were to want to back out your latest change, which might span multiple files, doing so using your eclipse history wouldn't be a trivial task

14:16 ataggart: but I do that far less than I check-in files, and so not being able to have a nice diff view is more of a liability

14:16 DuneMan: again, git diff > your favorite diff tool

14:16 ataggart: false

14:16 DuneMan: I don't see what the issue is :-)

14:16 ataggart: clearly

14:16 use subclipse

14:16 you'll see

14:16 wlangstroth: I don't think it's an issue, really. I've adapted to both, but I don't use a gui

14:16 maravillas: i think that's a redirect operator, not a greater than :)

14:17 DuneMan: indeed, maravillas

14:17 ataggart: ah lol

14:17 very well then

14:17 DuneMan: hahaha

14:17 reading inline diffs can be really painful

14:17 especially 3-way diffs

14:17 I'm used to it, but wouldn't exactly recommend it

14:18 ataggart: for example: http://subclipse.tigris.org/images/sync-ss.png

14:18 DuneMan: that gui makes me want to cry

14:18 ataggart: bear in mind it's a tiny window to the actually files are too small to be useful

14:18 DuneMan: I loath eclipse.

14:18 ataggart: that gui contains useful info

14:18 wlangstroth: haha - we're definitely arguing gui vs terminal now

14:19 ataggart: the set of all files changed, the directionality of the changes, a diff of a particular file, and the revision history

14:19 DuneMan: yeah, we are. just differing workflows. maybe someone will make a good git gui to accomodate ataggart's

14:19 ataggart: not likely

14:19 wlangstroth: I think it's called gitk

14:19 ataggart: how anyone can commit files to a repo without having all that info in front of them beforehand... I just don't understand

14:19 DuneMan: gitk/gitx are sorta half useful still

14:20 ataggart: no one in my office does a blind commit. everything gets reviewed thru the "synchronize view" so we all can know exactly what's changing

14:20 wlangstroth: ataggart: well, it's all text, so I use a text reader

14:20 ataggart: do you ave a screenshot showing what that looks like for multiple files?

14:21 DuneMan: ataggart: Because you basically get used to checking things in order.

14:21 ataggart: "in order"?

14:21 DuneMan: We also have a custom deployment system

14:21 which keeps track of branches for us.

14:21 ataggart: I'm not talking about branches

14:21 wlangstroth: it looks like diffs - what do you mean?

14:21 ataggart: I'm talking about, I change 5 files, someone else concurrently chnged 5 files, some of those changes overlap

14:22 DuneMan: Oh. That's easy.

14:22 ataggart: what does that diff look lke for you?

14:22 DuneMan: if the push fails, you pull and see what happened.

14:22 ataggart: ...

14:22 DuneMan: it looks like git diff.

14:22 git wont push revisions on top of each other that haven't been merged.

14:22 unless you do some really whacky dancing

14:22 with git merge and cherry picking commits

14:22 ataggart: so you trust the merge logic of git to understand how your changes will interact with the changes someone else made?

14:23 DuneMan: no, you pull and do the merge.

14:23 ataggart: but do you ever look at the changes side by side before a merge?

14:23 DuneMan: constantly.

14:23 You have to.

14:23 ataggart: ok, I'm asking what does that look like

14:23 in the terminal

14:23 DuneMan: it looks like git difff

14:23 wlangstroth: haha

14:23 fliebel: Can Clojure(or any Java language) run on mobile devices?

14:23 DuneMan: I look at the changes inline.

14:24 wlangstroth: ataggart: it looks like a lot of white text on a black screen

14:24 I'm thinking you wouldn't like it

14:25 ataggart: perhaps not.

14:25 I like not being constrained to 1980s tech

14:25 Drakeson: is there a standard way (i.e., one that can be done programmatically) to find the documentation of a fully-qualified class (e.g. java.io.File)?

14:25 DuneMan: I use vimdiff for side-by-side diff

14:25 if my diff is complicated

14:25 technomancy: ataggart: and yet you're using lisp... =)

14:25 wlangstroth: haha - it's still all text, dude

14:25 DuneMan: and sometimes a 3-way diff tool

14:25 ataggart: not really just text

14:25 there's deeper meanign there

14:26 Drakeson: technomancy: removing that flatten def fixes it here.

14:26 fliebel: What are the requirements(Java) for running Clojure?

14:26 technomancy: Drakeson: so it's giving you problems even though it's nested inside a when-not?

14:27 Drakeson: yes.

14:27 stuartsierra: fliebel: Java 1.5

14:27 Borkdude: Am I right when saying that Clojure is closer to Haskell than Scala is to Haskell? I don't want to force a discussion

14:28 fliebel: stuartsierra: I see… so I guess I'll forget about mobile and very mobile devices :D ( http://lejos.sourceforge.net/ )

14:28 sexpbot: "LeJOS, Java for Lego Mindstorms"

14:28 DuneMan: Borkdude: Why do you say that?

14:28 I actually don't know much about scala...

14:28 Borkdude: DuneMan: because of this question: http://stackoverflow.com/questions/2820801/yet-another-haskell-vs-scala-question

14:28 sexpbot: "Yet another Haskell vs. Scala question - Stack Overflow"

14:28 wlangstroth: Borkdude: I'd say it just to see the fur fly

14:29 DuneMan: but like... linguistically... a lisp isn't really like haskell.

14:29 Borkdude: He mentions Clojure briefly, but if he feels that Scala feels clunky wrt e.g. partial application, then he definitly should go for Clojure imho

14:30 DuneMan: if you compare the characteristics? immutibility, laziness, pattern matching?

14:31 It was just my feeling, I don't know Haskell and Scala that well, so.

14:31 DuneMan: Type systems seem far more.... ingrained than any of those.

14:31 Dawgmatix: whats a good clojure web framework to look at ?

14:31 fliebel: Dawgmatix: good question, I'm also interested :)

14:32 Borkdude: Dawgmatix: isn't Compojure one?

14:32 fliebel: I think compojure, thats the only one I heard of

14:32 Dawgmatix: okay

14:32 fliebel: Or Spring maybe :)

14:32 Borkdude: DuneMan: I think he's not after a type system, but after a nice language in which he also can use Java stuff

14:33 ober2: compojure is pretty nice. we moved some sinatra stuff over easily

14:33 DuneMan: Then that's a totally different question than "What's more like Haskell"

14:33 Dawgmatix: i am looking to move from django, because I finally feel confident about my clojure skills

14:33 mabes: Dawgmatix: compojure uses a framework called Ring which you can also use independently..

14:33 ober2: very simular

14:33 DuneMan: I've never used Scala :-)

14:33 Dawgmatix: okay mabes

14:35 joshua-choi: I have some questions on how Leiningen works. What version of Clojure does it use, and where is it stored? When I "lein self-install", from what source does it download from?

14:35 I'm asking this because I'm encountering some problems with Leiningen that I suspect has to do with Clojure 1.2.

14:36 ataggart: by default lein seems to pull down 1.1.0

14:36 but if you add a dep to 1.2.0-Master in your project.clj then it will pull that version

14:36 DuneMan: luckily technomancy is here

14:36 ataggart: yeah, ignore me. I'm mostly guessing :)

14:36 DuneMan: but yes, uses 1.1 by default

14:36 joshua-choi: I see, thank you

14:37 I'm encountering two problems

14:37 technomancy: joshua-choi: leiningen's clojure version is independent of the clojure version your project uses (with the notable exception of the lein repl task in lein 1.1)

14:38 DuneMan: which reminds me I should fix my lein version so lein repl works right

14:38 hah

14:38 joshua-choi: technomancy: I see. I'm encountering two errors in Lein. One is, in a project using Clojure 1.2's snapshot and Autodoc 0.7.1, using "lein autodoc" throws a bunch of errors...

14:39 But the other is stranger: simply running "lein help" gives similar errors.

14:39 I've pasted the output: http://gist.github.com/398271

14:39 wlangstroth: Scala is kind of like almost-functional java. F# does a better job on the functional side, it seems

14:40 technomancy: joshua-choi: there are some unresolved issues with autodoc I think. it's tightly coupled to a single clojure version, so I think it might only work with lein 1.2.0-SNAPSHOT (from git) right now.

14:40 since it uses the lein version of clojure, not the project's version

14:40 wlangstroth: (Of course, Clojure isn't purely functional, either, but ...)

14:40 joshua-choi: technomancy: "lein help" should not be affected by autodoc, though

14:41 ...as far as I can tell.

14:41 technomancy: joshua-choi: lein help tries to load all lein plugins in order to show their docstrings

14:41 but it should be resilient to broken plugins, you're right

14:41 joshua-choi: Ah. That would explain it.

14:42 Dawgmatix: i just heard about leiningen from the above discussion - is it similar to what asdf is in lisp ?

14:42 nvm, the github page has a good description :)

14:47 joshua-choi: technomancy: What is the relationship between the Clojure versions of Leiningen and its plugins? Does Leiningen itself currently always use 1.1?

14:47 Also, is there a Leiningen 1.2.0? I cannot find it on its GitHub website.

14:54 DuneMan: The method described in *Hacking* doesn't seem to work right

14:54 after I do lein self-install with a stable checkout

14:54 (on the stable branch)

14:54 I try to do lein deps

14:55 and it says "Your Leiningen development checkout is missing its dependencies" etc

14:56 And.... it installed 1.1.0

14:57 tips technomancy?

15:00 technomancy: DuneMan: sounds like you're confusing lein with lein-stable?

15:03 Dawgmatix: does "lein swank" not work with plain slime ?

15:05 dataangel: anyone know where I could find an overview of how to implement a persistent binary tree? I only ask here since clojure is my first exposure to persistent stuff ;p

15:05 persistent binary search tree rather

15:12 Winstons55: should the following code work (running off of clojure-1.2.0-master-20100507.230258-69)? I'm getting a compile error complaining about not resolving % in this context on the post condition.

15:12 (defprotocol TestProto

15:12 (simple-func [arg]))

15:12 (deftype TestType [test-val]

15:12 TestProto

15:12 (simple-func [arg]

15:12 {:pre [(= 0 arg)]

15:12 :post [(= 1 %)]}

15:12 1))

15:12 whoa, my bad on the formatting/multi-lines

15:15 stuartsierra: Winstons55: datatype methods don't have all the features of fn

15:16 which appears to include pre/post conditions

15:16 Winstons55: ah ok, good to know

15:16 thanks!

15:27 raek: dataangel: this article has an example implementation of a persistent binary tree: http://www.infoq.com/articles/in-depth-look-clojure-collections

15:27 sexpbot: "InfoQ: An In-Depth Look at Clojure Collections"

15:29 raek: to bad the formatting messed up the code examples including "<"

15:31 chouser: http://www.developer.com/print.php/3874551 -- same article, but apparently less broken formatting

15:31 sexpbot: "Clojure: Immutability at the Language Level — Developer.com"

15:32 raek: chouser: thanks!

15:33 chouser: quite welcome

15:33 http://joyofclojure.com/buy -- same article, but longer and more expensive

15:33 sexpbot: "Manning: The Joy of Clojure"

15:33 chouser: :-)

15:33 raek: :)

15:37 hrm, how does this work? it is available as an ebook now, but the physical one comes this fall?

15:37 chouser: right

15:37 well, parts are available as PDF now

15:38 raek: ah, I see

15:38 chouser: all of it should be available this fall in printed form and in several ebook formats (pdf and epub at least, I think)

15:39 LauJensen: Does anybody know the name of a function which turns all of this %40 into @ and %2F into / and so forth ?

15:40 raek: something like java.net.URLEncoder?

15:40 Dawgmatix: i am one of the people who bought the book as an early release

15:40 its pretty fascinating to read the updated pdfs as they are written :)

15:41 LauJensen: raek: java.net.URLDecoder/decode - Thanks, just what I needed

15:45 Borkdude: I am reading it too

16:01 ninjudd: chouser: i heard that you may or may not be working on a pure clojure version of protocol buffers...

16:05 chouser: ninjudd: hm... no, "pure clojure" isn't quite right

16:07 ninjudd: chouser: oh, have you looked at my implementation? http://github.com/ninjudd/clojure-protobuf

16:08 basically just a clojure wrapper around the official google java implementation

16:08 DuneMan: seems reasonable

16:08 chouser: ninjudd: yes, I believe I glanced through your code a while ago

16:10 I hadn't seen your set/map extensions. Those look neat

16:10 though it suggests we may have different usage profiles in mind. Not surprising, I suppose.

16:10 ninjudd: chouser: i've thought about rewriting PersistentProtocolBufferMap using deftype, but i don't want to duplicate work you may or may not be doing

16:11 chouser: how so?

16:11 DuneMan: technomancy: lein-stable is just bin/lein of the stable branch, no?

16:12 because the "Hacking" section refers to lein-stable, but nothing else does

16:12 chouser: I'm using protobufs defined by others for contexts other than clojure, just providing clojure interop with them. So I have no need for such extensions.

16:13 ninjudd: i see. makes sense. though the extensions are still usable by someone outside of clojure

16:13 chouser: sure

16:13 ninjudd: they just appear as repeated fields

16:13 chouser: oh, I see.

16:13 ninjudd: though a protobuf implementation in another language could choose to read the metadata and make them sets or maps

16:14 chouser: well, you shouldn't worry about duplicating effort. I'm not at liberty to opensource this code at the moment.

16:14 ninjudd: ah, i see

16:15 chouser: I'm pushing for it and management is open to the idea, but has more pressing priorities...

16:16 ninjudd: chouser: did you implement it the same way? by wrapping the google implementation?

16:16 chouser: yes, the version that works today wraps generated Message objects

16:16 ninjudd: or did you write your own implementation from scratch?

16:16 i see

16:18 ok well, i'll let you know if i get around to rewriting it to use deftype

16:19 chouser: mine doesn't have any .java code

16:19 ninjudd: other than the google code

16:19 chouser: right. I mean I managed to avoid writing any .java code. :-)

16:20 ninjudd: do you use deftype? or gen-class/proxy

16:21 chouser: it generates code (at compile time if it can, or runtime if necessary) so that (:field msg) is a straight call the java accessor generated by protoc

16:21 DuneMan: technomancy: I mean, I symlinked leingingen/bin/lein to lein-stable, but apparently that's not the way to go

16:21 chouser: the generated message-wrappers implement IKeywordLookup to tie into clojure's call-site caching

16:21 ninjudd: nice, so yours is probably faster

16:22 chouser: I haven't done much benchmarking -- I mostly wanted to make sure the API was such that it could be made fast if needed

16:22 and it gave me an excuse to play with IKeywordLookup

16:22 ninjudd: well i use DynamicMessage rather than the generated message classes, so i assume there is some cost to that

16:22 i'm not familiar with IKeywordLookup

16:23 chouser: yeah, it's not really documented. hence the fun in playing with it ;-)

16:23 DuneMan: technomancy: And the lein script linked to from the website installs 1.1.0 in ~/.m2/repository/leiningen

16:24 ninjudd: chouser: looking at the clojure code now... so it is part of deftype?

16:24 chouser: I think it only makes sense for when you're trying to expose a statically-typed thing (like a defrecord or protobuf) to Clojure

16:24 ninjudd: yeah, it's how defrecord field lookups can be as fast as a direct java field lookup

16:25 DuneMan: technomancy: So... I don't understand what I'm supposed to be doing differently.

16:25 chouser: (:foo thing) as fast as (.foo #^Thing thing)

16:25 DuneMan: oh, I bet I have to build the jar

16:25 duh

16:25 chouser: note it's just as fast even though no type hint, which is rhickey just showing off.

16:26 ataggart: lol

16:26 ninjudd: i see.. hehe

16:26 ataggart: I'm hearing praise from a co-worker in at the clojure thing in NC

16:26 ninjudd: chouser: i may look into doing it this way (if you don't mind). the serialization/deserialization speed is very important for our application

16:27 chouser: ninjudd: I don't mind. I wish I could share my code. :-/

16:27 ninjudd: me too!

16:27 chouser: for what it's worth, after I got all that working I realized we'd sometimes need to deal with dynamic messages

16:28 ninjudd: hmm

16:28 chouser: that is, we have a DescriptorProtos$DescriptorProto, but no generated java code for this particular message.

16:28 ninjudd: well i'd be really interested in a speed comparison between mine and yours if you get the time

16:28 chouser: we likely have the DescriptorProto at compile-time for any piece of clojure code using it, but not at java compile time.

16:29 so I've started reworking my code to provide an API as close as I can to what we are currently using, but to allow for these dynamic messages.

16:29 ninjudd: hm, yeah I should do that.

16:29 yay microbenchmarks. heh.

16:31 ninjudd: well, i'm sure yours will be faster, but it's hard to know how much

16:31 depends on the size of the messages and number of fields etc though

16:31 chouser: I'm sure

16:31 and how many reads per write, stuff like that.

16:33 ninjudd: i have a benchmark for our use case, but i'm trying to judge whether the work would be worth the increase

16:33 would be a good learning experience though

16:34 chouser: if you want to send me something I could run and then tweak to use our lib instead, I could do that and send you both sets of numbers.

16:34 ninjudd: thanks

16:36 there is some proprietary code in the benchmark, but i may be able to come up with a reasonable benchmark that doesn't have it

16:37 chouser: ok

16:37 ninjudd: i'm benchmarking our application code that depends on jiraph which depends on protobufs

16:37 i should probably write a direct benchmark for jiraph anyway

16:43 * arohner can't wait for clojure-in-clojure-in-javascript

16:47 technomancy: DuneMan: lein-stable doesn't belong in a checkout at all. just wget the script directly.

16:48 DuneMan: it can tell if it's running from a checkout or not. if it is, it assumes it's a dev version

16:48 DuneMan: I had just not done a lein-stable jar in my checkout

16:49 so it obviusly wasn't findind the jar

16:49 because I was a tard.

16:50 technomancy: I guess that might work too, but it's not what I meant

16:50 DuneMan: I basically just misread what the hacking section was telling ,me.

16:50 Because I didn't run lein-stable deps (lein-stable jar, of course, does this)

16:50 in my leiningen checkout

16:50 I was running it in my project

17:12 ska2342: Hi. Maybe this is a stupid question to ask, but... has there been a discussion yet on nth vs. get, especially when it comes to lists?

17:23 chouser: get is always fast (that is O(log n) or faster). nth is sometimes not always (sometimes O(n))

17:26 ska2342: get falls back on nth, but only for types where it can keep its performance guarantee, as far as I can see. Granted. However, I have a bad feeling having two functions doing almost the same (and actually the same sometimes) just for the performance guarantee. In addition to that: get silently returns nil for lists where nth raises an exception for maps. (The topic is related to the contains?-discussion, but I'd like to focus on lists this ti

17:28 ataggart: get is used when you have a "key" (loosely defined)

17:28 ,(get 1 '(:foo :bar))

17:28 clojurebot: nil

17:28 ataggart: erm

17:28 ,(get '(:foo :bar) 1)

17:28 clojurebot: nil

17:28 DeusExPikachu: in the documentation for defprotocol, shouldn't the method definitions in the deftype example include a first argument for this? I'm getting errors in the repl copypasting this code http://richhickey.github.com/clojure/clojure.core-api.html#clojure.core/defprotocol

17:29 ska2342: ataggart: I know :-), but e.g. for strings it falls back to nth

17:29 ataggart: ska2342: that's probably because strings have "keys"

17:30 i.e. the index of the char in the array

17:30 DeusExPikachu: note that in http://clojure.org/protocols, the 'this' field is supplied with the name 'x'

17:30 for deftype

17:31 ataggart: don't worry about implementation. get is for ~O(1) access by keys. nth gets the nth element which may end up being ~O(1) or O(n)

17:31 use the function that logically applies

17:32 ska2342: ataggart: yes, I can see that. I think I understood the implementation. I question the fact that two fn exists for basically the same thing (acessing elements of a collection) seemingly just for the performance guarantee. And that for lists get quietly return nil every time

17:32 is the performance guarantee part of a function or a datastructure?

17:33 ataggart: both

17:34 nth and get are different

17:34 for example:

17:34 ,(nth {:a :b, :c :d} 1)

17:34 clojurebot: java.lang.UnsupportedOperationException: nth not supported on this type: PersistentArrayMap

17:35 ska2342: ,(get '(1 2 3) 0)

17:35 clojurebot: nil

17:35 ataggart: ,(nth (seq {:a :b, :c :d}) 1)

17:35 clojurebot: [:c :d]

17:35 AWizzArd: They are different, but is such a difference required?

17:36 As I see it, the point of ska2342 is: for lists nth and get could be the same

17:36 ataggart: yes because the performance characteristics for different datastructures are different

17:36 ska2342: ,(get '(1 2 3) nil)

17:36 clojurebot: nil

17:36 ataggart: get on lists would not be ~O(1)

17:36 AWizzArd: ataggart: O(n) for nth for lists

17:36 so, no nth for lists then?

17:36 ska2342: ,(get '(1 2 3) :whatever)

17:36 clojurebot: nil

17:36 ataggart: nth works on sequential structures

17:36 get works on associative structures

17:36 they're different

17:37 only you can know which structures you're working with

17:37 AWizzArd: ,(get '[10 20 30 40] 2)

17:37 clojurebot: 30

17:37 AWizzArd: ,(get '(10 20 30 40) 2)

17:37 clojurebot: nil

17:37 ataggart: and you don't need to quote vectors

17:37 AWizzArd: I know.

17:37 ska2342: what about raising an exception if you pass a sequential thing to get?

17:37 ataggart: k :)

17:37 AWizzArd: that would not be a good thing

17:38 It was part of rhickeys descisions to return nil instead of throwing exceptions

17:38 ataggart: if you need to check for that case (instead of relying on nil) then use contains?

17:38 AWizzArd: so you don't have to scatter your code everywhere with (try (get ..) (catch Exception e nil))

17:38 ska2342: AWizzArd: like nth for associatives? ;-P

17:39 ataggart: might be an oversight

17:39 AWizzArd: nth on maps is one thing, it could be discussed, but well, for get the situation is different. I don't see why get can not be like nth on lists

17:39 ska2342: ataggart: contains? quietly returns nil for lists, every time. I this time it could get the result in O(1) just like it does for vectors

17:40 ataggart: AWizzArd: because get is contractually fast. You cannot be fast on lists.

17:40 ska2342: nil == false in that context

17:40 AWizzArd: Is there an argument why get should be contractually fast?

17:40 ska2342: I am not a language desinger (IANALD? ;-) but this is fishy

17:41 AWizzArd: Maybe usabilty could come before efficiency here

17:41 ska2342: ataggart: don't ever try to argue with a newcomer to lisp-likes about nil not being false anytime :)

17:42 mmarczyk: AWizzArd: there might be a general argument to support the notion that any core library function performing basic data structure manipulation duties should have its performance guarantees included in its contract

17:42 ataggart: since get returns nil for structures where get is not ~O(1), if you're worried about whether that nil is the "not able" nil, or the "here's the value, which happens to be nil" nil, then use contains?

17:43 mmarczyk: only contains? happens to be the predicate counterpart of get :-)

17:43 ataggart: AWizzArd: that's a great way for people to write slow code and blame the new language. Pick your datastructures with forethought instead.

17:43 ska2342: ataggart: but (as I said) contains? does the same thing as get with lists

17:43 mmarczyk: ,(contains? '(1 2 3) 1)

17:43 clojurebot: false

17:43 mmarczyk: ,(contains? [1 2 3] 1)

17:43 clojurebot: true

17:43 mmarczyk: ,(contains? [1 2 3] 3)

17:43 clojurebot: false

17:44 ataggart: the question being answered by contains? is "is it meaningful to use get"

17:44 mmarczyk: ,[(get [1 2 3] 1) (get [1 2 3] 3)]

17:44 clojurebot: [2 nil]

17:44 AWizzArd: ataggart: how would get be slower than nth?

17:44 mmarczyk: ataggart: ah, I see the point you're making now

17:44 ska2342: please don't get into the old contains? checks for index discussion now...

17:44 ataggart: I'm conveying what I understand to be Rich's POV

17:44 not my own

17:44 AWizzArd: newcomer wants to get element 5000 out of a list. (get elements 5000) ==> slow, so Clojure must be blamed?

17:45 mmarczyk: ska2342: not getting into any discussion on this, just point out the current state of afairs

17:45 ska2342: ataggart: perfectly fine, I try to understand it :-)

17:46 mmarczyk: AWizzArd: well hopefully people no better than to expect less than O(n) from linked list lookup :-)

17:46 know better

17:46 but still, if it is a totally different operation to, say, vector lookup by index

17:47 why overload a single function with both tasks

17:47 ska2342: mmarczyk: that's one of my points. If I feed a list to the element-getter-function, I know the penalty. I don't really see the reason for having both

17:47 ataggart: if you want the nth item, use nth

17:47 if you want to lookup by key, use get

17:47 mmarczyk: what ataggart said :-)

17:47 ataggart: it's not hard

17:48 mmarczyk: it's conceivable that we could have just one name in core for both things

17:48 ataggart: btw, regarding the need for contains?...

17:48 ,(get '(:a :b) 1)

17:48 mmarczyk: I don't see how that would be helpful in anything

17:48 clojurebot: nil

17:48 AWizzArd: well, a list is also a mapping, from its position (key) to the element that is referenced there (val)

17:48 ataggart: ,(get [:a nil :b] 1)

17:48 clojurebot: nil

17:48 ska2342: mmarczyk: overloading because then I can change the type later easily. Me, coming from lisp not java, likes to do experiments with lists. And I hated the changes I had to do in CL when I changed the implementation

17:48 mmarczyk: AWizzArd: not at all

17:48 ataggart: AWizzArd: incorrect

17:48 mmarczyk: ska2342: a-ha! you see, there's the point of "having both" for you :-)

17:49 ska2342: to force you out of your "listy" comfort zone into using the could-be-correct data structures from the get-go

17:49 which is perfectly easy to do in Clojure, since you've got first class vectors, on par with lists, functionally "updatable"

17:49 ska2342: mmarczyk: sorry, I don't get that. Could you please elaborate?

17:50 mmarczyk: ska2342: there's no point at all, in Clojure, to experimenting with lists first

17:50 when a vector is actually the better data structure

17:50 because you gain nothing in syntactic convenience or "natural feel" of your programme

17:50 AWizzArd: if lists can be used to implement maps, then they offer semantically the same, so, yes, lists are mappings

17:50 mmarczyk: that's in contrast to Scheme / CL where lists are obviously the only first class citizens

17:50 AWizzArd: you can implement classes and maps with lists, and vice versa

17:50 ska2342: mmarzyk: Point taken. And I already adapted my habits. It's just the remembrance of things that makes me shudder

17:51 ataggart: AWizzArd: maps are not implemented with lists

17:51 mmarczyk: well, lists and very similar abstractions like Scheme's streams

17:51 AWizzArd: I know, of course they are not

17:51 for sake of efficiency

17:51 but conceptually they can express the same thing

17:51 ataggart: and efficiency is the entire point of the get function

17:51 AWizzArd: from turing point of view

17:51 ska2342: It feels like in Clojure lists are only created for containing code.

17:51 mmarczyk: ska2342: yeah, I actually find I miss nice vector support in Scheme nowadays :-)

17:52 AWizzArd: I would say that the point of get is to get the value behind the key

17:52 ataggart: ska2342: bingo!

17:52 AWizzArd: with the best performance possible

17:52 ataggart: "key" has no meaning for lists

17:53 AWizzArd: it has the same meaning as it has for vectors or maps

17:53 ataggart: except the synthetic one you impute by position

17:53 false

17:53 mmarczyk: ska2342: actual lists / conses, yeah, but list-like seqs are used all over the place

17:53 AWizzArd: ataggart: can you explain it?

17:53 ataggart: apparently not

17:53 AWizzArd: (:

17:53 mmarczyk: :-)

17:53 ska2342: mmarzyk: seqs are a different beast. But get just returns nil for them, too ,-)

17:54 hiredman: ~ping

17:54 clojurebot: PONG!

17:54 ataggart: but to back up, certain functions are provided precisely for their performance characteristics.

17:54 get os one of those functions

17:54 mmarczyk: ska2342: for the same reasons as with lists :-)

17:55 chouser: one could try to implement all abstractions on all concrete types: use lists as maps and sets, maps as lists and vectors, etc.

17:55 AWizzArd: I don't mind having two fns, get and nth. Though in the end it would be totally acceptable to only have a "get" which works as efficient as possible on its specific type.

17:55 ska2342: ataggart: that kinda feels wrong for me, since I happen to think Big-O when I think about datastructures, not functions. I still hold my point with the exception

17:55 chouser: things would "just work" but with less clear performance profiles.

17:55 AWizzArd: chouser: yes, this is possible

17:55 exactly

17:55 chouser: but that language is not Clojure

17:56 AWizzArd: yes, this is more in the category of turing completness

17:56 ataggart: what does turing completeness have to do with any of this?

17:56 AWizzArd: in principle lists would be enough to do calculations, numbers are not needed

17:57 ataggart: sure, and the performance profile would be crap. Still not clear on what this has to do with TC

17:57 AWizzArd: the magic word here is "category"

17:57 ska2342: chouser: then, why have lists at all? Because Clojure is a lisp? Just for code?

17:58 ataggart: ska2342: you use them in macros

17:58 chouser: lists are useful

17:58 Borkdude: ska2342: I asked that question one time, then I came up with a GW-Basic version of Clojure where you can do goto to step into the nth instruction

17:58 chouser: if you want to pop and seq in the same direction, for example

17:59 ska2342: wouldn't anything implementing Sequential suffice?

17:59 mmarczyk: lists are basically finite sequences

17:59 if you're going to have lazy, potentially infinite seqs

17:59 it makes sense to allow for the finite case to

17:59 ska2342: Oh, sorry, the interface Sequential seems to be empty here

18:00 Borkdude: maybe you can say that lists are literal seqs in Clojure?

18:00 raek: also, lists can be partially garbage collected

18:00 mmarczyk: and as chouser points out, LIFOs "are" lists (are naturally implemented as)

18:01 raek: anything that has parts can be partially garbage collected

18:01 raek: for lists, you have to lose the head for that to happen, for vectors -- the trie root, which happens all the time

18:01 AWizzArd: btw, as vectors are tries under the hood, is conj as efficient for vectors as it is for lists?

18:02 mmarczyk: conj is the one op which is implemented for all Clojure data structures

18:02 and is efficient across the board

18:02 raek: don't vector seqs have a reference to the trie root?

18:02 ataggart: but, they do have *slightly* different chartacteristics

18:02 mmarczyk: but it does different things: cons for lists, push-at-tail for vectors

18:02 AWizzArd: ataggart: yes, this is what i would intuitively thing

18:02 i am going to try this now :)

18:03 raek: (drop 999 (seq 1000-element-vector))

18:03 ataggart: O(1) vs O(log32n)

18:03 mmarczyk: raek: ah, possibly

18:03 ataggart: close enough

18:03 raek: won't that retain all the elements?

18:04 ataggart: raek: nope, nothign holds the head

18:04 of the 100-element-vector

18:04 mmarczyk: raek: but if you do (assoc [...] ix :foo), the old version of the vector might be garbage collected

18:04 raek: so there's partial GC for you

18:04 AWizzArd: ,(time (dotimes [i 1000000] (conj [] 10)))

18:04 clojurebot: "Elapsed time: 226.984 msecs"

18:04 Borkdude: maybe it would be nice to include some big-O information as metadata and some functions that can deduce how your functions will perform... just thinking aloud

18:04 AWizzArd: ,(time (dotimes [i 1000000] (conj () 10)))

18:04 arohner: if 1000-element-vector is a local or var, doesn't that hold head?

18:04 clojurebot: "Elapsed time: 148.905 msecs"

18:04 ataggart: try not to kill clojurebot

18:04 :)

18:04 mmarczyk: Borkdude: wow, this is really cool :-)

18:04 AWizzArd: the bot is pretty well secured by now

18:05 mmarczyk: ataggart: on the contrary, we should all endeavour to kill clojurebot so that clj-sandbox might be improved :-)

18:05 AWizzArd: now Licenser should step in :)

18:05 mmarczyk: or is this one not based on clj-sandbox, I forget... state-of-the-art in Clojure sandboxing, anyway

18:07 Borkdude: mmarczyk: don't know if it's possible though

18:07 just an interesting thought

18:08 mmarczyk: Borkdude: well, I suppose a general big-O calculator would be impossible, as it would have to determine stuff like no. of iterations per element etc.

18:08 Borkdude: but having an extra piece of meta data would be cool :-)

18:08 {:big-O "n"} for O(n)? :-)

18:09 ataggart: big-O's usefulness is often overstated

18:09 Borkdude: For example, or maybe :big-O {:get "1" :nth "n"}

18:09 ataggart: case in point:

18:09 ,(type {:foo :bar})

18:09 clojurebot: clojure.lang.PersistentArrayMap

18:10 ska2342: the meta-tag would need a better name, though. :landau ? ;-)

18:10 arkahn: for the following ;;; (defn read-a-file [#^String f] (with-open [#^BufferedReader r (FileReader. f)] (.r readline))) ;;; does the #^String help or is it unnecessary?

18:10 ataggart: take it away and call (set! *warn-on-reflection* true)

18:10 mmarczyk: ska2342: yeah :-)

18:10 ataggart: clojure will tell you

18:10 premature type-hinting is...

18:11 arkahn: started, the noob-clojure programming has ... : (

18:11 : )

18:12 mmarczyk: ataggart: I'm not sure if this perfectly valid point has any bearing on whether big-O is useful :-)

18:12 Fare: does clojure run on Android?

18:12 lancepantz: Fare: yes

18:12 Fare: yay.

18:12 ataggart: clojure run where java runs (more or less)

18:12 mmarczyk: Fare: I remember reading an entry on some blog describing how to set up a repl for use on an android phone :-)

18:13 Fare: (yes, but Android has its own set of Java libraries, so I was wondering)

18:45 arkahn: should 'when' be avoided if side-effects are not being introduced

18:46 Fare: use and ?

18:46 arkahn: Fare: I'm sorry - I'm not sure what you mean

18:47 Fare: use a pred?

18:48 raek: 'when' is useful whenever you would put nil in the false branch of an if

18:48 tomoj: ,(if nil 3)

18:48 clojurebot: nil

18:48 tomoj: guess it's just a better name than 'if' for this case

18:48 raek: hrm, yes

18:49 * technomancy posits that "when" is an indicator to the reader that side-effects are coming

18:49 arkahn: ok ... so side effects are not required in a stylistic sense

18:49 tomoj: wait, huh?

18:49 people use side-effects with when?

18:49 raek: (when pred do-a do-b do-c)

18:49 arkahn: I was reading that using 'do' suggests that "side effects follow" and 'when' is an if + do

18:49 technomancy: yes, that's why "when" has an implicit "do"

18:50 arkahn: that's quite right.

18:50 tomoj: oh, weird, I never got that

18:50 arkahn: cool - thanks all

18:50 tomoj: I always just used it to replace an if with no else

18:50 arkahn: I read it's used then, too, but apparently only when you want to introduce side effects (?)

18:51 not enforced by clojure, but programming style

18:55 chouser: no, 'when' is fine in pure code for "ifs" with no "elses"

18:57 arkahn: chouser: Programming Clojure (p. 48) suggests what technomancy said, but that's the only authoritative source I have to go off of

19:00 chouser: at least, it refers to 'do' in that example, so does that implicitly apply to 'when' when it's just an 'if ? do-a do-b do-c'? I'm just learning ; )

19:01 I feel like I'm learning basketball and all I've done so far is learn dribbling a basic passing o.0

19:08 fwiw, I checked Joy of Clojure and they don't use 'when' only for forms including side effects. Clojure is my first lisp; is 'if' so gimpy because of lisp heritage, so 'when' was created? 'if' doesn't seem like it would be commonly used.

19:09 Chousuke: hm?

19:09 when is just a convenient form for an if that has no else-clause

19:10 the syntax for is is (if pred then else) whereas when is (when pred then-expr*)

19:11 it also conveys the intent better

19:11 arohner: arkahn: 'when' is also useful as a hint to the reader that there should be no else clause

19:11 as opposed to (if p true-clause)

19:12 arkahn: ok - thank you

19:17 tomoj: why does if seem like it would be uncommon?

19:17 it's quite common

19:19 ataggart: perhaps he's asking because if isn't in the api?

19:19 arkahn: most of the code I've read doesn't use it but that's not saying much - what I said really doesn't make sense, including the "gimpy" label

19:19 all this has been helpful to think over though

19:28 DuneMan: one thing is that the normal places that you see lots of if/elses in imperative code get shoved into things like (filter...) in clojure. There tends to be somewhat less boiler-plate conditional checking construction.

19:30 * technomancy is not convinced that you need a "shorthand" for if without else

19:31 DuneMan: neither am I.

19:31 but I do like how "when" reads.

19:36 maxhodak: no matter what i do amap always throws java.lang.IllegalArgumentException on me

19:40 defn: Could someone explain the whole Q thing?

19:40 ,Q

19:40 clojurebot: <-nil-<

19:40 defn: ,`Q

19:40 clojurebot: sandbox/Q

19:40 defn: ,``Q

19:40 clojurebot: (quote sandbox/Q)

19:41 arkahn: it's shorthand for clojure.lang.PersistentQueue/EMPTY I think, but I've only seen it used with clojurebot and/or sexpbot

19:42 ataggart: (conj 5 Q)

19:42 ,(conj 5 Q)

19:42 clojurebot: java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IPersistentCollection

19:42 ataggart: ,(conj Q 5)

19:42 clojurebot: <-(5)-<

19:43 ataggart: interesting

19:43 ,(pop *1)

19:43 clojurebot: java.lang.IllegalStateException: Var clojure.core/*1 is unbound.

19:44 tomoj: what about the whole <-*-< thing?

19:45 is that how PersistentQueues print now?

19:45 arkahn: that's bot specific because I haven't seen that at the repl when using those

19:46 it makes me think they're there to show where elements enter and exit the queue

19:49 I was looking at a way to share data between two threads and at first thought I wanted to use clojure.lang.PersistentQueue but am now thinking agents might be more idiomatic ... and hoping I don't take a performance hit for agents over PersistantQueue

19:52 ninjudd: ,(class Q)

19:52 clojurebot: clojure.lang.PersistentQueue

19:53 tomoj: arkahn: I don't think the choice is between PersistentQueue and agents

19:54 if you use a PersistentQueue, don't you need a reference type anyway?

19:54 arkahn: yes

19:56 ninjudd: that reminds me, i have a patch i need to submit to make PersistentQueue count O(1)

19:56 arkahn: I was thinking of it as a way to pass data: a thread could stuff it in a shared data structure or could send-off messages to an agent which ends up being a fifo-style anyway

19:56 ninjudd: right now, if you call count, it iterates through the list portion of the queue to count it

19:58 arkahn: all persistent data structures are a way to share data

20:00 you still need a time construct to modify a persistent queue... a ref or an agent or an atom

20:01 if you want another thread to see the change

20:02 DuneMan: arkahn: SynchronousBlockingQueue can actually make more sense for that use case

20:03 but it depends on what you're doing

20:03 If you're just doing like... spin up a bunch of threads and process messages on them

20:03 then just use agents

20:03 'cause that's what they are.

20:03 arkahn: I guess I was going to use the PersistentQueue or agent (scalar? just passing strings) for raw data to communicate between the threads and another data structure for parsed data

20:04 DuneMan: Atom + watchers

20:04 or a SynchronousBlockingQueue

20:05 depending on what behavior you need.

20:05 arkahn: For my first clojure program, I wanted to write something that tailed a log file and then parsed the data, perhaps in two threads but I was still debating that "design". Just starting out with clojure.

20:05 DuneMan: take a look at fill-queue

20:05 arkahn: ok

20:06 ninjudd: arkahn: PersistentQueue and agent are two different types of things. PersistentQueue is a data structure whereas agents are a mechanism for changing a reference in a thread-safe way

20:06 the reference could be to a PersistentQueue

20:07 arkahn: ninjudd: yes - I didn't mean to confuse the two ... I should finish up some code and show that - it'd be easier for me to explain ; )

20:07 ninjudd: ok :)

20:07 tomoj: are there any good examples of fill-queue out there?

20:08 I believe I understand how it works, but that I don't really get it

20:32 mmarczyk: tomoj: clojure.contrib.lazy-seq uses it

20:33 tomoj: thanks

20:34 mmarczyk: aaaa, wait, wrong lib

20:34 I meant c.c.lazy-xml

20:34 in parse-seq

20:35 Raynes: Michael Kohl alerted me a little while ago to the fact that someone is considering presenting an IRC bot based on Irclj at a functional programming user group this Monday. :>

20:35 This makes me a happy Rayne.

20:35 mmarczyk: Raynes: cool :-)

20:54 alexyk: given two maps with keys which are integers, what's the cutest way to get the merged deduped list of keys in sorted order?

20:54 don't need values here, just the keys

20:55 I guess adding them to sorted set?

20:56 forgot, how do add things to a set?...

20:56 .(sorted-set 1 2 3)

20:56 ,(sorted-set 1 2 3)

20:56 clojurebot: #{1 2 3}

20:57 alexyk: now how do we add 4?

20:58 ninjudd: ,(keys (merge (sorted-map) {2 3 7 6} {19 2 1 3}))

20:58 clojurebot: (1 2 7 19)

20:58 alexyk: ninjudd: no merge before keys!

20:59 maps are huge, think graphs :)

20:59 rdsr: Hi all, can I define a let within the bindings of for

20:59 ?

20:59 mmarczyk: ,(reduce into [(sorted-set) (keys {2 3 7 6}) (keys {19 2 1 3})])

20:59 clojurebot: #{1 2 7 19}

21:00 rdsr: something like this (for [i ... j ... :let n (* i j)] ...

21:00 mmarczyk: rdsr: :let [n (* i j)]

21:01 alexyk: mmarczyk: warmer, can we tuck both keys into a map to operate on a list of maps?

21:01 ninjudd: mmarczyk: nice

21:01 alexyk: i.e. say keys once :)

21:01 mmarczyk: sure

21:01 alexyk: ok :)

21:01 mmarczyk: ,(reduce into (cons (sorted-set) (map keys [{2 3 7 6} {19 2 1 3}])))

21:01 clojurebot: #{1 2 7 19}

21:01 alexyk: yay!

21:01 mmarczyk: :-)

21:02 alexyk: how about we do (apply sorted-set (concat...)) instead?

21:02 then the set will be sorted at creation time

21:02 mmarczyk: um, nope, try it

21:03 also, the set *is* sorted at creation time

21:03 of course it's also empty :-)

21:03 ninjudd: ,(apply sorted-set (mapcat keys [{2 3 7 6} {19 2 1 3}]))

21:03 clojurebot: #{1 2 7 19}

21:03 mmarczyk: ah yes, mapcat helps :-)

21:04 DuneMan: *enjoys watching these types of discussions*

21:04 MadWombat: Hello

21:04 mmarczyk: but anyway, it's the same thing

21:04 with the sorted set being built incrementally by a Java loop

21:04 who knows, maybe that's a bit faster :-)

21:05 alexyk: ,(apply sorted-set (apply concat (map keys [{2 3 7 6} {19 2 1 3}])))

21:05 clojurebot: #{1 2 7 19}

21:05 mmarczyk: DuneMan: me too :-)

21:05 alexyk: mapcat = (apply concat (map ...))

21:05 alexyk: ah!

21:05 mapcat should be clojure mascot

21:06 DuneMan: *pictures a really lame logo*

21:06 mmarczyk: ohhh, and you mentioned concat above

21:06 alexyk: and... the Oscar goes to ninjudd!

21:06 mmarczyk: sorry, missed that

21:06 DuneMan: aha, I'm in IRC, I can actually use /me, doh

21:06 ataggart: cdr shdr wdr

21:07 DuneMan: ugh

21:07 * alexyk mmarczyk gets the viewers prize :)

21:07 alexyk: who stole car/cdr from clojure?

21:07 DuneMan: An ex-coworker of mine made and sold a bunch of t-shirts with just "()" on them

21:07 alexyk: ,(doc car)

21:07 clojurebot: I don't understand.

21:07 DuneMan: I see the occasional nerd in the bay are wandering around with one

21:07 area*

21:08 ataggart: "my other car is a cdr."

21:08 mmarczyk: :-)

21:08 ataggart: someone's bumpersticker

21:08 DuneMan: *shakes head*

21:09 I almost got a custom license plate with SFINAE on it... but I decided only 4 people would get it

21:09 * ataggart wishes leiningen was based on ant+ivy instead of maven

21:10 * mmarczyk just went off to Wikipedia to become the 5th person

21:10 * alexyk is happy one can do it all in maven, even though it's crappy. technomancy is our Great Leader and Dear Leader rolled into one.

21:11 * alexyk reminisces how Scala Simple Build Tool's reliance on Ivy made early days annoying for coexistence with maven

21:11 mmarczyk: is the *jure ban due to the Great or the Dear part? ;-)

21:12 alexyk: mmarczyk: meaning Great Dear Leader's reluctance to use *jure-suffixed names?

21:12 ataggart: there are only so many puns

21:12 seajure

21:12 I like the best

21:13 mmarczyk: alexyk: no, meaning his reluctance to allow people to use those names with their projects with current snapshots of lein :-P

21:14 alexyk: mmarczyk: that's the dear part, since it's endearing :)

21:15 mmarczyk: alexyk: isn't that "endangering", with who knows how many *jure partisans lurking around?

21:16 alexyk: mmarczyk: then it's Great since it imposes an iron will on an unruly and anarchical mob!

21:16 with the unabashed bold display of stylistic preferences

21:19 mmarczyk: fine :-)

21:20 _brian2_: noob question > I want to develop patches to a library, what do to my project file, etc?

21:20 ninjudd: lancepantz: maybe we should name our NativeClassLoader project classlojure just to spite him

21:21 or is classloadjure better?

21:21 mmarczyk: I'd say, go with loajure

21:21 ;-)

21:22 ninjudd: classlojure is nice because you take the c from clojure and replace it with class

21:22 mmarczyk: true!

21:27 ninjudd: http://github.com/ninjudd/classlojure

21:27 mmarczyk: way to go!

21:28 :-)

21:28 nice Gist (NCL), by the way

21:29 ninjudd: mmarczyk: thanks. now we just need to figure out how to make it work without changing Clojure internals

21:31 mmarczyk: you think that's possible? (I really wouldn't know, my Java-fu is rather weak)

21:33 ninjudd: i think that *use-context-classloader* is supposed to allow you to use your own classloader

21:33 but it doesn't seem to work for import for whatever reason

21:38 hugod: ninjudd: *use-context-classloader* is true by default, you just need to set the thread context class loader to the one you want

21:39 ninjudd: hugod: yeah, but for some reason it doesn't work for import

21:39 here's my code that doesn't work: http://github.com/ninjudd/classlojure/blob/master/src/clj/classlojure.clj

21:45 MadWombat: can anyone point me in the right direction to load and call ant tasks from an XML file in clojure/java?

21:45 some sort of factory class perhaps?

21:47 hugod: ninjudd: you trying that AOT'd ?

21:47 ninjudd: hmm, no

21:47 i was just trying it on the repl

21:52 _brian2_: noob question, if I want to develop patches for a pre-existing library, do I git the library to my computer and put [lein-clojars "0.5.0"] into my project file, do I have to take the original dependencies out?

21:56 hugod: ninjudd: it looks to me as if the context class loader is not used if Compiler.LOADER.isBound(), which is the case inside an eval or a load. I have only ever tried setting the classloader before calling into clojure from java.

21:57 brweber2: so I created a gateway drug to help people get into clojure

21:57 http://github.com/brweber2/clojure/tree/master/examples/

21:57 mostly b/c I wanted to start messing around with the source code

21:57 it is NOT intended to be serious

21:57 but any feedback is appreciated

21:57 it is a full fork of clojure on github

21:57 but the changes are very minimal

22:01 rhickey How was day 1?

22:04 hugod: some clojure mojo : http://github.com/hugoduncan/clojure-mojo-example/blob/master/src/main/clojure/maven/clojure/example/plugin.clj

22:14 lancepantz: how do i get emacs to always use paredit in clojure-mode?

22:17 _brian2_: DuneMan : do you know.. if I want to develop patches for congomongo, whats the idiomatic way, do I git it to my computer, put [lein-clojars "0.5.0"] in project file and take congomongo dependenicies out, or leave in, or am I on the wrong track?

22:50 joshua-choi: Perhaps this has been asked before, but... I want to know if there's a fast, standard function that transforms a map: (= (transform f m) (into {} (for [[k v] m] [k (f val)]))).

22:50 Perhaps one that uses transients. This function would be very useful to me.

22:53 hiredman: ,(doc fmap)

22:53 clojurebot: "clojure.contrib.generic.functor/fmap;[[f s]]; Applies function f to each item in the data structure s and returns a structure of the same kind."

22:55 tomoj: awesome

22:55 joshua-choi: Eh...that's a multimethod. Thank you, though.

23:06 powr-toc: lancepantz: http://gist.github.com/399438

23:06 lancepantz: thank you :)

23:12 joshua-choi: Is there a for-like macro that iterates specifically through nested maps?

23:14 powr-toc: joshua-choi: the closest I can think of is building something with tree-seq

23:14 joshua-choi: (map-for [x {:a {:a 1, :b 3}, :b {:a 2, :b 2}}, y x] (+ (count x) y))

23:14 Hmm

23:15 powr-toc: can you not just call seq on the maps?

23:15 and treat them as pairs?#

23:16 joshua-choi: powr-toc: Yeah, but it's a pain to do (into {} (for [[x-k x-v] {...}] [x-k (into {} (for [[y-k y-v] x-v] [y-k (+ (count x-v) y-v)]))])).

23:17 powr-toc: yeah

23:17 joshua-choi: I'm surprised that this isn't much in demand yet

23:18 I want things like this all the time

23:18 powr-toc: what do you want it for?

23:19 joshua-choi: I have a nested map, and I want to transform it into a similar nested map with modified inner vals

23:20 powr-toc: can you use merge-with?

23:20 joshua-choi: How would I do that?

23:21 I don't think I can, no.

23:22 tomoj: can't you just take the fmap for maps and make it a function?

23:23 huh, seems fmap doesn't even do what you want

23:24 powr-toc: joshua-choi: I'm struggling to see what your idea for map-for is doing... is the destructuring right?

23:24 joshua-choi: I believe the do-monad of the map-m monad does what I want, though it's not very well-supported

23:25 tomoj: and certainly not fast, I'd think?

23:25 joshua-choi: powr-toc: The bound variable x is bound to each val of the {:a ..., :b ...} map, and the subsequent bound variable y is bound to each val of x.

23:26 Ideally, it'd use transients or something

23:26 If I wrote my own, could I submit it to clojure-contrib?

23:30 If monads are good at one thing, it's making it easier to write let/for-like macros.

23:31 tomoj: oh, so you'd use map-m just to generate the macroexpansion which would be fast code?

23:33 joshua-choi: tomoj: Yes, I would—except map-m doesn't yet exist in clojure.contrib.monads.

23:33 * joshua-choi wants monads to be updated with protocols and better var names

23:34 tomoj: I was wondering earlier whether protocols would help

23:34 joshua-choi: I'm glad Rich Hickey showed an interest in eventually integrating monads into clojure's main namespaces

23:34 powr-toc: he did?

23:34 joshua-choi: I think it was on the clojure-dev Google group.

23:34 tomoj: "Number of monads in Clojure 1.0: Zero. In 1.1: Zero. In 1.2: Zero. Monads are not idiomatic (via @stuarthalloway)"

23:35 heh

23:35 joshua-choi: Yeah, I read that too.

23:35 But anyways, it seems that there's currently no standard way to transform a map's vals easily, which is annoying

23:35 Oh well

23:35 (into {} (map ...))

23:35 tomoj: I've run into that problem before as well

23:35 and I think it's come up in here before

23:36 joshua-choi: I would think this would be a common thing to do with maps...:|

23:36 rdsr: hey All, I once saw a cheat sheet which detailed the time complexity of various functions in clojure. I can't seem to find it now, does any one know about it

23:36 ?

23:37 powr-toc: http://www.innoq.com/blog/st/2010/04/clojure_performance_guarantees.html

23:37 sexpbot: "Clojure Performance Guarantees - Stefan Tilkov's Random Stuff"

23:38 rdsr: powr-toc: thanks

Logging service provided by n01se.net