#clojure log - Feb 21 2011

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

2:25 amalloy: DespiteItAll: i was thinking of writing a twenty-questions program for my first foray into clojure web programming

4:35 rata_: what's the recommended way to generate json strings?

4:43 ejackson: c.c.json ?

4:44 rata_: I've used it for a while no w/o problem

4:44 rata_: ejackson: ok =) thanks

4:44 I had heard about clj-json too, but I'll better go with contrib

4:48 ejackson: contrib is a solid choice

5:14 e-user: hi all

5:19 anyone with experience running clojureclr on mono here?

7:25 Dranik: is there anything like prolog for clojure?

7:30 Fossi: Dranik: logos

7:30 google would've found that as well i guess

7:32 Dranik: Fossi, thanks

7:51 edoloughlin: https://gist.github.com/837007 — don't understand why my dispatcher doesn't work for []

7:57 … or any arg, for that matter.

8:58 TimMc: DespiteItAll: Write a flatmate contracts website, where people click radio buttons to agree to certain standard options ("Pots and pans [do]/[don't] go through the dishwasher") and then agree to it by verifying an email sent to each person.

8:59 DespiteItAll: There, now you have a website to write that involves user interaction, input validation, a database, and email sending.

9:01 charliekilo: Stupid question: (def x 2) (eval '(+ x 1)) works while (eval (let [y 3] '(+ y 1))) does not. Why?

9:03 TimMc: ,(let [y 3] '(+ y 1))

9:03 clojurebot: (+ y 1)

9:03 TimMc: ,(let [y 3] (eval '(+ y 1)))

9:03 clojurebot: DENIED

9:03 charliekilo: Sorry I meant (let [y 3] (eval '(+ y 1)))

9:03 TimMc: Ooh, clojurebot doesn't like eval.

9:04 charliekilo: My REPL doesn't either ;): java.lang.Exception: Unable to resolve symbol: y in this context

9:04 TimMc: In that case, I don't know the answer.

9:05 charliekilo: I got it to work with (eval '(let [y 3] (+ y 1)))

9:05 but thats not what I want

9:06 TimMc: Hmmm... I bet this has to do with symbols -> vars stuff, and let not introducing var bindings.

9:06 ...but that's beyond my knowledge, really.

9:07 In any event, what are you trying to do? Seems like you want quasiquoting instead.

9:10 e-user: anyone with experience running clojureclr on mono?

9:21 fliebel: morning

9:21 mids: hoi

9:41 fliebel: Not directly Clojure related, but anyway… The Reasoned Schemer mentioned that NAND is a universal binary relation. All other relations can de defined by it. Does such a relation exist for >binary?

9:45 So, a sensible relation for(for example) a trinary(0, 1 2) number, that can be used to define all other relations, and eventually half-adders and such. If there are non, I'm going to invent them :) (ouch, I hope I'm not saying impossible things now)

9:58 dnolen: fliebel: is the any-o issue fixed for you?

9:59 fliebel: dnolen: I havn't tried yet, I've been away the whole weekend. I did read a lot on TRS though.

10:00 dnolen: I'm still intrigued by the number stuff. I can see why it would be slow, but I like it.

10:00 dnolen: fliebel: nice. well let me know how it goes and if anything else crops up.

10:00 fliebel: sure :)

10:00 dnolen: fliebel: it's very beautiful. all sort of arithmetic relationships appear like magic :)

10:01 fliebel: dnolen: I've been thinking about moving the numbers from binary relations to decimal relations. I'm not sure if it's even possible, or fast(er), but it's an interesting exercise.

10:03 dnolen: I think it would be useful to have some debug option in Logos, to see how many unifications are done for a result.

10:04 Cozey: Hello. Ring passes body to response.getOutputStream. I want to pass a result of XSLT transformation which itself requires an OutputStream. Can I somehow short-circut these? Or do I need to first get a whole output of transformation and then return it as string body to ring. seems inefficient.

10:05 dnolen: fliebel: yes, that would be very useful, still thinking about how to properly implement debugging facilities. A bit tricky since the whole thing works with lazy sequences.

10:06 fliebel: dnolen: If I implemented that number stuff, would you want it for Logos, or do I just keep that to myself?

10:08 dnolen: fliebel: I would definitely consider it. Keep me posted on how it goes.

10:09 fliebel: dnolen: Great :) I'll start out by converting the stuff from the book to Clojure, and then I plan to see if I can make it any more efficient. I haven't studied computer science though ;)

10:12 (was the any-o bug really fixed in one line?)

10:13 dnolen: fliebel: only a couple lines. The issue was simple, reduce is not lazy, I replaced it with mplus-concat which is lazy.

10:13 Cozey: hmm answering myself: looks like a job for piped streams of java's

10:17 dnolen: wow! this plotter idea is absolutely fantastic!

10:18 dnolen: Cozey: plotter?

10:18 Cozey: isn't this Yours? http://www.formconstant.net/

10:18 dnolen: Cozey: heh, yes.

10:20 Cozey: as well as one drawing a day :-) hope that's working

10:20 dnolen: Cozey: haven't done much with recently. Got a bit into a Python implementation 2-3 years ago that I haven't touched since. That stuff is fun. Pen plotters are easy to come by and they use a brain dead simple ASCII serial protocol that's well documented.

10:20 Fossi: bit noisy on the console :)

10:21 dnolen: Cozey: also not so much recently, but hope to get back to that.

10:22 Cozey: will take a look at logos as well. . i was missing prolog

10:22 are You using SLD or something more advanced?

10:23 dnolen: Cozey: there's quite a history of pen plotter artists, Vera Molnar is particular cool, http://www.veramolnar.com/diapo.php

10:23 Cozey: this is from a plotter?

10:23 but not programmed I guess?

10:23 ah, black and whites

10:23 angerman: What would be a good datastruction for a mesh to do subdivion on in clojure?

10:25 Cozey: so that's where the linear pictures come from

10:25 dnolen: Cozey: not that front image no. http://www.google.com/images?q=vera+molnar

10:26 Cozey: not SLD, the algorithms from The Reasoned Schemer, but with Clojure changes for better performance.

10:28 Cozey: implementation discussed in the book is this "Kanren"?

10:29 interesting :-) thanks :D

10:32 dnolen: Cozey: Kanren is an earlier implementation by Oleg Kiselyov. miniKanren is distillation of that work by Kiselyov, Daniel Freidman, and William Byrd.

10:33 kgrad5_: If i have an infinite sequence, let's say something like (iterate #(+ % 2) 1) how would I take all numbers less than some threshold? conceptually i want to do something like (take #(< % 1000) (iterate #(+ % 2) 1)) (i know that doesn't make sense)

10:33 gfrlog: take-while?

10:33 if they're sorted that will work

10:33 kgrad5_: oh sweet, thanks a lot gfrlog

10:33 gfrlog: ,(take-while #(< % 100) (iterate #(+ % 2) 1))

10:33 clojurebot: (1 3 5 7 9 11 13 15 17 19 ...)

10:34 gfrlog: kgrad5_: no problem

10:36 chouser: whoever thought that bundling code and data together would promote code re-use was ... wrong.

10:38 I don't see any option other than (1) patch someone else's code (2) copy huge swaths of their code and make minor changes, or (3) use reflection hacks to work my will at runtime.

11:01 Munksgaard: I'm using cake to run a slime server with swank-clojure, but the connection keeps closing. I'm using clojure-1.3.0-alpha4 and swank-clojure-1.3.0-SNAPSHOT... Does anyone know how to get it working?

11:04 i can evaluate nil in the slime REPL, but once i try to write (println "something") it closes the connection before i even get to the space

11:09 and if i try to use an older version (clojure-1.2.0 and swank-clojure-1.2.0) it just hangs when i try to evaluate nil in the repl

11:15 tensai_cirno: hello guys. I'am experiencing problems with lein repl. It breaks after first error.

11:16 http://pastie.org/1589769

11:17 emacs swank mode just breaks after first whitespace in parenthesis

11:17 also *Versions differ: 2010-06-04 (slime) vs. 20100404 (swank).*

11:17 in emacs

11:17 ubuntu 10.10, emacs and slime from repo

11:22 Munksgaard: tensai_cirno: i've got the same problems

11:36 tensai_cirno: Munksgaard, got working slime

11:36 you need to install it from technomancy repos

11:36 https://github.com/technomancy/swank-clojure

11:36 there's section for emacs

11:36 and ':dev-dependencies [[swank-clojure "1.3.0-SNAPSHOT"]]' in project.clj

11:49 Munksgaard: tensai_cirno: ok, thanks

12:11 Cozey: what's the overhead of "future" ?

12:14 gfrlog: Cozey: seems to call clojure.lang.Agent/soloExecutor

12:15 Cozey: and then doing some thread pool magic... but what does it all mean? Is it really lightweight? so You can paralelize some things 'just because you can' or is it not worth it?

12:16 gfrlog: ,(future 20)

12:16 clojurebot: #<core$future_call$reify__5500@404baf: :pending>

12:16 gfrlog: ,(map deref (map #(future %) (range 10))

12:16 clojurebot: EOF while reading

12:16 gfrlog: ,(map deref (map #(future %) (range 10)))

12:17 clojurebot: (0 1 2 3 4 5 6 7 8 9)

12:17 gfrlog: Cozey: no idea :)

12:17 performance test?

12:17 Cozey: it seems i would need to do that

12:17 gfrlog: or maybe somebody else will speak up

12:17 Cozey: but making benchmarks is quite a taunting task

12:17 gfrlog: just don't listen when tasks taunt you

12:18 they're only doing it because they're insecure themselves

12:20 maybe I shouldn't make fun of strangers

12:43 cdddr: If I do something like (call sorted-set some-seq), does it unwind the whole sequence at once, or process it one at a time?

12:48 AWizzArd: cdddr: it would have to calculate the hash of some-seq.

12:49 some-seq is tested via the hash if it is one of the elements in your sorted-set.

12:50 cdddr: Uhh, my bad, I meant apply not call.

12:50 I basically want to keep unique values from some-seq.

12:50 Sorting is nice, but I can do it in another step.

12:51 gfrlog: cdddr: I'm watching tv and not paying attention, but does distinct help?

12:52 cdddr: gfrlog: Ah, yes.

12:53 I'm still at the stage where I'm not sure what the stdlib can do. :(

12:53 gfrlog: easiest people to help :)

12:54 cdddr: Hahaha, right. It's better like this, though. I remember when I "learned" Python on my own, and then I needed to stick for like 3 months on #python to realise I was being ass-backwards about almost everything. :)

12:55 gfrlog: there are so many ways to write bad code...

12:55 cdddr: Yeah. I mean, reimplementing stdlib out of ignorance is bad, but I'd take that over, say, writing COBOL in Java anytime. ;)

12:56 gfrlog: the first option sounds a lot more fun

12:56 clizzin: anyone have any experience with parsing HTML in clojure/java? what's the best library to use?

12:57 raek: clizzin: enlive is very easy to use

12:57 it uses tagsoup under the hood

12:57 clizzin: raek: enlive has functions specifically for parsing? i thought it was a templating library.

12:57 raek: it does that too... :)

12:57 cdddr: gfrlog: Oh, trust me. I've had the misfortune of actually seeing COBOL-in-Java. I almost cried.

12:58 clizzin: raek: interesting, shall check it out. thanks!

12:58 raek: dnolen made a tutorial that explains both the scraping and templating uses

12:59 clizzin: minimal example (fetching the title of a page): https://github.com/raek/lcug-examples/blob/master/bot/src/se/raek/lcug/titlebot.clj

12:59 clizzin: raek: awesome, thanks! btw, any idea how it compares to https://github.com/getwoven/webmine? that's the other one i just remembered which might work well for parsing.

13:02 fceccon|a: clizzin: check https://github.com/swannodette/enlive-tutorial

13:02 raek: clizzin: webmine seems to use tagsoup just like evlive, but looks much more specialized towards extraction (disclaimer: I haven't used webmine)

13:03 clizzin: raek, fceccon|a: great, thanks for the thoughts and advice! i'll play around and see what works best for my use case.

13:31 charliekilo: Stupid question: (def x 2) (eval '(+ x 1)) works while (let [y 3] (eval '(+ y 1))) does not (java.lang.Exception: Unable to resolve symbol: y in this context) ... Why, oh why?

13:31 gfrlog: (doc eval)

13:31 clojurebot: DENIED

13:31 gfrlog: ,(doc eval)

13:31 clojurebot: DENIED

13:31 gfrlog: dangit

13:32 I think eval is funny about local bindings

13:32 by which I guess I mean it ignores them

13:33 what do you get if you (def x 12) (let [x 13] (eval '(+ x)))

13:33 edoloughlin: Anyone got CCW content-assist for Clojure working? It only does Java for me

13:35 gfrlog: ,(let [def 12] (+ def 5))

13:35 clojurebot: DENIED

13:37 charliekilo: 13

13:37 since it sees the first x

13:37 gfrlog: wouldn't 13 mean it sees the second?

13:38 I get 12

13:38 charliekilo: oh, I thought you meant '(+ x 1) and just forgot the 1

13:38 gfrlog: ah; yeah I guess that was unnecessarily complex

13:38 so I would assume that eval just ignores all local 'variables'

13:39 apparently it does see binding; but that's probably not what you want to do

13:39 cdddr: Uhh, why would eval ignore the local bindings?

13:39 gfrlog: dunno...why wouldn't it?

13:40 TimMc: gfrlog: Because it is surprising.

13:40 gfrlog: that is a good reason.

13:40 cdddr: Yeah, and I don't see a good reason to ignore them.

13:40 gfrlog: I should retreat to "I don't know" then

13:41 maybe it's harder to execute...

13:41 TimMc: gfrlog: There is a difference between local let "bindings" and def'ined vars, but I don't know enough about Clojure to say anything further on the subject.

13:41 gfrlog: because the vars are all stored somewhere public, but the local lettings are probably much...slyer?

13:41 TimMc: I do know that let bindings are not mutable.

13:41 gfrlog: well they can be overridden

13:42 ,(let [x 12] (let [x 15] x))

13:42 clojurebot: 15

13:42 TimMc: Sure, but that's just scope.

13:42 gfrlog: yeah

13:42 I would think

13:42 that

13:42 charliekilo: let me ask another stupid question: is 'eval' the right function here?

13:42 gfrlog: lettings can be handled at compile time

13:42 TimMc: ("just scope", he said, infuriating language designers everywhere)

13:42 charliekilo: or is there another one I should use?

13:42 gfrlog: but whatever goes into eval has to be handled at runtime

13:42 TimMc: charliekilo: What do you want to do?

13:43 raek: the lexical scope where eval is called is does not "span" into the evaled form

13:43 TimMc: charliekilo: I ask because you might be trying to reimplement defmacro or something.

13:43 gfrlog: raek: Is that a fancy restatement of "eval doesn't see local bindings"?

13:44 raek: gfrlog: pretty much. :)

13:44 charliekilo: TimMc: I am looking at SICP symbolic differentation and want to eval the resulting function with some value of x

13:44 gfrlog: okay, just making sure I understood

13:44 we were wondering why it would be that way

13:44 TimMc: from a language design standpoint, preferably

13:44 cdddr: You know what Clojure API docs could really use? "See also:" everywhere.

13:45 gfrlog: charliekilo: I'm wondering if macros can help

13:45 TimMc: cdddr: I tend to use clojuredocs.org

13:45 gfrlog: I assume the "don't write macros" mantra has an implicit "unless you would otherwise be using eval"

13:45 charliekilo: gfrlog: thats what I was thinking, but since I am not modifying executing order, it should be possible without it, right?!?

13:45 TimMc: gfrlog: Oooh... symbolic differentiation via macros? I'm getting all tingly.

13:46 cdddr: TimMc: Ooh, that's a gem.

13:46 gfrlog: maybe I should stop talking because I actually have no idea what "symbolic differentiation" means and TimMc makes me think that might be important

13:46 TimMc: cdddr: Blame gfrlog.

13:46 gfrlog: for the existence of a gem?

13:47 cdddr: Heh, I meant the clojuredocs site, but hey, that works, too. :)

13:47 TimMc: cdddr: Hah! OK.

13:47 gfrlog: none of the currently active conversations are not confusing me.

13:48 TimMc: charliekilo: If you were doing symbolic differentiation of hardcoded expressions, macros *might* be appropriate, as outrageous as that idea seems to me at the moment.

13:49 However, I suspect you are receiving sexprs as arguments and wanting to differentiate and evaluate those.

13:49 Quasiquote might help you, actually.

13:50 gfrlog: I was thinking of macros instead of evaling

13:50 i.e., for inserting the code

13:50 inside a (let)

13:50 charliekilo: TimMc: I will try, but it somehow does not feel right ... then again, I have not come up with a good solution either

13:50 gfrlog: now I'm second-guessing myself though

13:51 TimMc: (eval `(let [y 4] ~expr))

13:51 gfrlog: that was the next thing I started thinking about

13:51 so as long as that's not dependent on other local bindings...

13:52 and even if it is you can probably do (eval `(let [x ~x] ~expr))

13:52 raek: iirc, fogus made a library for these kind of things

13:52 TimMc: gfrlog: That was my thought as well.

13:53 charliekilo: hmm ... I guess I have to play around multiple options and see what looks nice in the flow of code

13:53 gfrlog: the only way to write readable code is with triply-nested macros.

13:54 raek: charliekilo: https://github.com/fogus/evalive

13:54 example from the docs: (evil '{message "Hello", place "Cleveland"} '(println message place))

13:55 looks like something that could accomplish what you are trying to do

13:55 cdddr: Ooh, Python-style eval. :)

13:55 charliekilo: raek: that looks like it will work ... I'll take a look .. thanks

14:15 TimMc: Any quick way to turn a seq of maps into a map of seqs?

14:16 brehaut: eg [{:a 1} {:a 2 :b 1} {:b 3}] {:a [1 2] :b [1]} ?

14:17 scottj: merge-with concat?

14:17 gfrlog: ,(doc merge-with)

14:17 clojurebot: "([f & maps]); Returns a map that consists of the rest of the maps conj-ed onto the first. If a key occurs in more than one map, the mapping(s) from the latter (left-to-right) will be combined with t...

14:17 gfrlog: scottj: is that a question?

14:18 scottj: gfrlog: nm

14:18 brehaut: merge-with isnt quite right

14:18 gfrlog: now I'm wondering what a function called concat? would do

14:18 brehaut: merge-with will not call you fn if there is no conflict

14:18 gfrlog: scottj: sorry, I failed to notice the previous comments

14:19 TimMc: brehaut: I know these maps all contain the same keys.

14:19 But no, merge-with wouldn't work.

14:19 gfrlog: TimMc: there's an easy way to do this

14:19 cdddr: brehaut: How so? You can specify your own key-combining function.

14:20 gfrlog: (map (apply juxt maps) ...) should be helpful

14:20 brehaut: cdddr: ##(merge-with (constantly :applied) {:a 1} {:b 2})

14:20 sexpbot: ⟹ {:b 2, :a 1}

14:20 cdddr: brehaut: Ahh.

14:21 gfrlog: (into {} (map (juxt identity #(map (apply juxt maps) %)) (keys (first maps)))

14:21 maybe could clean that up with ->>

14:22 TimMc: I think I'll stick with a three-liner instead.

14:22 gfrlog: but juxt is fun!

14:22 TimMc: ,(doc juxt)

14:22 clojurebot: "([f] [f g] [f g h] [f g h & fs]); Alpha - name subject to change. Takes a set of functions and returns a fn that is the juxtaposition of those fns. The returned fn takes a variable number of args, a...

14:23 gfrlog: (apply juxt maps) is a function that takes a key and returns a vector of the key's value in all the maps

14:23 TimMc: I kind of see where you are going with that.

14:23 gfrlog: the rest is just cruft for tying everything together into a map

14:24 I would think the (apply juxt maps) part would be useful no matter how you rearrange everything else

14:24 brehaut: gfrlog: are you sure that even runs?

14:25 gfrlog: nope :)

14:25 I'm sure that it would if I had a few rounds to debug it though

14:25 TimMc: These maps only have two keys, and I know them.

14:26 cdddr: TimMc: Give in to the dark side of premature abstraction! ;)

14:26 TimMc: (apply juxt my-maps) is a neat trick, but too complicated for this task.

14:26 gfrlog: maybe (let [vals-fn (apply juxt maps)] {:a (vals-fn :a), :b (vals-fn :b)})

14:26 brehaut: tim then its simple

14:26 cdddr: It's just like premature optimization, but with ore fun and mess. ;)

14:27 TimMc: cdddr: I *might* write a LoM->MoL fn.

14:27 brehaut: Don't tell me I can destructure this thing...

14:27 brehaut: ,

14:27 (reduce #(merge-with conj %1 %2) {:a [] :b []} [{:a 1} {:b 2 :a 2} {:b 2}])

14:27 clojurebot: EOF while reading

14:27 gfrlog: mine had less :a's and :b's in it

14:28 brehaut: ,(reduce #(merge-with conj %1 %2) {:a [] :b []} [{:a 1} {:b 2 :a 2} {:b 2}])

14:28 clojurebot: {:a [1 2], :b [2 2]}

14:28 gfrlog: oh nm

14:28 brehaut: yeah its not a 'general' solution

14:28 even easier

14:28 ,(apply merge-with conj{:a [] :b []} [{:a 1} {:b 2 :a 2} {:b 2}])

14:28 clojurebot: {:a [1 2], :b [2 2]}

14:29 gfrlog: brehaut: I think I like it

14:29 TimMc: hm

14:30 gfrlog: making use of the good ole' conj{:a function

14:30 TimMc: After I finish making my tests pass, I'll see if I can wedge that in.

14:31 gfrlog: make a switch statement with a case for each possible number of maps that there could be

14:31 TimMc: Data structure dilemma!

14:32 I'm traversing a DAG and picking up values. I don't want duplicates, but I want to preserve topological order.

14:32 brehaut: ,(reduce (fn [a [k v]] (update-in a [k] (fnil conj []) v)) {} (mapcat (partial map identity) [{:a 1} {:b 2 :a 2} {:b 2}]))

14:32 clojurebot: {:b [2 2], :a [1 2]}

14:32 brehaut: a genera solution

14:32 gfrlog: okay now mine is better

14:33 * TimMc shrieks

14:33 TimMc: OK, that used *two* functions I don't know yet.

14:33 brehaut: gfrlog: really? mine runs :P

14:33 upfate-in and fnil?

14:33 TimMc: mapcat and fnil

14:33 gfrlog: brehaut: That's cuz you have a higher draft standard for irc

14:33 TimMc: Oh man, mapcat is what I've been looking for for another thing.

14:34 I had to write that once for some functional JS I was doing.

14:34 brehaut: TimMc: haha

14:34 TimMc: for is often a more useful way of writing mapcat

14:35 cdddr: Woah, there's map-indexed? One less function in the chain.

14:37 gfrlog: ,(let [maps [{:a 1 :b 2} {:a 2 :b 2}]] (into {} (map (juxt identity (apply juxt maps)) (keys (first maps)))))

14:37 clojurebot: {:a [1 2], :b [2 2]}

14:38 gfrlog: brehaut: I was assuming his all-maps-have-same-keys condition

14:38 brehaut: ok sure. cause otherwise you generate interstitial nils

14:38 gfrlog: and miss some of the keys if they aren't in the first map

14:40 TimMc: That would be the equivalent of a ragged 2D array.

14:40 brehaut: TimMc: vector of vectors is the obvious one

14:40 or a map of vectors

14:40 TimMc: Heh, I guess what I'm basically doing is a transpose.

14:40 brehaut: depends on your keys

14:43 TimMc: if you have a vector of vectors, and you want to transpose its just ##(apply map vector [[1 2 3] [4 5 6]])

14:43 sexpbot: ⟹ ([1 4] [2 5] [3 6])

14:44 TimMc: $findfn [1 2 1 2 4 1] [1 2 4]

14:44 sexpbot: [clojure.core/distinct]

14:45 TimMc: oooh

14:45 gfrlog: I was trying to figure out how to do $findfn just the other day... digging through the sexpbot source and no luck

14:55 amalloy: gfrlog: it's in sexpbot.plugins.clojure

14:55 near the bottom somewhere

14:55 gfrlog: amalloy: must have missed it. I was looking at exactly that.

14:56 I only skimmed the source, so I don't think I actually gleaned any info at all

14:56 I was hoping it'd be full of (def-thing-you-can-type "$findfn" ...)

14:58 amalloy: gfrlog: it is! if you search for "findfn" you find what you want immediately

14:58 (not $findfn, because the command prefix is configurable)

15:00 gfrlog: https://github.com/Raynes/sexpbot/blob/master/src/sexpbot/plugins/clojure.clj#L156

15:01 gfrlog: hmmm

15:01 since I didn't know it was called "findfn" I'm not sure if that would have jumped out

15:01 but I should clarify that I don't at all mean to criticize the code.

15:04 amalloy: gfrlog: sure? i do so enjoy sulking after being maligned

15:05 gfrlog: amalloy: absolutely -- I would have been shocked if the information had been accessible within the amount of effort I was willing to put in

15:05 amalloy: lol

15:05 gfrlog: then I would have written you a personal physical letter of thanks with a five dollar bill in it.

15:07 amalloy: the basic concept of findfn took a couple hours and a dozen lines, but all the tweaking necessary to deal with sandboxing and such makes it a huge mess

15:08 $findfn [1] 1

15:08 sexpbot: [clojure.core/last clojure.core/count clojure.core/peek clojure.core/first clojure.core/rand-nth]

15:08 amalloy: i always get a laugh when rand-nth makes it into the answer list

15:09 cdddr: amalloy: It only tries the core functions, right?

15:09 amalloy: cdddr: https://github.com/Raynes/sexpbot/blob/master/src/sexpbot/plugins/clojure.clj#L146

15:09 $findfn "test" 2 "te"

15:09 sexpbot: []

15:09 amalloy: hm

15:10 cdddr: Ooh.

15:10 amalloy: $findfn 2 "test" "te"

15:10 sexpbot: [clojure.contrib.string/butlast clojure.contrib.string/take]

15:10 Cozey: $findfn (fn [a b] a) 2

15:10 sexpbot: []

15:10 Cozey: any way to get functions arity?

15:10 amalloy: Cozey: that is not an easy problem

15:10 Cozey: I know :-)

15:10 amalloy: someone posted a hacky solution to the google group months ago

15:11 Cozey: http://groups.google.com/group/clojure/browse_thread/thread/d9953ada48068d78/1823e56ffba50dbb

15:28 jweiss_: looking for the simplest fn that will return a different value every time it is called

15:28 (i just care that the values are not equal and don't have isa? relationship)

15:29 scottj: jweiss_: gensym?

15:29 jweiss_: scottj: ah good call

15:45 cinch: jweiss_: (str (java.util.UUID/randomUUID))

15:47 clizzin: is there a way to use apply when you're calling a java method on a variable-length vector of arguments?

15:48 amalloy: clizzin: not really. what's your usage scenario?

15:48 cinch: that's not guaranteed to be different, though of course the odds are...somewhat in favor :P

15:49 clizzin: amalloy: i'm using clojure to wrap a java method. the clojure method takes a variable-length list of arguments at the end, and i wanted to just use apply to call various versions of the java method that take different numbers of arguments

15:50 amalloy: clizzin: the current "best" way to do it is manually, i think. you can hack something up with clojure.lang.Reflector if you want

15:50 clizzin: amalloy: alright, thanks for the info

15:50 cdddr: $findfn [1 2 3] [4 5] [1 2 3 4 5]

15:50 sexpbot: [clojure.set/union clojure.core/lazy-cat clojure.core/concat clojure.core/into]

15:52 amalloy: cdddr: into is the least-awful of those options

15:56 cdddr: amalloy: Yeah, but I'm doing something like (set (concat A B)), so I think concat actually fits better.

15:56 amalloy: cdddr: (into (set A) B)?

15:57 &(into (set [1 2 4 5 2]) [5 7])

15:57 sexpbot: ⟹ #{1 2 4 5 7}

15:57 cdddr: Oooh.

15:57 drobati: I'm trying to use slime for the first time and slime-repl isn't showing up when i slime-connect

15:57 cdddr: Although it feels weird somehow.

15:57 drobati: I installed slime not from packages.el

15:58 amalloy: cdddr: or (set/union (set A) (set B)) if you like

15:58 brehaut: &(use 'clojure.set)

15:58 sexpbot: ⟹ nil

15:58 brehaut: amalloy: i dont think b needs to be a set for union

15:58 amalloy: brehaut: it doesn't, but that's an impl detail

15:58 brehaut: (union #{1 2 3} [1 3])

15:58 amalloy: sure

15:59 amalloy: might even be better for performance to make them both sets, if A were large and distinct, and B were like [1 1 1 1 1 1 ...]

16:01 kjeldahl: drobati: Do you have swank-clojure installed?

16:01 cdddr: x (map println (take 10 some-var)) inside a let... I'm going to debugging hell,

16:01 gfrlog: cdddr: I don't think (map println ...) normally does much

16:02 drobati: I have a dev-dependency in project.clj "1.2.1"

16:02 kjeldahl: I use lein swank.

16:02 cdddr: gfrlog: Hence the take except I lied, I'm doing (count (map... :)

16:02 gfrlog: cdddr: oh okay

16:03 cdddr: My initial, even more clueless version was (drop-while (constantly true)...

16:03 gfrlog: ,(drop-while (constantly true) (repeat "haha"))

16:03 kjeldahl: drobati: swank-clojure.el is an emacs package. On github. I know nothing about lein swank.

16:03 clojurebot: Execution Timed Out

16:04 * cdddr laughs

16:04 drobati: kjeldahl: lein installs swank-clojure from github for me.

16:05 kjeldahl: drobati: It installs an emacs package for you? You're way ahead of me then..

16:05 drobati: Wait. Not an emacs package.

16:06 kjeldahl: It's emacs support you're struggling with, right?

16:06 drobati: I believe so.

16:06 amalloy: cdddr: (filter #{} some-var) :P

16:06 drobati: The swank server seems to work.

16:06 But no repl is showing up.

16:06 scottj: what does slime-connect do?

16:06 kjeldahl: No repl inside Emacs you mean?

16:06 drobati: yes

16:06 Slime repl spits back a cute message.

16:07 But no repl (it opens *slime-events* though

16:07 )

16:07 scottj: what version of slime?

16:07 gfrlog: amalloy: (= (constantly true) (comp not #{}))

16:07 scottj: recent versions are not supported

16:07 gfrlog: man if you could compare functions like that we wouldn't need to write programs anymorj

16:08 drobati: scottj: I didn't know that.

16:08 I'm pulling from the official slime repo.

16:08 building and installing myself

16:09 semperos: drobati: try adding this to your .emacs

16:09 (slime-setup '(slime-repl))

16:09 drobati: I saw that before. Let me try it again but I think it was a bit quirky.

16:10 semperos: I had slime auto-starting my repl for me, and then "one day" it just stopped, and that solved it for me

16:10 scottj: go to slime commit 605f930a or oct 15 2009

16:10 drobati: should I eval that then rerun slime-connect

16:11 semperos: should do the trick

16:11 drobati: its up

16:11 semperos: great

16:11 drobati: Works!

16:11 is the swank repl prompt user>

16:11 ossareh: morning all

16:11 semperos: is for me

16:11 drobati: perfect

16:12 Thanks semperos, kjeldahl, and scottj

16:12 semperos: np, enjoy

16:12 drobati: Will do. :)

16:13 scottj: drobati: to use slime-fancy you'll need to use an older version of slime I think. http://www.youtube.com/emailataskcom to see some of the advanced slime features

16:14 drobati: thanks for the link

16:21 TimMc: Well, that yak looks pretty well shaved: https://github.com/timmc/CS4300-HW3/blob/master/src/timmcHW3/cascade.clj

16:21 Now I can get back to my actual program. >_<

16:22 gfrlog: so if I'm implementing my own numeric type, I don't get to use the clojure.core/+ and such functions, right?

16:23 gotta use (defn add) and (defn multiply)?

16:24 Chousuke: you can define + and * in your own namespace too.

16:24 you just need to exclude the core ones

16:24 gfrlog: yeah, but then other namespaces making use of it can't...

16:24 Chousuke: can't what?

16:25 gfrlog: can't use the overridden functions

16:25 Chousuke: sure they can

16:25 all functions are namespaced

16:25 amalloy: gfrlog: c.c.generic-math

16:25 cnataren: is there a place where there are tasks that need to be done for clojure-clr?

16:25 Chousuke: what you can not do is augment the clojure arithmetic operators :/

16:25 gfrlog: Chousuke: and regardless, my implementations would need to use the core ones; so it'd be sticky

16:26 Chousuke: gfrlog: you can reimport them namespace-qualified, it's not that hard :)

16:26 the use them as core/+ etc.

16:26 gfrlog: yeah

16:26 is there some reason arithmetic isn't done as a protocol?

16:26 Chousuke: speed

16:26 stuartsierra: Does `lein test` run with dev-dependencies?

16:26 abedra: technomancy, is there a way to get "test" dependencies in lein?

16:27 Chousuke: also I guess JVM integration/historical reasons

16:27 gfrlog: stuartsierra: does for me I'm pretty sure

16:28 I'd say I'm completely sure, but I think you wrote a book about clojure or something, so that puts an upper limit on my sureness

16:28 stuartsierra: I wrote a book about Clojure, not lein.

16:28 gfrlog: I didn't write a book about lein

16:29 stuartsierra: And I don't intend to.

16:29 gfrlog: I infer from having written a book about clojure that you've used lein more than me

16:29 stuartsierra: No, I use Maven.

16:29 gfrlog: okay, my sureness is rising then

16:29 let's say I'm sure

16:31 amalloy: c.c.generic.math-functions seems to specifically exclude arithmetic... is there some reason the arithmetic functions weren't defined as multimethods in the first place?

16:31 abedra: gfrlog turns out it does

16:31 gfrlog: abedra: cool, thx

16:31 amalloy: gfrlog: sorry, i always get these two confused: http://richhickey.github.com/clojure-contrib/generic.arithmetic-api.html#clojure.contrib.generic.arithmetic/*

16:32 gfrlog: aw man I missed than 5 lines above the other one

16:32 the question still stands though

16:41 amalloy: gfrlog: performance

16:42 multimethods would slow the bejeezus out of the huge majority of apps that don't need to override +

16:42 gfrlog: I guess clojure.core/+ can be redeffed manually anyhow, right? perhaps to the c.c.generic.arithmetic versions?

16:43 is that a disastrous idea?

16:45 brehaut: gfrlog: dont redefine it; refer-clojure :exclude it out of the way, and use :only the one from c.c.g.a

16:46 gfrlog: brehaut: yeah...I was thinking I'd get the benefit of the operators working anywhere in the app, but I guess being explicit is bester

16:47 and won't slow down random other libs that don't need it

16:47 brehaut: redefining this is pretty non-idiomatic clojure i think

16:47 yup

16:50 gfrlog: ,(let [do 12, if 19] (+ do if))

16:50 clojurebot: 31

16:51 brehaut: ever looked at PL/1 ?

16:51 gfrlog: nope

16:51 brehaut: IF IF THEN THEN ELSE ELSE is approximately valid code

16:51 gfrlog: that sounds useful

16:51 brehaut: keywords were explicitly not reserved

16:52 it was an early example of overengineering

16:52 i think it might have had something to do with multics

16:53 amalloy: gfrlog: ##(let [do 10 if 40] (do if))

16:53 sexpbot: ⟹ 40

16:54 gfrlog: amalloy: Okay what the heck.

16:54 amalloy: special forms are only special in the function position

16:55 gfrlog: and special forms are always special in the function position?

16:55 that's the part I didn't expect

16:55 amalloy: yes

16:55 &(let [do 10 if 40] (if do 5))

16:55 sexpbot: ⟹ 5

16:55 gfrlog: right

16:56 apparently you can't let reader macros though

16:57 amalloy: gfrlog: not sure what you mean, though either way you're right

16:57 gfrlog: I mean

16:57 ,(let [' 15] (+ 489 '))

16:57 clojurebot: Unmatched delimiter: )

16:59 amalloy: i'm not sure that counts as a reader macro, but maybe. it doesn't seem surprising to me: you can't let [ as a local either

17:00 gfrlog: yeah I don't know what I was thinking really

17:00 amalloy: the clojure cheatsheet says it's a reader macro

17:00 and the clojure cheatsheet has never let me down

17:01 amalloy: okay. i thought the name "reader macro" was reserved for things starting with #, but i seem to be wrong

17:01 brehaut: more importantly i think http://clojure.org/reader calls it a reader macro too

17:02 gfrlog: I assumed that any syntax that wasn't parentheses was a reader macro

17:02 but they don't list map literal or set literals etc, so I'm confused

17:03 brehaut: gfrlog: a map literal becomes a map in the AST, a ' becomes a list

17:04 excuse the fuzzy use of AST

17:04 gfrlog: brehaut: I would have expected that a map literal gets translated into a call to (hash-map)

17:04 maybe that's less efficient though

17:06 brehaut: gfrlog: but maps and vectors have meaning for evaluation, so you dont want to turn them into lists to be created at runtime

17:07 gfrlog: that is a terribly good point

17:07 brehaut: (again, sorry for the overly impress wording. im failing to express myself right)

17:07 nickik: Why not, works in CL :)

17:07 brehaut: man i fail at words today

17:08 gfrlog: since #{} is not a reader macro either, presumably we could use sets for stuff

17:08 brehaut: overly imprecise wording

17:08 gfrlog: ,(let [#{a b} #{1 3}] (+ a b))

17:08 clojurebot: java.lang.Exception: Unsupported binding form: #{a b}

17:08 gfrlog: I support that binding form

17:08 brehaut: i dont think we need to get into a common lisp / clojure debate thanks all the same

17:09 gfrlog: (let [[a b] #{"I wish" "this worked"}] a)

17:09 ,(let [[a b] #{"I wish" "this worked"}] a)

17:09 clojurebot: java.lang.UnsupportedOperationException: nth not supported on this type: PersistentHashSet

17:09 nickik: I didn't want a debate it was just a fun anecdot

17:09 gfrlog: nickik: While I see your point, I respectfully disagree.

17:10 amalloy: &(let [[a b] (seq #{"I wish" "this worked"})] a)

17:10 sexpbot: ⟹ "this worked"

17:10 gfrlog: nevermind that statement was probably more confusing than funny

17:11 amalloy: Yep, that's what I ended up doing, all over my code...

17:12 brehaut: gfrlog: there is little to gain from using sets in forms though

17:12 the binding form is a maybe

17:13 gfrlog: brehaut: I know. There's just fun.

17:13 add some randomness to which variable gets which value

17:13 brehaut: hah

17:13 indeed

17:14 amalloy: it makes some sense for a sorted-set though

17:14 brehaut: amalloy: sure, but there is no literal, so it would be a bit awkward for forms

17:14 gfrlog: no literal _yet_

17:14 brehaut: hah

17:15 #>{1 3 2}

17:15 gfrlog: I don't think that's beatable

17:15 TimMc: brehaut: Why not #<{1 2 3} ?

17:15 brehaut: why not indeed

17:15 i think they are both less good than

17:15 #{< 1 2 3} or #{> 1 2 3}

17:16 gfrlog: augh

17:16 TimMc: ,>

17:16 clojurebot: #<core$_GT_ clojure.core$_GT_@1160709>

17:16 brehaut: and {> 1 :a 2 :b}

17:16 amalloy: brehaut: that form is evil

17:16 TimMc: brehaut: < is already a symbol

17:16 gfrlog: ,(let [<{ "party-hat"] (println "I'm wearing my" <{))

17:16 clojurebot: Unmatched delimiter: ]

17:16 brehaut: TimMc: so is >

17:17 TimMc: brehaut: As in, having it inside the braces is ambiguous.

17:17 brehaut: so is outside

17:17 TimMc: ,{< :a 1}

17:17 clojurebot: java.lang.RuntimeException: java.lang.ArrayIndexOutOfBoundsException: 3

17:17 brehaut: because then its not consistent with maps

17:17 its ambigous for maps both ways

17:17 TimMc: Outside with a # in front, it isn't ambiguous.

17:18 gfrlog: we need a syntax for queues too

17:18 brehaut: and if the sorted-map and sorted-set literals arent consistent, someone would need to be punched in the throat

17:18 TimMc: Hmm, sorted map...

17:18 brehaut: ,(sorted-map 1 :b 4: a :2 :d)

17:18 clojurebot: Invalid number: 4:

17:19 brehaut: hah whoops

17:19 ,(sorted-map 1 :b 4 :a 2 :d)

17:19 gfrlog: is not, I counted to 4: this morning

17:19 clojurebot: {1 :b, 2 :d, 4 :a}

17:19 gfrlog: oh man I think I've spent most of the day in irc

17:20 make sure you guys work out a syntax for finger trees too

17:20 brehaut: not everything needs a literal :P

17:22 amalloy: but brehaut, then how could anyone use my new racecar-type objects in a macro?

17:22 brehaut: amalloy: they can go use perl and write a text munging macro ;)

17:22 amalloy: #<==]blue should be added to clojure.core

17:22 for rocket ships with colors

17:23 brehaut: i dont tihnk you should force one colorspace on the definittion of colors

17:23 nickik: Are finger trees going to be 1.3?

17:23 clojurebot: excusez-moi

17:24 brehaut: we need to be able to define colors using rgb, bgr, cymk, X,Y,Z, X',Y',Z', pantone and css

17:25 amalloy: brehaut: why stop there? let's add color gradients

17:26 brehaut: now i understand why CL extensible reader macros are a bad idea :P

17:32 jweiss_: i hate to bring this up, but the "Latest News" section at http://clojure.org is not new at all

17:33 I think the newest item there is 6 months old or more

17:33 brehaut: there is a new piece of clojure the language news?

17:34 jweiss_: i only mention it because there are people I'm trying to sell clojure to, they notice nothing changes there, and they tend to think the language is not thriving which is not true

17:34 brehaut: isn't there?

17:35 brehaut: 'work continues on 1.3' every day is pretty uninformative news

17:35 compare it to python.org/news/

17:36 major releases, major cons, books about the language

17:36 if you want to see the nitty gritty then dev.clojure.org is a hive of activity

17:37 Chousuke: the dev page doesn't look superactive either to be honest. I have no idea where all the stuff is happening.

17:38 jweiss_: brehaut: i guess i'm saying it's better to redefine "news" to include smaller items

17:38 than to have the page go untouched for so long

17:38 brehaut: jweiss_: personally i'd rather people worked on the language than the news page is all im saying

17:38 jweiss_: i agree - that's why i hated to bring it up.

17:39 maybe the news page is not necessary

17:39 i mean, what good is the announcement that 1.1 is released?

17:39 brehaut: if you want mroe noisy general community news, the ML, dev ML, planet.clojure.in, disclojure.org all provide a huge range of stuff

17:40 jweiss_: brehaut: i'm not saying this because i have difficulty finding news

17:40 * amalloy updates to 1.1 asap

17:40 jweiss_: there's plenty of other sources

17:40 brehaut: jweiss_: i just dont see how you could invent more news for clojure.org

17:40 jweiss_: i'm just saying that if the official site has a news section, it should contain actual news :)

17:40 not links that are 6 months to 2 years old

17:41 brehaut: so you would rather it was empty?

17:41 or had one item

17:41 drobati: I'm not sure what I'm doing wrong with slime. But I've got a file that is connected to slime, with a -main in it. I've C-c C-k, but am failing to call the function in the repl.

17:41 jweiss_: yes. having it gathering dust like that is a little embarrassing for the language. makes it appear that it is not being actively worked on and used (even though that is not true)

17:41 drobati: I'm extremely new to this, so I know I'm doing something wrong.

17:42 jweiss_: brehaut: i don't want to be one to complain and not offer to help so i'd update the news section at least occasionally if someone let me :)

17:42 amalloy: drobati: is your repl prompt in the right namespace?

17:42 drobati: user>

17:42 do i have to apply a ns to it?

17:43 I've seen something about it somewhere.

17:43 I think in the videos someone linked me earlier.

17:46 amalloy: drobati: to call a function from your foo namespace, your repl should be in that namespace (with ns foo)

17:47 drobati: thanks

17:47 didn't understand that

17:50 raek: (in-ns 'the-ns) is safer than (ns the-ns), since it wont't auto-refer clojure.core vars

17:50 Stavros: hello!

17:51 how can i retrieve the second-to-last element from a vector?

17:51 raek: (nth v (- (count v) 2)) ?

17:51 Stavros: oh, isn't there a sort of reverse-nth?

17:52 raek: well there is. (second (rseq v))

17:52 Stavros: i see, thanks

17:53 raek: traversing the vector backwards has linear time complexity

17:53 nth is always constant time* for vectors

17:53 Stavros: i only want two elements, so that's fine

17:54 drobati: (in-ns 'name.space) worked. Thanks raek and amalloy.

17:55 raek: drobati: in case you use Emacs: you can press C-c M-p in the source buffer to switch to that namespace

17:55 drobati: Thank you for that binding.

17:55 amalloy: Stavros: ##(peek (pop [1 2 3 4 5]))

17:55 sexpbot: ⟹ 4

17:56 Stavros: amalloy: ah, thanks

17:57 raek: the readme of swank-clojure lists many *really* useful bindings. I recommend trying them if you haven't seen them

18:02 drobati: raek: I think I glanced through it on github.

18:02 Well the bindings part.

18:33 brehaut: is there a function that takes a seq and a predicate and returns [(take-while s) (drop-while s)]

18:33 and i forgot the pred in that expression

18:36 its called span in haskell

18:37 dnolen: ,(group-by even? [1 2 3 4 5 6 7 8 9 0])

18:37 clojurebot: {false [1 3 5 7 9], true [2 4 6 8 0]}

18:38 dnolen: brehaut: ^ ?

18:38 brehaut: dnolen: not quote

18:38 (span even? [2 4 5 6 7 8]) -> [[2 4], [5 6 7 8]]

18:38 hypothetically

18:40 sattvik: ,(split-with #(< % 5) (range 10))

18:40 clojurebot: [(0 1 2 3 4) (5 6 7 8 9)]

18:40 danbell: ,(split-with even? [2 4 5 6 7 8])

18:40 clojurebot: [(2 4) (5 6 7 8)]

18:40 brehaut: ah excellent. thanks!

18:50 danbell: anyone feeling charitable and want to explain to me why swank-clojure is both an elpa package and a lein plugin?

18:51 I'm 99% certain I'm confusing old blog posts with the current Way To Do Things

18:54 dnolen: danbell: I think swank-clojure in ELPA is just the machinery for the protocol, the client so to speak. the swank-clojure.jar is the server and it needs to be on the classpath of your current project. might be wrong tho.

18:54 danbell: dnolen: thx, but then what's slime for?

18:55 dnolen: SLIME is the mode.

18:55 danbell: ah

18:56 gotcha, thx

18:58 dnolen: danbell: http://bc.tech.coop/blog/081209.html, nice graphic describing the relationship.

19:00 danbell: where does clojure-mode fall in there?

19:03 dnolen: danbell: clojure-mode is just syntax-highlighting and indentation really.

19:03 danbell: ah

19:03 the pieces are falling into place

19:04 ok, thanks a lot

19:04 was banging my head there

19:04 dnolen: it's all pretty confusing. crazed Lispers.

20:34 amalloy: brehaut: split-with is definitely the way to go, but there's also http://clojuredocs.org/clojure_contrib/clojure.contrib.seq/separate if you want something slightly different

20:34 brehaut: amalloy: cheers

21:11 TimMc: I wrote a program state dependency manager that allows you to (lazily?) propagate recomputations through your application's state: https://github.com/timmc/CS4300-HW3/blob/master/src/timmcHW3/cascade.clj

21:12 Basically, you give it a DAG with a "cleaner" function at each vertex. When you mark a node dirty, that propagates out to all dependant nodes, transitively.

21:14 When you call clean on a node, it cleans all the dirty dependency nodes, then calls the node's own cleaner thunk (which does something in your app) and returns the new state with the nodes marked clean.

21:14 1) Does anybody else find this useful or interesting? 2) If so, what should I call it?

21:15 amalloy: TimMc: sounds neat. i don't know what i'd find it useful for

21:15 TimMc: I wrote it for a graphics program.

21:16 Use case: The user hits undo. Toolbar buttons need to be en/disabled, undo/redo menus change state, canvas is redrawn, etc.

21:16 amalloy: i wonder how you discover which nodes to call clean on. you can't call clean on the root node, because it has no dependents

21:16 TimMc: I got tired of debugging all these state recomputation cascades every time I added a feature.

21:17 amalloy: https://github.com/timmc/CS4300-HW3/blob/master/src/timmcHW3/core.clj#L446 <-- I created an :all node that depends on :gui and :painting, each of which depends on several other things.

21:17 So, you can have logical nodes that have nil cleaners.

21:18 Checking if a given node is clean is pretty much a constant time operation.

21:20 brehaut: amalloy: the ? macro to the rescue

21:20 amalloy: brehaut: yeah?

21:20 brehaut: im debugging mess of a tokenizer

21:21 amalloy: yeah, debugging messes is the use case :P

21:21 brehaut: yes :)

21:26 TimMc: The ? macro?

21:26 amalloy: TimMc: something i gisted a while ago

21:27 brehaut: https://gist.github.com/c93c37345c49c47dcfa2

21:28 * amalloy always laughs when he sees '~'

21:28 brehaut: what does it do ?

21:29 amalloy: brehaut: it's not a special operator or anything. it "just" quotes the result of unquoting (quote x)

21:29 brehaut: ohright

21:29 haha

21:29 amalloy: &`[x '~'x]

21:29 sexpbot: ⟹ [clojure.core/x (quote x)]

21:30 TimMc: I'm struggling to read this thing.

21:30 amalloy: i guess more apt would be ##`[x 'x '~'x]

21:30 sexpbot: ⟹ [clojure.core/x (quote clojure.core/x) (quote x)]

21:30 TimMc: I need to play with macroexpand-1 a bit.

21:32 '~' = quote unquote quote?

21:32 amalloy: yeah

21:33 TimMc: So that's... (quote (unquote (quote x)))

21:33 amalloy: ie, it's the same as ', except that you want to leave the syntax-quoting context and enter a regular-quoting context

21:33 brehaut: amalloy: you'll be happy to know i resisted the urge to use regexps to write this parser

21:36 joshua__: Is it possible to execute another Clojure program from within a Clojure program? I have a list of items in a queue and a program for processing that list of items. I have a separate program which adds items to the queue and I want to give that program the ability to say, "process the queue if it not already being processed."

21:37 One way to handle this that I've considered is making a cron script that runs the first program every few minutes.

21:38 (note the processing is scraping a website, the separate program is a website that allows you to add items to the queue)

21:38 brehaut: joshua__: why is the consumer not blocking on reading the queue

21:39 joshua__: brehaut, I don't understand?

21:39 brehaut: joshua__: are you familiar with the idea of blocking?

21:40 amalloy: joshua__: he suggests having the processing program always be in "processing mode", and wait if there's nothing to do

21:40 joshua__: Oh... I hadn't even considered that options. That sounds like the way to do it.

21:41 brehaut, my understanding of blocking is that it means that one program can't reach the resources that another program is using.. am I way off?

21:41 amalloy: joshua__: yeah, you are

21:41 joshua__: Goes off to read wikipedia, unless you guys have better links.. yeay learning

21:42 amalloy: i'm having a surprisingly hard time finding a good link

21:42 joshua__: Oo. I think I was confusing blocking with locking..

21:44 amalloy: joshua__: amusingly, the best i could do is an msdn article: http://msdn.microsoft.com/en-us/library/aa365683%28v=vs.85%29.aspx

21:50 ah, or http://www.makelinux.net/ldd3/chp-6-sect-2.shtml

21:53 TimMc: amalloy: I don't think I'm ready to understand the inner workings of macro expansion, namespaces, and symbols yet. I'll leave that ? macro for when I am.

21:54 amalloy: TimMc: wise words

21:54 brehaut: amalloy: want a code improving challenge?

21:54 amalloy: oh noes. sure

21:54 brehaut: hah

21:54 https://github.com/brehaut/ring/blob/master/ring-core/src/ring/middleware/accept.clj

21:54 its a tokenizer for the spec of 14.1 of http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.41

21:55 amalloy: brehaut: s/seperat/separate. am i done yet? :)

21:55 brehaut: hah you dont have to do anything

21:56 but yse, i cannot spell

21:56 amalloy: (def token-char? (complement illegal))

21:56 brehaut: hah yes

22:00 joshua__: Alright, so blocking basically means that you put a thread to sleep until some event occurs that lets you know you can now deal.

22:00 brehaut: joshua__: effectively, but you shouldnt be putting the thread to sleep yourself

22:01 joshua__: brehaut, alright, how would you put it to sleep if your not allowed to put it to sleep yourself?

22:02 brehaut: your queue should implement a blocking read

22:02 amalloy: joshua__: ##(read)

22:02 sexpbot: java.lang.Exception: EOF while reading

22:02 brehaut: you jsut read from the queue

22:02 amalloy: i'd drop the cond in quoted-string and try to combine the (recur) clauses into one since they're pretty similar, plus lift some of the repetition into an enclosing let; make it more like (if (empty? ...) [..] (let [next (ffirst cs) tail (drop 2 cs)] ...))

22:03 brehaut: joshua__: in clojure, lots of reference types implement blocking on deref, eg (def p (promise)) (doto (Thread. (fn [] (Thread/sleep 3000) (deliver p 1))) .start) @p

22:04 run those three in a repl one at a time

22:04 @p should pause for a couple of seconds and then return 1

22:04 thats because the promise blocks until it has a value delivered to it

22:04 amalloy: sure that makes sense

22:05 amalloy: joshua__: you read from streams (java or c++) all the time, right? like sockets, for example?

22:06 joshua__: amalloy: I've done it before, but not all the time. Only once when I made a internet capable chess game for my an end-of-semester project.

22:06 amalloy: when you do (.read sock), if there's data available, you get it immediately; if not, your process falls asleep until there is. this happens transparently to your program so you don't need to thing about it

22:07 file IO is the same: the data usually isn't available the second you ask for it, so your process falls asleep for a millisecond or two while the disk spins up

22:07 joshua__: Oh this is making a lot more sense now.

22:07 I was thinking in terms of a database I would read the queue from instead of a socket that I would send it through.

22:08 amalloy: so the most straightforward way (maybe not best) to implement brehaut's suggestion is to write your processing program as a server that listens to some local socket and pulls events out of it

22:08 the "add work" program connects to that local socket and dumps in some work

22:08 brehaut: joshua__: what queue implementation are you using?

22:08 joshua__: and than the code for submitting an item to the queue would push something into that .

22:08 brehaut, haha.. I wasn't. I was using a table in mongodb ;p

22:08 brehaut: joshua__: oh.

22:09 joshua__: brehaut, but conceptually it is a list of things to process.. ;p

22:09 brehaut: joshua__: conceptually yes, but on the other hand, there are a heap of good queue servers around

22:09 and java APIs are pretty common

22:10 joshua__: brehaut, I agree that your guys ideas are better than my way of doing it. I think I'm going to implement amalloy's suggestion unless someone wants to toss out a better approach.

22:11 brehaut: https://github.com/robey/kestrel ?

22:11 you'll learn stuff from doing it by hand with sockets

22:12 joshua__: I think that is the way I want to go in part for the learning and in part because kestrel sounds like overkill

22:14 Thanks for the help guys. Best computer science education time can buy in #clojure ;)

22:16 brehaut: no worries

22:16 amalloy: programming with birds is always overkill

22:16 brehaut: haha

22:20 $findfn [\a \b \c] true

22:20 sexpbot: [clojure.core/== clojure.core/sequential? clojure.core/reversible? clojure.core/distinct? clojure.core/boolean clojure.core/vector? clojure.core/counted? clojure.core/associative? clojure.core/< clojure.core/= clojure.core/> clojure.core/>= clojure.core/<= clojure.core/ifn? clojure.core/coll?]

22:20 brehaut: $findfn [\a \b nil] false

22:20 sexpbot: [clojure.core/keyword? clojure.core/chunked-seq? clojure.core/fn? clojure.core/not= clojure.core/nil? clojure.core/string? clojure.core/sorted? clojure.core/false? clojure.core/true? clojure.core/symbol? clojure.core/number? clojure.core/integer? clojure.core/seq? cl... http://gist.github.com/838151

22:21 brehaut: waaay to general

22:21 i fail

22:28 TimMc: $findfn [\a \b \c] true ==

22:28 sexpbot: []

22:28 TimMc: :-P

22:29 brehaut: What are you looking for, anyway?

22:30 brehaut: (every? identity [a b c])

22:30 something to test that none of the vars are nil

22:30 TimMc: or false

22:31 ,(every? (complement nil?) [\a \b "c"])

22:31 clojurebot: true

22:31 TimMc: But you want a single fn?

22:31 brehaut: TimMc: i know that they arent going to be false

22:31 TimMc: (apply and [\a \b \c])

22:32 :-P

22:32 I always forget I can't do that.

22:33 rabidsnail: Can I compile a clojure namespace to java bytecode and put it in, for example, a database? Or does bytecode have to go on the filesystem?

22:35 TimMc: Idiom/philosophy question! I'm developing this small library. Should I check for and throw exceptions on bad inputs, or should I expect relying code to give good inputs?

22:35 (Relying code will only hurt itself with bad inputs.)

22:35 brehaut: you should check for bad inputs, but throwing exceptions is debatable

22:36 amalloy: brehaut: you'd rather return nil?

22:37 brehaut: amalloy: no :P but 'exceptions' is a bit debatable

22:37 amalloy: brehaut: if you're checking for bad inputs, and not returning nil or throwing an exception, what are you doing when you get a bad input?

22:37 brehaut: pass back some sort of fault type?

22:37 gets a bit monadic though

22:38 TimMc: brehaut: They generally return nil on bad inputs anyway, just due to implementation.

22:41 brehaut: TimMc: its not too bad if the input is simple

22:42 TimMc: Maybe I'll just put validation on the main, non-recursive API calls.

22:42 Should catch most client errors that way.

22:43 brehaut: TimMc: i think c.c has some error handling librarys that make exceptions better

22:43 TimMc: I don't care about catching them, I just want to fail fast if the client is passing in bad args.

22:43 But that's good to know.

22:44 brehaut: wel if you dont care, then nil :P

22:44 rabidsnail: Is it still the case that not all of the core Clojure datastructures are serializable?

22:44 I remember that being true in 0.9

22:45 (and maybe 1.0, although I stopped using clojure around then)

22:45 TimMc: brehaut: That won

22:45 That won't make the client fail fast.

22:45 skelternet: serializable?...as in java.io.Serializable?

22:45 rabidsnail: yeah

22:46 TimMc: I know this because my own client code was passing in a bad keyword, and I was getting nil propagation tht I only detected later.

23:27 skelternet: I could ( reduce into myListOfVectorTuples myOtherListOfVectorTuples myOtherListOfVecotrTuples) to produce my desired list of all vectors, but I can't help but think there is an easier, more idiomatic and lazy way.

23:30 amalloy: skelternet: ummmm, did you ask an actual question?

23:30 skelternet: heh...lazily? sort of?

23:30 I think I expressed angst, rather than actually asked it.

23:31 spewn: skelternet: lazy-cat?

23:31 amalloy: spewn: afaik there is no reason to use lazy-cat after 1.1.0. concat is lazy

23:31 spewn: Good to know, thanks.

23:33 skelternet: I'll look at lazy-cat again. It was returning lists of lists and I was trying to unify into one large list.

23:34 or seq

23:34 spewn: skelternet: Like amalloy said, look at concat instead.

23:35 amalloy: skelternet: to glue together a list of lists into one list of all the sub-elements, (1) make sure you actually want to do it, (2) (apply concat list-of-lists)

23:36 &(apply concat [[1 2] [3 4 6] [9]])

23:36 sexpbot: ⟹ (1 2 3 4 6 9)

23:36 skelternet: Thanks! I've actually had an itch to second-guess the assumption (1)

23:38 amalloy: if you're getting the list of lists from a (map ...) or (for ...), you can generally cut out the middle man by asking that process to give you a single list to begin with

23:43 skelternet: it's a list comprehension that is feeding table names to a function that returns column definitions extracted from a remote wiki page.

23:44 I'll explore tweaking the for or the function (which I'm sure has a for in it as well)

23:46 tomoj: lazy-cat doesn't even evaluate the coll exprs until needed

23:46 I can't think of an example, but it seems like that could be useful

23:50 brehaut: "java.lang.Exception: Unable to resolve symbol: in this context (NO_SOURCE_FILE:0)"

23:50 anyone seen an error like that before?

23:52 skelternet: do you have a lone apostrophe next to a character that appears to be blank ?

23:52 joshua__: ( )

23:54 brehaut: hmm nothing like that

23:55 joshua__: I think I get errors 'like' that when I try to call a function that doesn't exist.

23:55 ,(as)

23:55 clojurebot: java.lang.Exception: Unable to resolve symbol: as in this context

23:55 amalloy: brehaut: you were doing stuff with \tab or something, right? is it possible that you have a macro that's not quoting \space properly?

23:56 brehaut: its possible…

23:56 binary chop ATM

23:57 amalloy: &(let [x (symbol \space)] `(var ~x))

23:57 sexpbot: java.lang.ClassCastException: java.lang.Character cannot be cast to java.lang.String

23:57 amalloy: &(let [x (symbol " ")] `(var ~x))

23:57 sexpbot: ⟹ (var )

23:58 amalloy: a bit comical that (symbol " ") is even allowed, but...

23:59 brehaut: ha yeah

23:59 i tihnk i have a hidden character

23:59 i removed everything and it still balked

23:59 amalloy: brehaut: i've always suspected you of having character after all

Logging service provided by n01se.net