#clojure log - Nov 22 2011

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

0:33 boborygmy: ?

1:19 callen: is anyone aware what the preferred library or mechanism for event handling/callbacks in Clojure is?

1:20 I've got a dumb loop in my code right now, and I really don't want to go through the pains required to make it non-retarded.

1:20 I found spectator, but it seems specifically wrapped around maps, oddly enough.

1:20 and it seems less like an event library and more of a signals thing for mutation.

1:23 amalloy: lamina? or just functions?

1:24 callen: amalloy: taking a look at lamina. Tbqh, something like twisted would serve my needs really well.

1:25 amalloy: basically I need to keep a socket connection alive, and start firing stuff off based on what I get.

1:25 amalloy: I might make my parsing/processing asnychronous or secondary to the main event loop for performance, but in general, I need to keep the damn socket alive and make certain stuff goes.

1:26 amalloy: twisted happens to be really good at what I described, and given that I don't know Clojure that well yet, I'm trying to force myself to do the project in clj.

1:26 amalloy: if you want *networked* event-listeners, see also aleph and the millions of message-queue impls like zeromq and rabbit. i don't know anything about any of those, but probably at least one of them is good

1:26 callen: amalloy: I was just going to say that I think Aleph is more appropriate.

1:26 amalloy: rabbitmq and zeromq are totally inappropriate for my use-case, hahaha.

1:27 amalloy: don't recommend either of those to people who don't necessarily know what they want, fyi.

1:52 tolstoy: The thing I really love about leiningen is that if I have a question, I can just read the source and actually understand it.

1:52 I mean, the files are named after the tasks.

1:52 * tolstoy is still shell-shocked from sbt 10+.

1:53 tolstoy: Just had to get that out there.

1:56 diptanuc: tolstoy: SBT is lik a dragon.

1:57 * scottj goes to look at the sbt source

1:57 tolstoy: xsbt....

1:58 the old SBT was a bit easier.

2:00 Just about every time I need to write a leiningen plugin, I write it, then look in the sample-project.clj file, and realize I didn't have to. But if I did, it's so easy.

2:01 scottj: Have you actually found which top-level dir to look in over at https://github.com/harrah/xsbt?

2:08 callen: tolstoy: I wish more stuff was written like lein.

2:10 tolstoy: callen: I find a lot of clojure stuff much more understandable than I would have thought.

2:11 callen: For instance, the docs on congomongo are slim and reading the code is not the irritating chore I thought it would be.

2:11 callen: tolstoy: I don't think it has much to do with Clojure actually, more that Clojure attracts smart people

2:11 tolstoy: and smart people write good code.

2:12 tolstoy: I could write some seriously incomprehensible Clojure if you liked.

2:12 tolstoy: I mean, do you really think it's anything other than technomancy_ that is why lein is so nicely organized?

2:12 tolstoy: you do him a disservice by attributing it to Clojure, as nice as clj is.

2:13 tolstoy: I'm sure his example inspires a lot of others.

2:15 callen: Kudos to technomancy, of course, but (as well) I do think that the whole ethos of clojure helps a lot.

2:15 brehaut: “In [OO], everything happens somewhere else.” — Adele Goldberg

2:16 tolstoy: brehaut: OO is like a rainbow when you're a kid. You keep running toward stuff, but....

2:17 callen: I hate following ravioli code.

2:33 ivan`: newbies like me might be interested to know there's now an Anki deck with the language API

4:29 Bahman: Is this code (make-writer index-file [:append true :encoding "UTF-8"]) correct to append to an output writer?

4:30 raek: what is make-writer?

4:31 brehaut: ,(use 'clojure.java.io)

4:31 clojurebot: nil

4:31 Bahman: raek: clojure.java.io/make-writer

4:31 brehaut: ,(doc make-writer)

4:31 clojurebot: "([x opts]); Creates a BufferedWriter. See also IOFactory docs."

4:31 Bahman: ([x opts])

4:31 Creates a BufferedWriter. See also IOFactory docs.

4:32 brehaut: raek: i think its used by other higher level c.j.io functions?

4:32 raek: if you want to open a writer to a file in append mode, use (io/writer index-file :append true :encoding "UTF-8")

4:32 brehaut: frinstance writer

4:32 raek: brehaut: as brehaut said, make-writer is an implementation detail of writer

4:33 (inc Bahman)

4:33 lazybot: ⇒ 1

4:33 raek: for being explicit about the encoding of the file

4:34 Bahman: raek, brehaut: Thanks. That worked.

4:35 How can I figure if I should not use a function, such as in my case 'make-writer'?

4:36 raek: good question... I guess it's hard to know in this case

4:36 writer has more docs than make-writer

4:36 and make-writer is a protocol method

4:37 these can be hints that the function is more low-level

4:37 Bahman: raek: How can you tell make-writer is a protocol method?

4:38 raek: I happened to know that :)

4:38 Bahman: Oh, I see :-) Thank you.

4:39 Raynes: Bahman: There is invisible text prefixed the name that says 'protocol method' that only experienced Clojurians can see.

4:40 Bahman: Alright Shao Lin masters...when I write my own language I'll put invisible text such as no one but myself can see :-D

4:40 Raynes: That's cheating.

7:20 kzar`: Is there a function that I can use to take a sequence and return two sequences, one with every first item, one with every other one. So for example, something like this: (? [1 1 3 4 5 6]) -> [[1 3 5] [1 4 6]]

7:24 clgv: kzar`: ##(let [s [1 1 3 4 5 6]] [(take-nth 2 s) (take-nth 2 (rest s))])

7:24 lazybot: ⇒ [(1 3 5) (1 4 6)]

7:25 kzar`: clgv: Oh shit, should have got that one. Thanks

7:25 clgv: kzar`: you'll remember next time I guess ;)

7:26 licenser: whoa up to 353 kilo tokens a second with the clojure scanner :D

7:26 clgv: licenser: what clojure scanner?

7:26 licenser: clgv: for the highlighter

7:26 clgv: which highlighter? ;)

7:27 licenser: mine ;)

7:27 clgv: github-link? ;)

7:28 licenser: clgv: https://github.com/Licenser/clj-highlight

7:28 hoeck: parsing clojure is not that hard, its a lisp at all!

7:28 kzar`: Is there a quicker way to convert a character to integer than (Integer. (str \1)), I find myself doing that a lot

7:29 (I've just defined a tiny function anyway, just wondered)

7:29 clgv: &(- (char \1) 49)

7:29 lazybot: java.lang.ClassCastException: java.lang.Character cannot be cast to java.lang.Number

7:29 clgv: &(- (int \1) 49)

7:29 lazybot: ⇒ 0

7:29 clgv: ok 48^^

7:29 dont know if thats quicker. It's directly from char to in at least.

7:29 *int

7:30 kzar`: clgv: or I guess ({\0 0 \1 1 \2 2...} \1)

7:31 licenser: hoeck: I don't talk about hard, I talk about fast

7:31 kzar`: clgv: Think your way's the best except it doesn't check the character represents a number

7:31 clgv: kzar`: thats an option as well. map lookup (potential hashfunction) vs char-conversion + subtraction

7:32 hoeck: licenser: sorry, no offense, I just meant its relatively simple to parse and therefore probably efficient as well

7:33 licenser: hoeck: well the approach is a general one, which makes it a magneitute slower since I can't just use (read …) :P

7:33 hoeck: licenser: I once wanted to write a incremental parser for sql, hoping that I could built a better autocompletion, and I initially though, 'how hard can that be, I once wrote a parser for lisp'

7:34 licenser: hoeck: I know the topic quite well, lisp is incredible simple

7:34 * licenser had his fair share of syntax highlighting ^^

7:44 clgv: licenser: customizable syntax highlighting would be great. "predicate => style" pairs :)

7:48 erluko: ,(eval (read-string (pr-str '#(123))))

7:48 clojurebot: #<Exception java.lang.Exception: SANBOX DENIED>

7:51 licenser: clgv: you can do that

7:51 erluko: Having a little trouble reading the printing of a quoted form. Quoting a #() function adds {:line 1} metadata to the body. The 1 is a java.lang.Integer. Reading turns it into a java.lang.Long, which causes a class-cast exception the compiler.

7:51 licenser: instead of style I use a token kind then you can just define styles for the kind

7:51 that way you can group multiple predicates towards one style

7:59 hoeck: for the record, the java scanner only get 54 kTokens/s

8:04 clgv: erluko: clojure 1.3?

8:04 erluko: yep

8:05 clgv: erluko: integers are always long in 1.3 - for java interop you have to cast them explicitly to Integer when calling the java method

8:06 erluko: Absolutely. The change doesn't seem to have made it to clojure.lang.Compiler.analyzeSeq()

8:10 clgv: /* in Compiler.java */ line = (Integer) RT.meta(form).valAt(RT.LINE_KEY);

8:11 ,(map class [4 (int 4) 2.2 (float 2.2)])

8:11 clojurebot: (java.lang.Long java.lang.Long java.lang.Double java.lang.Float)

8:12 erluko: clgv: Note the second term above. That makes it a little harder to work around the explicit cast in the compiler

8:17 clgv: ,erluko: the behavior of your map form is expected for the int afaik it converts to int and back again when you put it into the vector

8:17 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: Invalid token: erluko:>

8:17 clgv: oops .

8:18 ,(clojure-version)

8:18 clojurebot: "1.3.0"

8:18 erluko: Ah, of course. I needed to use (Integer.)

8:18 clgv: &(clojure-version)

8:18 lazybot: ⇒ "1.3.0"

8:18 clgv: uff no 1.2 bot here anymore

8:19 erluko: Still odd that the compiler insists that when it sees {:line X}, X must be a java.lang.Integer

8:19 -- in certain contexts

8:20 clgv: I meant ^{:line X}

8:20 clgv: do java.lang.Thread objects get garbage collected when the run method exits?

8:22 Bahman: It's probably very naive but how can I use 'byte-array'? Every time I try to use it like (byte-array 3 [1 2 3]) exceptions are thrown at my face saying Long cannot be cast to Byte.

8:25 clgv: Bahman: (byte-array 3 (map byte [1 2 3])) works. but it's not nice to have to do the conversion like that, indeed.

8:27 Bahman: clgv: AFAIK on JVM, you can't count on the exact timing of GC. But yes, when the Thread exits if there are no more refs to it, it is marked for recycling on the next GC run.

8:27 Thanks clgv.

8:27 clgv: ok. exact timing is not needed. I wasnt sure if threads might be treated special

8:28 licenser: I start to hate clojure-jack in :( for no good reason it starts or stop working with the oddest of errors :.(

8:30 erluko: licenser: does it break after a change to project.clj?

8:30 licenser: erluko: map, it told me now that it does not find lein

8:32 erluko: Can it still be found in a shell? Does 'lein swank' work in the root of your project?

8:32 licenser: perfectly


8:32 clgv: licenser: I wouldnt wonder if bash didnt find lein here since it's that foggy here

8:32 licenser: clgv: I even called /bin/bash lein to make sure it works

8:32 but I wonder why it would work 1s ago and then stops

8:33 clgv: restart^^

8:33 only emacs I mean ;)

8:33 cemerick: OT: is there any way in the github UI to just fast-forward commits from pull requests instead of creating separate merge commits?

8:33 licenser: clgv: did taht

8:38 interesting, parsing huge files is faster in a lazy mode, small files are faster in a non lazy mode

8:51 broquaint: Don't think so, cemerick.

8:52 cemerick: broquaint: that's what I thought. Bizarre. Do people not like clean commit histories? :-P

8:52 erluko: clgv: I had a bad lein plugin do that to my setup once

8:53 clgv: erluko: a lein plugin made your bash foggy? :D

8:54 broquaint: Not the github guys at least, cemerick ;)

8:54 erluko: clgv: I think that was the gin. :D

8:54 licenser: have you tried lein clean?

8:55 licenser: erluko: it just started to work again , I have no clue why

8:55 Bahman: licenser: Have you appended the path to lein to PATH in .bash_profile?

8:55 licenser: Bahman: lein is in my global path

8:56 Bahman: Some X programs only regard variables defined in .bash_profile not .bashrc

8:58 clgv: Bahman: usually .bash_profile is loading .bashrc if it exists ;)

8:58 erluko: clgv: re Integer issue. Turning on *print-dup* makes (eval (read-string (pr-str '#(123)))) work again

8:59 w/out dup: (fn* [] ^{:line 1} (123)) w/dup: (fn* [] ^#=(clojure.lang.PersistentArrayMap/create {:line #=(java.lang.Integer. "1")}) (123))

8:59 The magic is in (java.lang.Integer. "1")

9:00 Bahman: clgv: I know...it's sourcing .bashrc as the first line but I have run into this weird problem before. It might be worth a try.

9:00 clgv: oh ok. I always used *printdup* when experimenting with read and writing clojure forms. so I didnt notice that.

9:23 Borkdude: I am trying out Clojure from the console instead of emacs, to prepare some assignments for students.

9:24 TimMc: cemerick: My main objective is to ensure that every commit leaves the tree in a buildable state where the same or fewer tests fail. I also like to commit features + tests + doc together.

9:24 Borkdude: I was wondering, what is jline supposed to enhance? I see no difference

9:24 TimMc: cemerick: Beyond that, I try to make commits as small in scope as possible, in order to make merges easier.

9:24 cemerick: TimMc: Of course, but if a changeset doesn't require a merge commit at all, why add one?

9:24 TimMc: a merge commit?

9:25 joegallo: Borkdude: ability to hit up and get back the previous line is the primary thing that i noticed

9:25 cemerick: TimMc: Yeah, that was my original gripe re: github pull requests

9:25 the web UI produces a merge commit even if one isn't necessary

9:25 Borkdude: joegallo: the normal clojure repl does that already

9:26 fliebel: Any idea how I can tell lein to check the maven repos? It just bombs out immediately.

9:27 TimMc: cemerick: Huh, haven't seen that.

9:27 cemerick: I've never seen a pull request *not* produce a merge commit.

9:27 joegallo: Borkdude: not for me, it doesn't

9:27 cemerick: Whereas if I do the pull on the command line, I get a clean history.

9:27 joegallo: how are you running it?

9:28 TimMc: cemerick: Ah, I see. I've never done collab using github.

9:28 Borkdude: joegallo: I just downloaded the jar and hit "java -jar clojure-1.3.0.jar"

9:28 joegallo: and i as well

9:29 what terminal and shell are you using on what os? is it possible that you're benefitting from an external feature provided by something else?

9:30 i'm using iterm2 on osx to ssh into a linux virtual machine

9:30 Borkdude: joegallo: hmm, I now found out it works in Windows but not in OS X and jline makes a difference there

9:31 joegallo: iTerm2 here also on OX

9:31 OSX

9:31 TimMc: cemerick: Aha! I misread your question that started this whole thread. >_<

9:32 Borkdude: is there smth which enhances the repl with paren matching and nice colors?

9:32 TimMc: For some reason I thought it was about rebasing groups of commits.

9:32 cemerick: nah

9:32 but I do always rebase my work into one or two commits so as to eliminate extraneous chaff :-)

9:33 Borkdude: cemerick: I know how that works now ;)

9:33 TimMc: I think I was remembering an earlier comment of yours to that effect.

9:36 hugod: cemerick: you probably know this already, but you might find http://notes.envato.com/developers/rebasing-merge-commits-in-git/ interesting

9:41 cemerick: hugod: that's a great post about --rebase

9:56 jweiss: i'm seeing some strange behavior here, is it possible for a lazy seq to "escape" a try/catch in which it's calculated? eg (let [x (try (calc-seq) (catch Exception e e))] (do-other x)) and do-other throws an exception from calc-seq?

9:56 Chousuke: jweiss: yes.

9:56 jweiss: lazy seqs generally do no calculation until you consume items from them

9:57 melipone: how do you write wrapping macros like with-out-writer in duckstreams?

9:57 jweiss: Chousuke: wow really? but when it is calculated, shouldn't it still be done in the context of the try/catch?

9:57 Chousuke: jweiss: no

9:57 jweiss: Chousuke: ok, i was hoping i'd missed something. so what's the proper way to do what i want?

9:57 Chousuke: jweiss: if you consume a value from it outside a try block, you can't catch the exception if the generation throws one

9:58 jweiss: just force the whole seq with doall?

9:58 Chousuke: either that, or wrap the code where the seq is used in a try block

9:59 or try to make it so that it doesn't throw exceptions

9:59 eg. you can catch the exception when the item is generated and just not return anything, thus ending the sequence

10:00 it might not be a good solution for your problem but it is an option :)

10:00 jweiss: Chousuke: ok thanks for the info, i had a hard time believing that was really what was happening, thx for confirming :)

10:01 Chousuke: jweiss: lazy seqs are a bit unintuitive the first time you encounter it; and I guess dynamic scope in general.

10:01 melipone: that question is a bit vague. Have you looked at how with-out-stream is implemented?

10:02 er, out-writer

10:03 clojurebot: def with-out-writer

10:04 hm :(

10:45 chouser: I'd like to use lein's checkouts dir to point to a couple non-lein projects (clojure itself and another with a pom.xml)

10:46 Should I give up now, or is it possible perhaps by adding stub project.clj's to those projects?

10:52 cemerick: chouser: that's all that's required AFAIK. The child projects' source, compile, and resources paths will be added to the parent's classpath for e.g. REPL interactions, compilation, etc.

10:54 mdeboard: Is anyone here doing high-volume crawling/scraping with Clojure?

10:57 chouser: cemerick: perfect, thanks.

11:04 fliebel_: How long does it usually take from a hudson build to availability in maven central?

11:10 cemerick: fliebel_: can be a number of hours, depending on central's promotion schedule that day, and the phase of the moon

11:10 :-P

11:10 Outer bounds I've seen are 20 minutes - 24 hours.

11:11 fliebel_: cemerick: I can't see the moon, it's to foggy here.

11:12 cemerick: tea leaves or chicken entrails will do in that case

11:12 fliebel_: oh, we have chickens... *looks up what entrails are*

11:13 uhm, that's not going to work either. Our chickens are enclosed by fethers. Let's have some tea instead.

11:15 Borkdude: cemerick: I decided to give ccw a spin

11:16 fliebel_: Borkdude: good pun :)

11:16 Borkdude: when I right-click a .clj file and select Run As Clojure Application (preload file) I do get a REPL but it doesn't do anything with my input

11:17 fliebel_ :)

11:17 chouser: cemerick: works perfectly, thanks again.

11:18 cemerick: chouser: thank technomancy :-)

11:18 Borkdude: you mean it's not loading the file you selected?

11:18 clgv: Borkdude: what is your file like?

11:18 Borkdude: CTRL+ALT+S on the file will definitely load its content in the repl

11:19 Borkdude: file is like this: https://gist.github.com/1386029

11:19 cemerick: FWIW, I greatly prefer to start a "project-level" REPL with nothing preloaded, and then I load files in as I like.

11:19 Borkdude: clgv: is S the super key or the capitalized letter s?

11:19 clgv: s

11:19 Borkdude: cemerick: I find that acceptable, but such a repl still doesn't do anything

11:20 clgv: Borkdude: well you will have to call the hello function to see something happening in your repl

11:20 cemerick: Borkdude: what do you mean by "doesn't do anything" — is helloworld/hello not defined when the REPL comes up?

11:20 Borkdude: cemerick: clgv I can just type whatever I want in the repl

11:20 but no evaluation what so ever

11:21 I upgraded btw

11:21 clgv: Borkdude: then your nrepl server probably died

11:21 Borkdude: not a fresh install

11:21 but that should work right?

11:21 cemerick: Borkdude: you hit return and it just adds a linebreak, you mean?

11:21 Borkdude: cemerick: yes

11:21 cemerick: Ctrl+Enter evaluates the REPL input :-)

11:22 clgv: kill that repl view and stop everything on the console view and refresh the project

11:22 Borkdude: ah wtf ;)

11:22 cemerick: (maybe Cmd+Enter on Mac by default, I've long forgotten what the defaults are)

11:22 Borkdude: that's it

11:22 clgv: yeah Enter only evaluates if you are at the end of the input

11:22 Borkdude: they should have put sound to that getting started video ;)

11:22 cemerick: clgv: not even that on the latest builds

11:23 clgv: cemerick: there is a recent update?

11:23 Borkdude: clgv: what do you mean, end of input? you can always type one extra character?

11:23 cemerick: yeah, 0.5.0

11:23 clgv: uuuuh

11:23 cemerick: clgv: handling enter like that was interfering with accepting completion suggestions, etc.

11:23 Borkdude: cemerick: does it do autocomplete or suggest what parameters my hello functions wants?

11:23 clgv: cemerick: yeah that sucked sometimes

11:24 Borkdude: function

11:24 cemerick: Borkdude: Yes, completion is available in the REPL, and parameters and documentation is given in the completion popup.

11:24 Borkdude: cemerick: Cmd+Enter on OS X

11:25 cemerick: where should I see this popup

11:25 and when

11:25 cemerick: If you type (helloworld/ …and then request completion (probably Ctrl+Space by default) you'll get suggestions (or an immediate completion if there's only one match)

11:26 clgv: ah a block comemnt is in as well? great

11:26 cemerick: docs and parameters are not (yet) offered if the function position symbol is already in place

11:26 Borkdude: The getting started video is quite out of date AFAIK.

11:27 Borkdude: cemerick: what is a good resource to get started then

11:27 clgv: I would love if CCW would also provide autocompletion without an active repl

11:27 Borkdude: cemerick: ah ctrl+space works, I am so used to tab ;)

11:28 cemerick: Borkdude: you can rebind all of the defaults to your preferred shortcuts in the preferences FYI

11:28 Borkdude: cemerick: yes, ctrl+space is fine, it's just that I'm so used to emacs ;

11:28 )

11:29 cemerick: clgv: There has to be a running environment of some kind to provide any kind of autocompletion. We're hoping to automatically take care of one in the background so you don't have to start a REPL yourself though.

11:29 Borkdude: cemerick: is there some documentation for people to get started?

11:29 clgv: cemerick: yes, thats what I thought how it can be done^^

11:29 Borkdude: cemerick: no outdated stuff

11:30 cemerick: or are these things all I need to know? ;)

11:30 clgv: cemerick: I would also love a short "get potential CCW developers started" guide for CCW. exploring the source on your own was kinda futile for me.

11:33 cemerick: Borkdude: Actually, that screencast is more up to date than I thought. There's http://code.google.com/p/counterclockwise/wiki/Documentation which is in decent shape, and if you choose Help > Help Contents, you should see a Counterclockwise group in the sidebar.

11:33 Borkdude: cemerick: another question (just firing away as usual..) how do I do eval-last-sexp kind of things in cCW?

11:33 cemerick: Beyond that, ping me or the ML, which is well-trafficked.

11:34 Borkdude: Ctrl+up / Ctrl+down

11:34 Borkdude: cemerick: say I want to re-evaluate the hello function

11:34 cemerick: or maybe Alt+up / down, I forget the defaults

11:35 Borkdude: alt-up is transpose-line so to see

11:35 duck1123: I believe it's Control up

11:35 but it has a conflict on OSX

11:35 Borkdude: ctrl-up just moves the cursor to the sexp above

11:35 cmd-up I mean

11:35 duck1123: That's what I was told anyway when I had the same question

11:35 Borkdude: ctrl-up brings up mission control

11:36 clgv: the java ThreadPoolExecutor with a bounded queue throws an RejectedExecutionException - can I try to convince it to just freeze the submitter until there is space in the queue again?

11:36 cemerick: mission control?

11:36 Borkdude: cemerick: an overview of all open applications

11:36 cemerick: in the current space

11:36 cemerick: ah, right

11:37 duck1123: I think you have to either disable that, or find out if you can rebind it

11:37 cemerick: Borkdude: There's a long-standing issue on OS X where some default keybindings conflict with OS X system stuff. The workaround is to either disable spaces, or rebind the expression history keybindings to something else.

11:37 e.g. Preferences > Keys — filter by "REPL"

11:38 tcj: I've got a really basic compojure question: How do I pass multiple values to a hiccup function that renders HTML? I'm using compojure. My handler function needs to pass a sequence of maps and a number. Right now, I have the handler passing the sequence of maps to the hiccup function, but I'm not sure the best way to pass multiple values. I'm thinking of using juxt to solve this. I'm not sure...

11:39 ...if this is even an asnwerable question...

11:39 Borkdude: cemerick: I think I found it in the documentation: cmd-shift-x

11:39 cemerick: Borkdude: oh, you wanted to evaluate the current top-level expression in an editor!

11:40 Borkdude: cemerick: yes

11:40 duck1123: tcj: if you want to render multiple hiccup elements, wrap them in a (list )

11:40 cemerick: I interpreted "eval-last-sexp" as command history recall in the REPL :-)

11:40 Borkdude: cemerick: actually the last sexp, so like (do (first-thing)| (second-thing)) -> eval-last-sexp should evaluate (first-thing)

11:42 cemerick: Borkdude: No corollary for that in ccw. Cmd-Shift-X will evaluate the current top-level or the selected region.

11:42 Borkdude: cemerick: that's good enough for my students ;)

11:58 clgv: how do I convince clojure/java that it can determine the right constructor. those are up for selection:

11:58 [ 1] <init> (int,int,long,TimeUnit,BlockingQueue,RejectedExecutionHandler)

11:58 [ 2] <init> (int,int,long,TimeUnit,BlockingQueue,ThreadFactory)

11:58 type hint ^RejectedExecutionHandler seems not to work

11:59 without the last handler it knows exactly what constructor to choose

12:02 humm using the setter afterwards is a workaround - but it is really strange that typehinting does not work

12:09 jcromartie: Korma: I WANT TO BELIEVE

12:09 kzar`: Can you convert an exception to a string?

12:09 jcromartie: (try (/ 1 0) (catch Exception e (str e)))

12:09 &(try (/ 1 0) (catch Exception e (str e)))

12:09 lazybot: java.lang.SecurityException: You tripped the alarm! catch is bad!

12:09 jcromartie: oh yeah

12:09 ...

12:10 TimMc: => "java.lang.ArithmeticException: Divide by zero"

12:15 kzar`: jcromartie: Cool OK, that easy eh?

12:15 assumed it was harder!

12:16 jcromartie: str just calls .toString on most objects

12:16 &(map str [1 2 3 '(4 5) {:x :y}])

12:16 lazybot: ⇒ ("1" "2" "3" "(4 5)" "{:x :y}")

12:16 jcromartie: &(map str [(Object.) (Exception. "hi")])

12:16 lazybot: ⇒ ("java.lang.Object@95bf88" "java.lang.Exception: hi")

12:37 Borkdude: cemerick: does it make sense that I don't get suggestions for (String/ <ctrl-space> ?

12:57 hiredman: the implementation of drop-last is too cute by half

13:01 TimMc: hiredman: Oh man, that's... kind of absurd.

13:02 (That's https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L2526 for those of you following along at home.)

13:04 ejackson: TimMc: hiredman: sneaky, sneaky.

13:04 TimMc: So, what is that illustrating... commutativity of addition?

13:04 associativity?

13:05 ejackson: neither, I don't think.

13:07 TimMc: Taking (first) of a drop-last should then realize roughly the first n elements, yeah?

13:09 &(take 5 (drop-last 20 (range)))

13:09 lazybot: ⇒ (0 1 2 3 4)

13:09 TimMc: Very cute.

13:55 * TimMc impatients for Conj videos

14:18 TimMc: cemerick: Are you saying that you'd prefer the diagram on the right in http://nvie.com/img/2010/01/merge-without-ff.png or am I completely misunderstanding you?

14:19 amalloy: TimMc: for those of us who aren't caught up on the backlog, what did cemerick say (or, a link to where he said it)?

14:24 TimMc: &(range)

14:25 lazybot: java.lang.OutOfMemoryError: Java heap space

14:25 TimMc: amalloy: just a sec

14:25 ,(range)

14:25 clojurebot: (0 1 2 3 4 ...)

14:25 cemerick: TimMc: generally, yeah. There are circumstances where I prefer to retain the separate "feature" history, but they're rare.

14:26 * technomancy likes the explicit merge commit when the branch has more than a handful of commits

14:26 TimMc: amalloy: GitHub pull requests apparenly create an empty merge commit, which cemerick doesn't like.

14:26 technomancy: but forcing it for single-commit branches is silly

14:26 amalloy: TimMc: accepting a pull request from the github web ui creates a merge commit, anyway

14:27 TimMc: amalloy: right

14:27 cemerick: technomancy: roughly my point

14:27 TimMc: Feature request time! :-D

14:27 cemerick: an extra button wouldn't hurt

14:27 amalloy: i wonder, what is everyone's opinion about rebasing pull requests?

14:27 TimMc: "Please to be adding a ticky-box."

14:27 cemerick: bitching on twitter is my feedback line

14:28 hiredman: rebasing :(

14:28 amalloy: like, i get pull requests based on some snapshot of master from a month ago

14:28 TimMc: A rebase once set my grandmother on fire.

14:28 or so I hear

14:28 amalloy: and i don't want a stupid merge there, so i often rebase them. but then the submitter's commits aren't actually in my tree, just another version of their commits. so they have to junk em and fetch master again

14:29 ideally submitters would rebase it themselves, but in practice not everyone knows how

14:29 hiredman: joegallo has opinions on rebasing

14:29 joegallo: rebase ALL THE THINGS!

14:29 cemerick: I like having only one commit to represent _all history_

14:30 Raynes: I wish I cared about the state of my git repos as much as you people.

14:30 I bascially just execute different git commands until things look okay.

14:30 TimMc: I demand that my repo history look like a geodesic.

14:30 only triangles

14:31 Raynes: Those two are not mutually exclusive. :-(

14:32 technomancy: ,(= #"" #"")

14:32 clojurebot: false

14:32 * technomancy whimpers

14:32 amalloy: haha awesome

14:32 joegallo: my typically work flow ends up being something like: branch from master, make a bunch of commits (rebasing onto master as i go), and when i'm finally finished i reset (soft!) back to master and then commit individual bits and pieces of the final giant delta with nice little commits

14:32 TimMc: technomancy: Perhaps because Pattern can represent non-regular languages? :-)

14:33 drewr: joegallo: why the soft reset? why not just fix them as you rebase?

14:33 technomancy: amalloy: yeah, I rebase pull requests all the time; I try to get contributors to use topic branches

14:34 amalloy: drewr: at the end he can craft a patch series with full knowledge of the diff and group things "logically" instead of temporally

14:34 not really my style, but i like that git lets him do that without bothering me

14:34 hiredman: "patch series" what is this mercurial?

14:35 joegallo: drewr: i dunno, sometimes it just seems easier to redo the commits from nothing but a ball of unchecked in changes -- particularly if i have something is one commit already and i want it to become two or three

14:35 drewr: amalloy: yeah, I just do that with interactive rebasing as I go

14:36 joegallo: I like to retain some semblance of the thought-progression

14:36 joegallo: i find that interactive rebasing is great for reordering and squashing, but bad for splitting (but that's probably just my own ignorance, and in fact the tool is amazing for that, also)

14:36 TimMc: joegallo: But then you lose all the archaeological value of your commit history!

14:36 drewr: TimMc++

14:36 joegallo: just the crap

14:36 technomancy: TimMc: but you get to appear smarter than you really were!

14:36 joegallo: i lose the crap

14:37 TimMc: joegallo: and more importantly, that makes it easy to have broken-build commits on master.

14:37 joegallo: yes, you have to be really careful to avoid those

14:37 pjstadig: you guys are all insane

14:37 joegallo: if those are even something you try to avoid

14:37 drewr: joegallo: you're too busy shining your perfect little merge commits

14:37 joegallo: each one is a precious pearl, drewr

14:37 a unique beatiful snowflake, with it's very own sha1

14:37 ugh, its

14:38 amalloy: joegallo: rebase -i actually is pretty good for splitting too, though i don't often do that

14:38 joegallo: yeah, i love the -i, how do you make it do splits nicely?

14:38 s/pick/edit/?

14:38 amalloy: if you mark a commit as "edit", you can perform multiple commits before --continue

14:39 joegallo: but doesn't it drop you into a clean working directory?

14:39 do you reset the commit off HEAD to split it?

14:39 amalloy: joegallo: eh. git reset HEAD^

14:39 joegallo: bingo, okay.

14:39 amalloy: or HEAD, or whatever. one of those

14:40 joegallo: okay, that's perfectly logical. i sortof imagined you could make that work, but never bothered to try it.

14:40 thanks!

14:41 * TimMc still doesn't know how to recover from a merge conflict

14:42 triyo: Is there a way to specify in leiningen libraries (jars) to be included that are not in any repo?

14:42 TimMc: triyo: You can install them in your local Maven repo.

14:43 There's some "install" command.

14:43 for mvn, not lein, I think

14:44 amalloy: triyo: yes, but technomancy wishes you wouldn't do that

14:44 TimMc: Raynes: Merge conflicts are where I start flailing wildly until things work.

14:45 triyo: amalloy: ok so whats the way to approach this when you get 3rd party jars you have no control over?

14:45 They not in any maven repo, etc.

14:46 joegallo: which particular library?

14:47 drewr: joegallo: by rebase above I was talking about rebase -i (I do with magit which is much nicer)

14:47 technomancy: triyo: report a bug with the library; it's a pretty serious failing on their part

14:47 joegallo: i really should learn to use that well, drewr

14:47 technomancy: while you're waiting for the bug to be fixed you can use the lein-localrepo plugin or set up your own private archiva/nexus server

14:48 triyo: technomancy: I see what you mean

14:49 TimMc: Of course, at work I use git-svn, so it all gets linearized anyway -- and I can't even do branches safely.

14:50 amalloy: TimMc: you can merge with svn. if you've ever merged with cvs, svn feels like a breath of fresh air

14:50 git is a thousand times easier, of course

14:51 TimMc: amalloy: git-svn is a special case -- you're restricted in what features you can use from either system.

14:51 And I would contend that git is more awesome, but more complicated.

14:51 amalloy: doing simple things with git is certainly more complicated than doing them with svn

14:52 TimMc: right

14:53 joegallo: s/complicated/awesome/ :)

14:53 R4p70r: Git just has better command line tools. I love how you get a pager for default and how much options you have. SVN has some nice UI though.

14:54 *how many options

14:54 amalloy: R4p70r: the command line is a UI. unclear what you mean

14:54 R4p70r: GUI sorry

14:55 Raynes: We should all use bzr.

14:55 R4p70r: I've tried some git GUIs but I just don't get them. Would be nice to have something like "rebase --interactive" where you could drag commits to reorder them or something.

14:56 amalloy: R4p70r: so, you want a text editor that lets you use a mouse? those are pretty common

14:56 and rebase --interactive does exactly that; i'm not sure whether you realized that or were wishing for it

15:01 R4p70r: A text editor isn’t the kind of graphical UI I’m hoping for. It’s been a while since I looked at what was available. Maybe there are more interesting options now.

15:01 TimMc: "git topiary"

15:03 davidd_: we have an svn project at work and my coworker asked me how to rebase in svn

15:03 lol

15:04 * gfredericks waits for somebody to say something about tears of children

15:05 R4p70r: TimMc, What is that?

15:06 TimMc: R4p70r: It's a term I just came up with to describe obsessive git history sculpting.

15:11 R4p70r: TimMc, Well Guilty as charged

15:13 gfredericks: TimMc: I spend way more time sculpting my git history than I do taking advantage of my sculpted git history

15:14 $findfn nil ()

15:14 lazybot: [clojure.core/distinct clojure.core/lazy-cat clojure.core/sequence clojure.core/vec clojure.core/concat clojure.core/seque clojure.core/drop-last clojure.core/reverse clojure.core/cycle clojure.core/rest clojure.core/lazy-seq clojure.core/flatten clojure.core/sort]

15:16 mebaran151: what's the most recent guide for setting up emacs 24 on windows with slime; something broke my current setup and I've decided to redo it from scratch

15:27 raek: mebaran151: https://github.com/technomancy/clojure-mode and https://github.com/technomancy/swank-clojure

15:27 mebaran151: clojure-mode is the only thing you need to install in emacs if you use the "jack in" approach

15:45 jcromartie: what's the idiomatic way to handle resources (like input/output streams)

15:45 a la C#'s using

15:46 raek: with-open

15:46 the same as calling .close in a finally block

15:46 jcromartie: right, thanks

15:47 duck1123: take a look at clojure.java.io for some other helpers if you're using io streams

15:48 jcromartie: yeah, I'm using those

15:49 WOAH File/pathSeparator is not to be trusted!

15:50 jeez, how wrong can Java be?

15:50 it uses a colon on Mac OS X

15:50 old school

15:51 TimMc: What is it supposed to be on Mac?

15:51 jcromartie: a slash

15:51 darrint: Is 4clojure.com working for anyone else right now? All my solutions are answered with "clojure.lang.PersistentList cannot be cast to clojure.lang.IFn"

15:52 raek: jcromartie: what do you get if you use (clojure.java.io/file "foo" "bar")? "foo/bar"?

15:52 duck1123: jcromartie: The system-dependent path-separator character. This field is initialized to contain the first character of the value of the system property path.separator. This character is used to separate filenames in a sequence of files given as a path list. On UNIX systems, this character is ':'; on Microsoft Windows systems it is ';'

15:52 TimMc: jcromartie: No, this is for separating paths, not path components.

15:52 amalloy: darrint: should be fixed now

15:52 we're having a bumpy deploy cycle :P

15:52 raek: ah.

15:52 TimMc: ,File/separatorChar

15:52 clojurebot: #<CompilerException java.lang.RuntimeException: No such namespace: File, compiling:(NO_SOURCE_PATH:0)>

15:52 TimMc: ,java.io.File/separatorChar

15:52 clojurebot: \/

15:52 TimMc: ,java.io.File/pathSeparatorChar

15:52 clojurebot: \:

15:53 jcromartie: ohderp

15:53 thanks for the smackdown

15:53 TimMc: heh

15:53 jcromartie: I thought it was stuck in OS 9 days

15:54 raek: jcromartie: the Java default encoding on OS X is still Mac Roman, though :( (and OS X acually uses UTF-8)

15:54 jcromartie: yes

15:56 mebaran151: I think those are installed, but run-lisp doesn't work

15:56 raek: run-lisp?

15:58 darrint: stupid browser

15:58 mebaran151: run-lisp in the clojure mode guidelines says it will start a quick repl

15:58 darrint: amalloy: Thanks. Thought I had lost my mind.

15:58 mebaran151: failed for me :(

15:59 also slime-connect throws an error about an unbound slime-clj

15:59 raek: mebaran151: uninstall the slime-clj package. it's another implementation of slime that causes conflicts

16:00 slime-clj + swank-clj are alternative implementations of the more common slime and swank-clojure

16:01 (they have also been renamed, but they are still available under their old names)

16:03 mebaran151: thanks raek, now everything works; I had to delete slime-fuzzy and slime-clj

16:03 I still have slime and slime-repl installed; is that optimal?

16:04 raek: you don't need to have those installed if you use clojure-jack-in

16:04 mebaran151: oh I sometimes use slime-connect

16:05 raek: since clojure-jack-in loads a slime.el file (that has a suitable version) from swank

16:05 if it doesn't cause problems, then keep it :)

16:05 slime-connect is useful too

16:13 mebaran151: clojure-jack-in fails on Windows still

16:14 wiseen: if I have (defmacro foo[bar] '(let [x ~bar] ...)) why does the macro result expand x to namespace variable, eg. (foo apple) => (let [foobar/x apple] ...)

16:14 assuming I call foo from a different namespace

16:14 mebaran151: how do I get the autodoc back working in emacs with the new clojure mode?

16:14 raek: wiseen: you should use x# in the let

16:15 hiredman: wiseen: you are using ` not '

16:15 wiseen: hiredman, yeah `

16:15 hiredman: wiseen: but you should be using `, so that is ok, just the example code you pasted does not match what you really have

16:15 Bronsa: wiseen: ~'x

16:16 raek: Bronsa: that will result in symbol capture

16:16 hiredman: in the future being precise about this kind of thing when asking for help will serve you well

16:16 mebaran151: strike that; just had to start slime :)

16:16 Bronsa: raek: right

16:16 wiseen: raek, is # some magic ?

16:17 like ` is for (quote)

16:17 raek: wiseen: in most cases you want the symbols that are emittet by your macros to either be qualified with a namespace or be autogensymed

16:17 brehaut: ' is for (quote …) ` is quasiquote

16:17 raek: wiseen: yes, the # suffix is special syntax-quote syntax

16:18 all occurances of the same x# in the syntax-quoted expression will become a symbol starting with "x" but with a unique suffix

16:18 ,`(x# x#)

16:18 clojurebot: (x__27__auto__ x__27__auto__)

16:18 brehaut: ,(read-string "['(quoted a b c) `(quasiquoted a b c)]") ; wiseen ` and ' are different

16:18 clojurebot: [(quote (quoted a b c)) (clojure.core/seq (clojure.core/concat (clojure.core/list (quote sandbox/quasiquoted)) (clojure.core/list (quote sandbox/a)) (clojure.core/list (quote sandbox/b)) (clojure.core/list (quote sandbox/c))))]

16:19 hiredman: brehaut: syntax quote

16:19 Raynes: &`((gemsym) (gemsym))

16:19 lazybot: ⇒ ((clojure.core/gemsym) (clojure.core/gemsym))

16:19 Raynes: Duh.

16:19 brehaut: hiredman: crap. thanks

16:19 wiseen: brehaut, oh I see, tnx

16:19 * brehaut go fixes his parser

16:20 raek: wiseen: if you take a piece of code from the macro caller and wrap that in a (let [x ...] ...), you can accidentally capture the x symbol (and break the user code, if it happens to use that symbol name)

16:20 jcromartie: hm

16:20 I can't get DigestOutputStream to work here

16:20 brehaut: i dont know why ive been calling syntax-quote quasiquite. is that some older lispism?

16:20 jcromartie: using clojure.java.io's copy

16:21 the copy works fine

16:21 raek: wiseen: so clojure makes it simple to get unique names that won't conflict with the user code

16:21 amalloy: brehaut: yes

16:22 i think we call it syntax-quote because it does the namespace prefixing, which traditional quasiquiting doesn't do

16:22 jcromartie: but the digest is of null data

16:22 i.e. openssl sha1 /dev/null

16:22 brehaut: amalloy: thanks

16:22 mebaran151: how do I get the locals debugger back working in Slime by the way?

16:25 jcromartie: can someone look at this real quick? https://gist.github.com/dda2e42a45226972aee5

16:25 using clojure.java.io

16:25 mebaran151: now just to get color-theme working and I'll be set

16:25 jcromartie: and DigestOutputStream to compute the SHA-1 of the file on the way out

16:26 amalloy: jcromartie: you're not writing to the digest-stream at all?

16:27 wiseen: raek, got it to work, tnx !

16:27 joegallo: amalloy: right, he's bypassing the digest-stream

16:27 amalloy: you need to copy in to digest-stream, not to out

16:27 jcromartie: ah ha

16:27 derp

16:27 I have even done this before!

16:27 thanks

16:28 ta-da

16:59 tolstoy: in lein 1.6.2, "lein uberjar my-app.main" gets me this error: Wrong number of args (2) passed to: clean$clean

16:59 the source suggests that supplying a main is legit.

17:00 technomancy: tolstoy: can you paste a stack trace?

17:00 bhenry: if lein compile fails how can i see the "12 more" lines of the stack trace?

17:00 tolstoy: What's the preferred paste bot here?

17:00 bhenry: gist

17:01 tolstoy: ok

17:01 technomancy: bhenry: you could try clj-stacktrace

17:02 amalloy: bhenry: you don't need the "12 more" - it only trims subsections which are already present in the trace

17:02 bhenry: none of the current lines are part of my project

17:02 amalloy: yeah, compiler errors don't happen in your code; they happen in the compiler, which is reading your code

17:02 bhenry: ah. i want to know what's wrong with my code that won't compile

17:03 joegallo: gist the entire stacktrace, and i bet you can get a pretty helpful answer

17:03 amalloy: the stacktrace from the compiler is a good start. usually one of the exceptions has a *message* indicating which line of your code is at issue

17:03 tolstoy: technomancy: regarding lein uberjar: git://gist.github.com/1387132.git

17:03 technomancy: regarding lein uberjar: https://gist.github.com/1387132

17:04 (Sorry.)

17:04 technomancy: tolstoy: looks like you've got a hook that is screwing things up

17:04 tolstoy: technomancy: Just noticed that. Hm. I'll check it out.

17:04 bhenry: https://gist.github.com/85463179180fcbc9cbd8

17:07 joegallo: bhenry: you are calling something that expects a symbol, but you're giving it a string. shot in the dark -- check the syntax of your namespace declaration.

17:07 amalloy: agreed that it looks like a bad ns decl

17:07 but hard to be sure

17:07 bhenry: joegallo: does the stacktrace indicate that it's happening when compiling floyd.server?

17:08 hiredman: joegallo: have you looked at bytescript at all?

17:09 amalloy: bhenry: i think when compiling one of the files that floyd.server depends on?

17:09 hiredman: joegallo: apropos your interest in asm

17:10 pjstadig: hiredman: you mean bitescript?

17:10 joegallo: bhenry: yes, that, or a depency of it (but some that must not be a dependency of floyd.version)

17:10 pjstadig: https://github.com/headius/bitescript

17:12 joegallo: hiredman: i have not, but it is pretty

17:12 man is it pretty

17:12 jcromartie: does anybody else read "prn-str" as "porn star">

17:12 ?

17:12 joegallo: always

17:12 brehaut: never

17:12 bhenry: amalloy: joegallo: well i don't think it's a namespace dec because i checked all the ones that changed between the last successful compile and my latest push

17:13 brehaut: jcromartie: but not im not going to be able to unsee it

17:13 joegallo: bhenry: is this open source code? why not just push the problem to a branch and send us a link?

17:13 bhenry: it's not open

17:13 : /

17:14 but my last push only changes files that don't have anything to do with floyd.server. they are new files independent of the rest of the app. i'm going to see what happens if i remove them, but they shouldn't be part of lein compile.

17:15 joegallo: well, it could be any one of the transitive dependencies of floyd.server

17:17 bhenry: haha i think i figured it out. i added :main to project.clj so i could start the server with lein run but for some reason it used to work with :main "floyd.server" and now wants floyd.server i guess.

17:17 technomancy: bhenry: I don't think strings for :main has ever worked

17:19 bhenry: by some magical force i've been using lein run for the last week

17:19 technomancy: oh... interesting. it may work for run, but not for compile.

17:20 bhenry: gotcha

17:21 jodaro: woop: Clojure in Action just arrived

17:22 jamiltron: I keep getting UPS stickers on my door saying they missed me and I have to pick mine up :(

17:22 jodaro: there will be some clojure in action tonight!

17:22 jamiltron: But I'm super excited for it.

17:25 jodaro: yeah me too

17:37 devn: I peeked at a friend's copy of Clojure in Action. It looks good.

17:37 justicefries: i have the MEAP, haven't opened it yet.

17:38 oh I guessI have the full version now.

17:41 kephale: is there a way to just use the integer bitops?

17:43 justicefries: anybody using a majority of Clojure in production?

17:44 Raynes: Lots of people.

17:44 http://dev.clojure.org/display/community/Clojure+Success+Stories are some public examples.

17:45 justicefries: ah ha. I'm working on getting it going in production.

17:45 brehaut: ,(apropos 'bit) ; kephale

17:45 clojurebot: (bit-or bit-set bit-xor bit-flip bit-and ...)

17:46 hiredman: justicefries: yes

17:46 kephale: brehaut: yes but ##(type (bit-shift-left (int 16) (int 7)))

17:46 lazybot: ⇒ java.lang.Long

17:47 brehaut: kephale: ah right, so you mean primative bit ops?

17:47 kephale: brehaut: exactly

17:47 brehaut: in that case, i have no idea sorry

17:48 amalloy: kephale: that doesn't necessarily show that you're not using primitive ints

17:48 kephale: yeah, but *digs up an example*

17:49 amalloy: yeah. clojure.lang.Numbers/shiftLeftInt takes two ints and returns an nit

17:49 *int

17:49 brehaut: kephale: are you on 1.2 or 1.3 ?

17:50 kephale: amalloy: ♥, i'll try that and the example being ##(bit-shift-left 0xFF 24)

17:50 lazybot: ⇒ 4278190080

17:50 kephale: brehaut: 1.3

17:51 Raynes: amalloy: Oh how I wish it returned a nit.

17:51 amalloy: kephale: yeah, i think it actually does box them up as a long first

17:52 you can call (clojure.lang.Numbers/shiftLeftInt (int x) (int y)), which should work

17:53 &(clojure.lang.Numbers/shiftLeft (int 0x7ffffff) 1)

17:53 lazybot: ⇒ 268435454

17:54 amalloy: &(clojure.lang.Numbers/shiftLeft (int 0x7fffffff) 1)

17:54 lazybot: ⇒ 4294967294

17:54 amalloy: hmph. why it isn't overflowing i'm not sure

17:54 brehaut: kephale: btw, https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L3047-3058 i dont think type does what you think it does

17:55 kephale: brehaut: mmm probably a time to be using class indeed

17:56 brehaut: kephale: well even class wont tell you if somethings primative i think?

17:56 amalloy: indeed, which is what i meant by "that doesn't necessarily show that you're not using primitive ints"

17:57 brehaut: i dont think there is a way on the jvm to even write a 'primative?' equivalent if you dont have static types?

17:57 amalloy: technomancy: find a funny comic with a monkey in it so brehaut will realize "primative" is about primates

17:57 kephale: lol

17:58 amalloy: hrm, clojure.lang.Numbers doesn't seem to have a bit-or for integers : X

17:58 brehaut: fine. i cant speel

17:58 amalloy: kephale: you have an allergy to objects or something?

17:58 technomancy: http://achewood.com/index.php?date=10262001 best I could do on short notice, sorry

17:58 amalloy: just box em up in Integers

17:59 brehaut: technomancy: umm. wow.

17:59 amalloy: technomancy: looks like you got it to stick in his memory. that's a win

18:00 kephale: amalloy: ok, i'll do that, but i am working on large sets of images

18:00 amalloy: thank you

18:06 choffstein: Hey all. I just updated one of my projects from 1.2 to 1.3 and am getting a strange error with clojure-csv. Specifically, "Can't dynamically bind non-dynamic var: clojure-csv.core/*strict*". Any thoughts, generically, on this type of issue?

18:06 Raynes: That means clojure-csv has dynamic vars that aren't explicitly declared dynamic.

18:06 It'll need to be updated if it isn't already.

18:07 choffstein: 1.3.2 uses 1.3-beta1, so it should work.

18:07 (1.3.2 of clojure-csv, I mean).

18:08 dsantiago: Update those deps, boy.

18:09 hiredman: choffstein: vars are not dynamic by default anymore

18:09 Raynes: God I wish he would unignore me.

18:09 choffstein: hmmm, I am using 1.3.2...

18:09 hiredman: clojure-csv needs to mark that var as dynamic if that is the intent

18:09 sure, since 1.3

18:09 dsantiago: It does mark it dynamic.

18:09 Raynes: https://github.com/davidsantiago/clojure-csv/blob/master/src/clojure_csv/core.clj#L33 is marked dynamic.

18:10 hiredman: dsantiago: most likely not with the version he is using

18:10 dsantiago: I missed the fact that it depends on 1.3.0-beta1, I can update that in a few.

18:10 Raynes: dsantiago: Doesn't really matter.

18:10 The top-level dep is preferred.

18:10 dsantiago: I wouldn't think it would, but it seems to be causing him a problem..

18:10 choffstein: dsantiago: a million things could be causing my issue ;)

18:10 don't assume its with you

18:10 dsantiago: Oh, I see, it looks like he is using an older version of clojure-csv.

18:11 You need at least clojure-csv to work with clojure 1.3+.

18:11 Er, clojure-csv 1.3.0

18:11 hiredman: that would be my guess, or hasn't fetch deps or something

18:11 choffstein: I am using clojure-csv 1.3.2

18:11 hiredman: is that the jar that is in your ~/lib/ ?

18:12 amalloy: ~/lib?

18:12 clojurebot: Titim gan éirí ort.

18:12 hiredman: ./lib

18:13 choffstein: clojure-csv-1.3.2.jar

18:13 hiredman: any other clojure-csv jars there?

18:14 choffstein: Nope.

18:14 dsantiago: I'm baffled.

18:14 choffstein: Me too.

18:14 hiredman: choffstein: have you cleaned out ./classes since you upgraded clojure-csv?

18:14 Raynes: 'lein clean' is known to cure cancer.

18:14 choffstein: hiredman …

18:15 stupid … stupid … stupid

18:15 hiredman: are you aot compiling?

18:15 (if so why?)

18:15 choffstein: annnddddd that fixed it

18:16 hiredman: that means you are aot compiling

18:16 dsantiago: Glad that's fixed.

18:17 hiredman: you may want to look into setting :clean-non-project-classes to true in your project.clj

18:18 technomancy: the latest lein will automatically clean when you pull in new deps

18:20 R4p70r: TimMc, amalloy, or anyone interested: I did a quick mockup of a git graphical UI I might like http://twitpic.com/7i1vl6 Do you know anything like it or have any thoughts?

18:21 amalloy: it seems pretty pointless to me. but you can try gitk and/or gitgui

18:22 hiredman: magit

18:22 R4p70r: hiredman, Thanks I'll take a look.

18:23 amalloy, How is it pointless? When I was working with SVN on windows I used to go back and forth between the Tortoise UI and command line a lot.

18:26 Granted the Windows command line is awful. no patch or find or whatever. I had a bunch of unix tools installed.

18:26 hiredman: there is a solution to that

18:26 why in the world are you developing on windows?

18:28 amalloy: R4p70r: all a gui will do is make you fiddle with the mouse to move things around instead of using muscle memory to move things around in a text editor with the keyboard

18:32 (or, more often, typing out quick commands on the cli vs clicking through a couple levels of menu)

18:32 R4p70r: I mostly used Windows for work... As for gui I someting use it on Linux as well "xdg-open ." to see thumbnails of image files in nautilus or something. Not anywhere as often as on Windows/OS X though

18:33 You can have keyboard friendly GUIs though

18:33 a/somting use/sometimes use"

18:38 amalloy: you're free to disagree, and to implement that gui if you're so inclined. you asked for thoughts, and my thought is: most of the git community would rather use the cli even with a pretty nice gui

18:40 R4p70r: Okay. Thanks for your feedback

18:41 tolstoy: There are some pretty nice GUIs out there for git, for those inclined.

18:41 http://www.git-tower.com/

18:42 Windows one: http://www.syntevo.com/smartgit/index.html

18:46 alex_baranosky: tolstoy: tower looks really nice, but I find myself asking why I would need it

18:47 tolstoy: alex_baranosky: Same here. The only reason I can think of is something that helps you visualize a complicated history. Which is something I don't need.

18:48 amalloy: tolstoy: actually github does a fantastic job of that. it's the main (only?) gui tool i use for git

18:48 technomancy: amalloy: you don't use magit?

18:48 amalloy: no

18:48 tolstoy: amalloy: Well, not everyone's on github, of course. ;(

18:49 amalloy: But yeah.

18:49 alex_baranosky: I just use gitk if I want to visualize the history. It's always been enough for me

18:50 technomancy: amalloy: it will change your life

18:50 Raynes: tolstoy: They should be.

18:50 We shouldn't considered them equals until they are.

18:51 dakrone: ugh, the worst part of releasing in writing a message to the clojure group about it

18:52 *is

18:52 technomancy: dakrone: the hoe tool for ruby actually automates release messages

18:53 dakrone: technomancy: when can I expect that in lein? ;)

18:53 technomancy: dakrone: go for it. =)

18:54 R4p70r: amalloy, The weird thing about github is that you can’t use it until the changed are pushed there.

18:54 tolstoy, I'll have to look into these as well

18:56 I can't type

18:56 hiredman: cemerick: why not sexps for nrepl?

18:57 amalloy: hiredman: harder to write parsers for every client

18:57 hiredman: amalloy: evidence?

18:57 is there a language someone hasn't written a lisp reader in?

18:57 is it any harder then writing a bencoding or netstrings decoder?

18:58 amalloy: hiredman: when ninjudd was poking at this on the flight from the conj, the bash netstring decoder is like two lines

18:58 hiredman: scala seems to use sexps just fine for ensime

18:58 amalloy: ok

18:58 do we care about clients written in bash?

18:59 amalloy: i got the impression that we do, but i'm not the expert here

18:59 hiredman: if you want such a thing use a socket repl

18:59 nrepl is for tools, right? are our tools going to be written in bash?

18:59 ninjudd: hiredman: yes. all of them

19:00 you didn't hear?

19:00 hiredman: I bet you could read sexps in bash if you really wanted to

19:00 ninjudd: sure, wouldn't be that hard

19:00 hiredman: I mean, it just seems like nrepl is bending over backwords to avoid signs of "favoritism" or something

19:01 I am not even proposing all sexps, just lists, strings, and numbers

19:01 with a padded hex byte count prefixed

19:02 ninjudd: hiredman: for the entire string?

19:02 hiredman: yes

19:02 0x00001D:(("code" "(+ 1 2)") ("id" 1))

19:02 ninjudd: so you want that instead of netstrings so that the prefix is fixed-width?

19:02 hiredman: if you want to send binary use nrepl to negotiate a more suitable channel

19:03 like websocket negotiation over http

19:03 ninjudd: yes

19:03 so you can easily tell if you have a whole message or not

19:05 colon and 0x could be left out, I dunno

19:07 ninjudd: i'm not opposed to this idea

19:07 i think the main objection will be the inability to send binary

19:08 hiredman: which is ridiculous

19:08 use nrepl to ask for an http endpoint

19:08 DONE

19:09 like, we are not build a protocol on which the entire internet is going to use

19:10 it's a repl protocol

19:10 ninjudd: i like that much better than adding all this crazy accepts stuff to the base protocol

19:10 hiredman: what does binary data have to do with reading, evaluating, printing, and looping?

19:11 ninjudd: richer printing i suppose

19:12 hiredman: richer display

19:14 I really just should ignore the nrepl thread and see what comes out of it, reading it just makes me want to grab people by the shoulders and shake them

19:14 ninjudd: heh. what's your take on this Atoms vs. Agents thing?

19:15 hiredman: who cares?

19:15 ninjudd: awesome

19:16 hiredman: the wire format and mock interactions (to get a feel for it) are 1e10 times more important then how it might currently be implemented

19:18 ninjudd: i'm not sure i agree with that. i'd say the semantics of the map being passed is equally important

19:19 hiredman: I don't follow how that is different from what I said

19:20 "passed" means going over the wire?

19:20 ninjudd: hiredman: i thought that by wire-format, you meant: how to represent the map, not the meaning of the keys in the map

19:21 hiredman: in my mind "the wire format and mock interactions" covered everything going on between a client and server

19:22 ninjudd: got it

19:23 hiredman: http://www.joelonsoftware.com/articles/fog0000000018.html

19:27 Bahman: Is there some equivalent to DOLISP in Lisp? I need to iterate a list and apply a function to each element.

19:27 amalloy: *chuckle*

19:27 Bahman: you probably don't actually need that, but if you do it's ##(doc doseq)

19:27 lazybot: ⇒ "Macro ([seq-exprs & body]); Repeatedly executes body (presumably for side-effects) with bindings and filtering as provided by \"for\". Does not retain the head of the sequence. Returns nil."

19:28 Bahman: Thanks amalloy!

19:28 cemerick: hiredman: sounds like you would like to essentially just lift clojure.main/repl onto a socket and call it a day

19:28 hiredman: cemerick: no, I don't thing exposing the rich set of sexps that clojure has is easy, a simple subset is good

19:29 and prefixed with a bytecount

19:29 cemerick: and again, clojure.main/repl is an implementation detail that at this phase in design has no place

19:29 ninjudd: hiredman: the decision about agents vs atoms has a lot to do with how mock interactions work

19:30 hiredman: ninjudd: I fail to see how, you make the mock interactions do what you want, then pick the bits you need to implement it

19:31 ninjudd: well, in this case, the implementation choice of atoms or agents influences the interface, which dictates how it works

19:31 hiredman: I would be much more likely to implement nrepl using something like a thread pool of repls that are given a state and a form and return new state and a result

19:32 ninjudd: I disagree

19:33 it is one thing to be mindful of the tools you have, it is another thing to make everything a nail or screw when you have a screendriver and a Mjöllnir

19:33 heh

19:33 (irssi setup to replace h a m m e r with Mjöllnir)

19:33 amalloy: haha awesome

19:34 hiredman: screwdriver

19:34 ninjudd: hiredman: so you would pass the state from the client with every command?

19:35 hiredman: ninjudd: most likely keep a separate map of id => state or session id => state or something like that

19:36 but I imagine that and agents both might run into issues with debuggers which may not like you jumping around on threads

19:36 not sure

19:38 ninjudd: oh, so you'd just reimplement a bad version of agents instead of using them. cool

19:38 hiredman: is it a bad version of agents?

19:38 could be

19:39 ninjudd: well, you'd probably implement a decent version i suppose

19:39 hiredman: but my point is, we should decided what we want, what is best, and that should drive the code we write, not the other way around

19:40 if we want forkable repls, fine, make that a requirement

19:40 cemerick: hiredman: That's the whole point of the wiki page and the problem statements, etc. therein.

19:40 If those are the wrong problems or an incomplete statement of them, speak up on the ML

19:41 hiredman: sure, the wikipedia does a better job of staying on (what I consider to be the) topic than the ml thread does

19:42 ninjudd: fine. it was just easier to say: "what do you think of Atoms vs. Agents" than, "what do you think about having the resulting state of parallel commands be undefined"

19:43 hiredman: that is interesting

19:44 enforced serialization seems to be the currect answer, but I don't know

19:44 correct

19:44 the wiki

19:49 cemerick: is the desire not use sexps because "well, if we use sexps we may as well just put a repl on a socket?"

19:50 sexps seem just as compelling as bencoding or netstrings, the with bonus that we already have a reader and a printer

19:54 xcv: Don't know if you guys consider this off topic, but I wanted to check whether anybody had experience writing a serious client-side web app in Clojurescript, how you like it and whether switching from jQuery / learning to use the Google Closure stuff instead was a bad experience or reasonably easy and worthwhile...?

19:56 tolstoy: Is there a handy function that's like cycle but remembers where it left off each time you call it?

19:57 xcv: the idea of writing the client-side code basically in clojure, with a mostly-clojure REPL, sounds like a dream, and I'm pondering whether to start investing my startup in it sometime in the coming months

19:57 hiredman: tolstoy: cycle generates a lazy seq, just walk it

19:57 xcv: by all means, opine :)

19:57 amalloy: tolstoy: you want a mutable sequence? kinda dangerous/gross, but otherwise that's all there is to it

19:58 tolstoy: amalloy: hiredman: Here's the use case: I have three IP addresses. Each time a function calls this X thing, I want it to move on to the next IP in the sequence, then start over.

19:58 Kind of a yield thing.

19:58 I have a habit of re-implementing core functions, so I was just curious. ;)

19:59 hiredman: tolstoy: best is if you do it as a lazy seq

19:59 tolstoy: hiredman: Okay. Thanks.

19:59 hiredman: e.g. you return an infinite lazy-seq of ip addresses, and first/rest as needed

20:00 amalloy: an infinite sequence of IP addresses! that would solve the ipv4->6 problem trivially

20:00 ninjudd: xcv: you may get more response if you post you question to the mailing list

20:00 tolstoy: ha ha.

20:01 hiredman: if you turn the caller of X into a fn that takes the ip as a parameter instead of calling X you can do (map (fn [ip] stuff) (cycle ips))

20:01 tolstoy: Hmm.

20:03 hiredman: if you have other parameters (map (fn [other ip] stuff) other (cycle ips))

20:03 tolstoy: Then take the first of that?

20:03 hiredman: well, replace the second other with others, unless it really is singular

20:03 tolstoy: hmm?

20:03 take how ever much you need

20:04 tolstoy: I have something like: (let [data (cycle addrs)] (defn next-addr [] (first data)))

20:04 hiredman: :(

20:04 that is horrible

20:04 tolstoy: Not only that, but it doesn't work! ;)

20:04 hiredman: the cycle there is pointless

20:04 tolstoy: Heh.

20:05 hiredman: do your futures have meaningful returns values?

20:05 functions

20:05 tolstoy: What I need is a generator.

20:05 Think a rabbit-mq connection, and a series of IP addresses in a cluster.

20:05 hiredman: if so then you want map anway, and you can just use it

20:05 sure

20:05 I understand how rabbitmq works

20:05 tolstoy: When a rabbit-mq connection goes down, I want to call a magical function called "get me the next one in the list".

20:06 Alas, I seem to have drawn a total blank. I probably need to rest.

20:06 hiredman: I think you'll find .newConnection on the connection factory takes an array of hosts

20:06 tolstoy: Does it?

20:07 Hm. I must have looked in the wrong place for that sort of thing.

20:07 hiredman: at least the version I am using does

20:07 amalloy: like i said, you're just asking for a mutable sequence, if this is the api you really want (i think hiredman is right that you probably don't want this api). but it's simple to do with a ref: (let [ips (ref (cycle addrs))] (defn next-addr [] (dosync (let [x (first ips)] (alter ips rest) x))))

20:07 hiredman: tolstoy: so you should just pass in your ips

20:08 (map compute-stuff (repeatedly (partial connect-to-rabbit params)))

20:08 or something

20:09 tolstoy: amalloy: Yes, that makes sense. And, yes, if I can find a place to supply the IPs direct to rabbit mq, I'd be happier.

20:10 You say .newConnection takes a list? I'm not seeing it.

20:10 hiredman: it takes an array

20:10 http://www.rabbitmq.com/releases/rabbitmq-java-client/v2.6.1/rabbitmq-java-client-javadoc-2.6.1/

20:10 http://www.rabbitmq.com/releases/rabbitmq-java-client/v2.6.1/rabbitmq-java-client-javadoc-2.6.1/com/rabbitmq/client/ConnectionFactory.html#newConnection%28com.rabbitmq.client.Address[]%29

20:11 tolstoy: Hm. I wonder if they dropped that on 2.7.0?

20:12 http://www.rabbitmq.com/releases/rabbitmq-java-client/v2.7.0/rabbitmq-java-client-javadoc-2.7.0/com/rabbitmq/client/ConnectionFactory.html#newConnection()

20:12 Perhaps they moved it to these magical "client properties" object.

20:14 hiredman: thats kind of annoying

20:14 tolstoy: No kidding! :)

20:18 Pretty interesting that they took it out. I guess I can post to a mailing list and ask why they did that.

20:20 pandeiro: how does one execute a do...while loop in clojure, where the condition is checked after at least one iteration?

20:21 amalloy: never, to a first approximation

20:21 hiredman: stop looping

20:21 amalloy: simply because while and do/while are atrociously non-functional

20:21 pandeiro: ok

20:22 i am trying to convert a string to byte array... any suggestions?

20:22 tolstoy: pandeiro: loop / recur might work.

20:22 (.getBytes "string")

20:22 hiredman: ,(.getBytes "foo")

20:22 amalloy: $javadoc String getBytes

20:22 lazybot: http://download.oracle.com/javase/6/docs/api/java/lang/String.html#getBytes(int,%20int,%20[B,%20int)

20:22 clojurebot: #<byte[] [B@136407c>

20:22 pandeiro: ClojureScript :)

20:22 lancepantz: they were waiting for that one

20:22 hiredman: reduce

20:22 tolstoy: Heh.

20:23 amalloy: pandeiro: if you do it youself, you'll do it wrong. i know i would

20:23 pandeiro: amalloy, i am using a pretty standard JS impl as the template

20:24 amalloy: what i'm getting at is such functions usually don't bother with character-encoding. characters contain more information than bytes (and not just because java uses two bytes to hold a char)

20:24 pandeiro: http://sprunge.us/IggK?js

20:25 i see.

20:25 hiredman: :(

20:25 horrid

20:26 anyway, use reduce

20:26 pandeiro: hiredman, ok i will meditate on that, thanks

20:26 amalloy: hiredman: more like a mapcat, isn't it? (mapcat (fn [char] [byte1 byte2 ...]) s)

20:26 tolstoy: Is this ongoing? http://clojure.org/streams Clojure 1.4, for instance?

20:27 hiredman: amalloy: could be, depends if he wants to produce a seq or a js array

20:27 amalloy: tolstoy: (Note: this section describes work in progress, currently only available in SVN)

20:27 hiredman: tolstoy: dead as far as I know

20:27 amalloy: that tells me it is extremely old

20:28 tolstoy: Yeah, I figured. Google has it at 2009.

20:28 hiredman: it is, pre-1.2, possibly pre-1.0

20:28 tolstoy: I know you are googling for "clojure generators" please stop

20:28 amalloy: interesting to see that clojure was defining map*, filter*, and so on, the way lamina does now

20:28 tolstoy: hiredman: Heh. No such thing and never will be?

20:29 hiredman: do what amalloy suggested with the atom, or use map

20:29 amalloy: generators are isomorphic with lazy-seqs

20:29 but they're presented in a much more stateful way

20:29 clojure doesn't like the statefulness, and already has lazy-seqs, so it isn't getting generators

20:30 tolstoy: Okay, okay. Just exploring a little.

20:33 reiddraper: I'm going to implement my own set "type" with deftype, and I'm looking for the protocol/interfaces I should implement to make it respond in the same way as a "normal" set. Where can I find this? The closest I've found is http://fiji.sc/javadoc/clojure/lang/IPersistentSet.html

20:34 hiredman: ,(supers (class #{}))

20:34 clojurebot: #{clojure.lang.APersistentSet clojure.lang.IPersistentCollection clojure.lang.AFn java.util.Set clojure.lang.IEditableCollection ...}

20:34 hiredman: all the interfaces in that set (not the abstract classes)

20:34 amalloy: reiddraper: https://github.com/flatland/ordered/blob/develop/src/ordered/set.clj

20:35 reiddraper: thanks hiredman, amalloy

20:35 hiredman: wow, yesterday was clojurebot's birthday

20:36 amalloy: hiredman: first commit, 1.0, first login...?

20:36 hiredman: nov. 21st, 2008 was the first gist

20:36 https://gist.github.com/27733

20:37 technomancy: yeah, I got started on Clojure from the pragprog black friday sale

20:38 hiredman: hah, look at all those docstrings

20:40 clojurebot: what is your origin story?

20:40 clojurebot: http://clojure-log.n01se.net/date/2008-11-21.html#13:04

20:56 devn: cemerick: you around?

20:58 jcromartie: meatdata, and lolcathost

21:00 reiddraper: I'm trying to understand how one might do something like implementation inheritance with deftype. I see the light of polymorphism with multimethods and defrecord, but in cases where you should use deftype, what options are there?

21:01 Raynes: You don't.

21:02 reiddraper: Raynes: alright, so perhaps someone can help me think about this problem "differently". I have two different Set types I'd like to implement, which have some underlying similarities.

21:02 hiredman: there are a number of ways to do that

21:02 reiddraper: I suppose I could create a builder func that would set some bool on the type and my funcs can decide whether they want to switch on it or not

21:02 hiredman: the simplest is just put the shared functionality in a function, and have both implementations call the function

21:03 but you can really do whatever you want, you can write macros to generate two deftypes that differ slightly

21:05 https://github.com/hiredman/tuples/blob/master/src/tuples/core.clj#L47 generates distinct types for tuples, with two element tupls also implementing Map.Entry

21:05 reiddraper: hiredman: I rather like that second idea. I get the idea that I shouldn't necessarily be inheriting someone else's implementation details

21:05 but it also seems wrong to have two quite similar types and have to declare that they are using the same funcs for 30% of their calls

21:05 hiredman: wrong how?

21:06 reiddraper: verbose, for one. I'd at least like to be able to do it for a whole protocol. Perhaps this is where the power of macros come in

21:06 goodieboy: how can i select alternating values from a list?

21:08 hiredman: ,(doc take-nth)

21:08 clojurebot: "([n coll]); Returns a lazy seq of every nth item in coll."

21:08 reiddraper: hiredman: the tuple-for example you sent is great, thanks

21:08 goodieboy: ,(take-nth 2 '(1 2 3))

21:08 clojurebot: (1 3)

21:08 hiredman: it is certainly something

21:08 goodieboy: hiredman: nice thanks!

21:09 hiredman: my first use of detype for a 'real' datastructure

21:16 goodieboy: i'm attempting to create a macro that defines a set of "lettings", I can't figure out how to make this work? https://gist.github.com/1387726

21:17 oops... just edited that to actually make sense :)

21:18 alex_baranosky: ok

21:20 goodieboy: looks liek aplain let to me

21:20 bhenry: same here

21:20 goodieboy: alex_baranosky: but how can i pass in arbitrary "lettings"?

21:21 alex_baranosky: your example is just 'let

21:21 Raynes: alex_baranosky: For a moment there I felt like I was playing madgab.

21:22 bhenry: goodieboy: what are you trying to do?

21:22 goodieboy: so yeah, sorry... that example doesn't describe what it is i'm trying to do fully

21:22 bhenry: ,(let [one 1 two 2]

21:22       (str "1 => " one " and 2 => " two))

21:22 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: EOF while reading>

21:23 alex_baranosky: goodieboy: create a nicer example, and I'm sure someone will help out

21:23 bhenry: that's a head scratcher

21:23 goodieboy: yes you're right, let met create a better example :)

21:24 alex_baranosky: Raynes: typing's a mofo sometimes ;)

21:25 cemerick: devn: hi

21:28 goodieboy: man, this is still probably a bad example, but what I'm trying to do is create a little dsl, and provide bindings for various values that might be needed within the body: https://gist.github.com/1387726

21:31 brehaut: goodieboy: you are using a macro so you can override or in the context of the query?

21:32 cemerick: hiredman: sexps are only beneficial if both sides of a connection are Clojure (or some other lisp, at a minimum) and you only care about pushing around the structures supported by the flavor of sexprs you choose, i.e. no efficient binary

21:33 goodieboy: brehaut: well, overriding or is not really what i'm doing specifically, but what I was hoping to illustrate is that I don't want to eval the code immediately, so I need a macro

21:34 i'm probably not thinking about this correctly, i guess i'm more curious about how you can create bindings that the body of a macor (when evaluated) can have access to?

21:34 err, macro :)

21:35 brehaut: goodieboy: do you understand (defmacro bogo-let [bindings & body] `(let ~bindings ~@body))

21:36 chouser: this must be some circle of hell Dente never imagined

21:36 goodieboy: brehaut: ahh yeah, i just tried something very similar!

21:37 amalloy: chouser: i'm trying desperately to come up with a dental pun here

21:37 chouser: heh

21:37 oops

21:37 brehaut: goodieboy: macroexpand and macroexpand-1 are your friends

21:38 pandeiro: hiredman: implemented string-to-bytes with reduce but how do i deal with the case of a char larger than one byte? http://sprunge.us/OieA?cl

21:38 chouser: I'm trying to port some code to Clojure 1.3, but it uses a lib that needs some tweaks, which uses a lib that needs some tweaks

21:38 amalloy: chouser: that's pretty much been the 1.3 story for months

21:38 chouser: ...so now I'm debugging build failures in a maven projects three levels deeper than I care about.

21:38 goodieboy: brehaut: geez, that was too simple in the end. thanks for that.

21:39 brehaut: goodieboy: clojure has a bunch of ways of delaying evaluation beyond macros too. functions are the most obvious, but also delay and force are worth you looking at

21:39 duck1123: chouser: there was a time when just about every lib I depend on was like that

21:40 goodieboy: brehaut: cool thanks, i'll be sure to check those out

21:40 duck1123: thankfully, It's much better now

21:40 chouser: I take back everything I ever said about enjoying breaking other peoples' code.

21:40 amalloy: brehaut, goodieboy: delay and force are just macros on top of the *real* way to delay evaluation, which is just wrapping something up in a function

21:40 brehaut: amalloy: of course; but theres no sense reinventing that

21:41 chouser: I don't mind so much fixing clojure code, but build errors drive me a bit crazy.

21:42 brehaut: chouser: i thought you were talking about being demoted by chanserv. build is definately a more hellish circle

21:42 duck1123: chouser: Especially when you find yourself asking "how did this ever work in the first place?"

21:43 chouser: amalloy: any new thoughts on macroexpansion metadata?

21:43 duck1123: yeah, exactly

21:43 one of the few really solid benefits of gentoo was if you could install it, you could build it.

21:44 not true in .jar land, is it. :-(

21:45 amalloy: the non-meta part of the form passed to a macro is only input, and what the macro returns is exactly the output

21:45 the current proposal has metadata being the input and also clobbering the output

21:45 amalloy: chouser: i don't htink i understand the significance of that statement

21:46 ah. i didn't wait long enough, i see

21:46 chouser: sorry

21:47 maybe patching defmacro was the right approach, because then there could be a new defmacro (defmacro* ?) that has the old behavior, that is gives the macro full control of the output.

21:48 amalloy: i don't think it makes sense to think of it as clobbering the output. it's just a compile-time assoc, right? it's like (-> some-map (f) (assoc mykey myval))

21:48 chouser: amalloy: yes, but (f) has limited control of the final output

21:48 amalloy: the caller is explicitly saying, "i need this form to have metadata X", so they assoc it in before they "look at" the result of macroexpansion

21:50 ninjudd: cemerick: so i take it you're opposed to establishing a separate channel for communicating binary data?

21:50 chouser: hm, it is true that a macro can has plenty of other ways to accept input. besides all the args, it has metadata on the args and on its own name

21:52 cemerick: ninjudd: not opposed, but such things get really complicated, especially if the REPL server is on a remote environment. Port privileges, firewalls, an implementation hurdle for clients and tools…

21:52 So, ok, maybe opposed :-)

21:52 brehaut: why not just http over spdy

21:52 (only mostly joking)

21:53 amalloy: chouser: i agree there's a place for something like defmacro* but it seems extremely uncommon to want to ignore metadata that the caller has put on the form

21:53 chouser: but it wouldn't be ignoring it necessarily. It could be taking it as input and doing something else with it.

21:53 cemerick: brehaut: carrier pigeon would resolve the firewall and port issues. :-P

21:54 ninjudd: cemerick: yeah. base64 encoding sounds way simpler that all that

21:54 Raynes: chouser: You're so adorable. I saw hiredman's origin-of-clojurebot IRC log where you said that an IRC bot would annoy people.

21:54 chouser: ^Foo (mac) --> (do ^Foo (that thing) (this thing))

21:54 Raynes: Three years later and we would all curl up and die if the evalbots disappeared.

21:54 cemerick: ninjudd: which is dreadfully slow, even using the fastest base64 impl :-/

21:54 ninjudd: yeah

21:55 chouser: clojurebot: do you annoy people?

21:55 amalloy: chouser: i've been having trouble constructing a form where this sort of behavior is useful, and i don't think yours is an example

21:55 clojurebot: min people is 5

21:55 chouser: amalloy: heh.

21:55 amalloy: hinting the return value of a form that doesn't get used is useless

21:55 chouser: amalloy: good point

21:55 brehaut: cemerick: lol

21:56 amalloy: i see what you're saying though. in the current system you can have a "back channel" to talk to the macro by settings its &form metadata to control how it behaves in some other way, without setting a typehint in your expansion context

21:56 chouser: Raynes: do you have a link?

21:56 Raynes: http://clojure-log.n01se.net/date/2008-11-21.html#13:04

21:56 chouser: amalloy: that's what I'm saying, but I'm not at all sure it's important

21:57 What metadata on an expression matters to the compiler besides the type hint, line number, and filename?

21:57 duck1123: ahhh... memories

21:57 amalloy: i think it's probably not, especially with your CRAZY hack of setting metadata on the macro's own name

21:58 chouser: i'm not sure. i haven't read the whole compiler, but those are the only three that stick out to me

21:58 chouser: Hm -- that's interesting. What if we turned the exception around and only applied :tag, rather than applying everything other than :line and :file?

21:58 amalloy: chouser: static, inline, dynamic

22:00 chouser: those are on var names, right? places where a macro can't expand anyway?

22:00 hugod: is there a clojure wrapper for WeakHashMap?

22:00 amalloy: chouser: as far as i know that's correct. i'm just listing relevant keywords in Compiler.java

22:00 chouser: hm

22:01 amalloy: chouser: i don't see any immediate failure cases for applying only :tag. i keep *thinking* it would be a problem if some external macro needed to mess with the metadata, but macros go outside-in

22:01 chouser: Raynes: I think you're misrepresenting my reaction. But you called me adorable so I guess I'll let it slide.

22:02 amalloy: i guess: ^{:foo 1} (macro1) => ^{:foo 1} (macro2)

22:03 is a cause that might break: you put meta on macro1 in order to get it to macro2, which looks at its &form meta

22:03 chouser: ooh, interesting.

22:03 amalloy: and you lose that ability if we only apply :tag

22:03 chouser: right

22:04 amalloy: not clear to me that this is an important ability, of course :P

22:05 well. i guess that wouldn't work in the current setup unless macro1 looked at its &form also

22:06 chouser: yeah, we've got one clear point -- the default case can be better. The consequences of making it always work that way for :tag or for other metadata is all vague.

22:06 amalloy: and if it *is* looking at &form, then it must be setting meta on its return value to get it macro2, and that would still work under your proposal. so we wouldn't break an existing usage by applying only :tag, we'd just lose the automatic-forwarding through a "dumb" macro1 to a "smart" macro2 that my original patch adds

22:07 chouser: does that argue for a change of smaller impact now? re-apply :tag for now, and add others either individually or en masse later?

22:07 amalloy: hmmmm

22:08 chouser: BTW, this is me just practicing at careful design. I assume whatever we come up with will be shot full of whole later in the process.

22:09 amalloy: well, i shot a bunch of holes myself by writing three patches. so i appreciate the goal

22:09 chouser: Not that the proposal won't ultimately be accepted, just that no matter how hard I work at careful design I seem to have blind spots for gaping holes elsewhere.

22:10 amalloy: chouser: i'm actually not sure whether adding just :tag is more or less likely to be accepted. it's smaller-impact, but has more "specific" things we could have gotten wrong

22:11 chouser: well, one last thought. If we did want to support defmacro* in the future, I wonder if it would be worth abstracting the applyMacro bit so that both macroexpand and add-meta could use it

22:11 I've gotta run. ttyl

22:11 amalloy: night, thanks

22:12 didn't understand that last point but not exactly urgent

22:13 reiddraper: in the definition of a type, what's the difference between (.seq this) and (seq this), if I've implemented the seq func for IPersistentSet?

22:14 amalloy: reiddraper: the latter routes through clojure.lang.RT but ends up the same place

22:14 reiddraper: amalloy: thanks

22:50 Raynes: Man. Why is fogus never here?

22:57 jcromartie: Raynes: dance class?

22:57 Raynes: Eh?

23:02 duck1123: I just spent a good 45 minutes debugging a tricky set of multimethods I have only to just now realize I had the order of arguments wrong for one of them.

23:02 go little used code

23:03 amalloy: duck1123: better than discovering a library author changed the argument order in an update, at least

23:06 duck1123: true. I have this series of multimethods that return different values depending on the value of two other dynamically bound values. For the longest time, I used two convenience macros for setting them up, but when I created a macro merging the two, I got the order backwards from how I had used it elsewhere

23:21 reiddraper: What determines how a type looks when it's printed at the repl? The result of pr on that obj?

23:21 I've made my own type and I'm curious where the look of it printed is coming from

23:23 amcnamara: amalloy: subtle.

23:23 brehaut: reiddraper: print-dup (a multi)

23:25 reiddraper: brehaut: and is there a way to see which func it's being dispatched to?

23:27 brehaut: reiddraper: i dunno. /me dives into source

23:27 amalloy: &(apropos 'method)

23:27 lazybot: java.lang.RuntimeException: Unable to resolve symbol: apropos in this context

23:27 amalloy: dangit brehaut, how do you use that thing

23:28 brehaut: $(use 'clojure.repl)

23:28 &(use 'clojure.repl)

23:28 lazybot: ⇒ nil

23:28 brehaut: (apropos 'method)

23:28 &(apropos 'method) ; excuse me while i fail a lot

23:28 lazybot: ⇒ (clj_http.core.proxy$org.apache.http.client.methods.HttpEntityEnclosingRequestBase$0 make-service-method remove-method find-protocol-method defmethod -reset-methods remove-all-methods prefer-method method-sig methods print-method get-method wrap-method)

23:28 amalloy: get-method

23:29 &(get-method print-dup '(1 2 3))

23:29 lazybot: ⇒ nil

23:29 amalloy: feh

23:29 brehaut: &(keys (methods print-dup))

23:29 lazybot: ⇒ (nil clojure.lang.PersistentVector java.util.regex.Pattern java.lang.Number clojure.lang.IPersistentList clojure.lang.Fn clojure.lang.PersistentHashMap java.lang.String java.lang.Character clojure.lang.ISeq java.lang.Double clojure.lang.BigInt clojure.lang.Ratio ja... https://gist.github.com/1387884

23:30 reiddraper: amalloy: yeah I get nil too in my repl

23:30 amalloy: oh, right

23:30 brehaut: it'll probably fall through to a default?

23:30 amalloy: &(get-method print-dup (class '(1 2 3)))

23:30 lazybot: ⇒ #<core$fn__4992 clojure.core$fn__4992@be0cd7>

23:30 brehaut: actually, clojure.lang.IRecord

23:30 is a likely candidate

23:31 amalloy: IRecord? is that in 1.3?

23:32 brehaut: i guess it must be, my 1.2 repl isnt finding it

23:32 https://github.com/clojure/clojure/blob/master/src/clj/clojure/core_print.clj#L217

23:33 so it turns out there is a crap ton of detail in what implementation is chosen for a particular type

23:34 and i see that a) im missing a bunch of the specially named characters in inc-clojure-brush and that b) the pygments brush is missing them all

23:34 amalloy: specially-named characters? you mean like \newline?

23:34 brehaut: yeah

23:34 amalloy: i covered those in pygments

23:34 brehaut: https://github.com/clojure/clojure/blob/master/src/clj/clojure/core_print.clj#L248-253

23:34 amalloy: \, followed by either any single character or a-z+

23:35 brehaut: amalloy: perhaps github isnt using the latest version of the brush ?

23:35 amalloy: brehaut: they updated to my version at least. are you sure it's pygments and not their css?

23:36 reiddraper: brehaut: thanks, looks like it's getting called here https://github.com/clojure/clojure/blob/master/src/clj/clojure/core_print.clj#L240

23:36 for my type

23:36 brehaut: amalloy: yeah, the spans are wrapping (for example) '\n' a 'ewline' 

23:37 amalloy: oh. i bet i just did it in the wrong order

23:37 brehaut: reiddraper: bonus lesson: the clojure clojure source code is pretty readable

23:37 amalloy: (.|[a-z]+), instead of the other way round

23:37 brehaut: oh true, that'd do it

23:37 reiddraper: brehaut: yeah I'm finding that out :)

23:37 brehaut: now you have two problems

23:38 amalloy: im going to copy your rule for my brush

23:38 much easier than hardcoding a bunch of names

23:38 amalloy: brehaut: copy+fix it, plz :P

23:38 brehaut: amalloy: ha yes :P i have no regexp though, so i wont fall into the same trap ;)

23:38 amalloy: clever

23:39 brehaut: i did it for speed more than correctness :P

23:39 reiddraper: brehaut: so I think we're calling get-method wrong

23:39 brehaut: (all though as a side effect it fixed a couple of really curly bugs)

23:39 reiddraper: the last arg should not by the obj, but the result returned from defmethod

23:39 err defmulti

23:40 amalloy: reiddraper: that's what i did the second time

23:40 &(get-method print-dup (class '(1 2 3)))

23:40 lazybot: ⇒ #<core$fn__4992 clojure.core$fn__4992@be0cd7>

23:40 reiddraper: amalloy: oh yes, sorry I missed that

23:40 alexbaranosky: say you wanted to mock any arbitrary java method call, how would you go about it?.... I ask because I'm looking for ideas on good ways to add the ability to do this to Midje

23:43 amalloy: alexbaranosky: am i implementing the feature or using it?

23:43 brehaut: amalloy: damnit. im still going to need to explicitly check for &amp; &lt; and &gt; . what a pita

23:43 alexbaranosky: amalloy: depends on your enthusiasm level

23:43 amalloy: i mean, what is the question you're asking

23:43 brehaut: now i have to catch a bus

23:44 alexbaranosky: I want to make it so that in midje you can say (fact (foo 2) => 8 (provided (.size bar) => 40)

23:45 amalloy: I'm wondering what some approaches to that problem might work under the hood

23:46 amalloy: and the thing you're mocking is some java object that has to continue behaving the way it already does except for this change?

23:47 alexbaranosky: amalloy: well there are different possibilities: what you're describing is usually called a spy

23:47 amalloy: but the standard is to assuem a mock is a totally new object, that only does the stuff you specified

23:47 amalloy: thus, we don't need to preserve behavior

23:48 duck1123: it would be nice though if you could mock only a particular method

23:48 amalloy: well. if you can require the user to provide a class or interfaces that this thing should extend/implement it's not hard

23:48 alexbaranosky: duck1123: yeah we could have spies too perhaps???

23:48 lazybot: alexbaranosky: Oh, absolutely.

23:48 amalloy: but we can't just add arbitrary methods to an object/class like we could in ruby or java

23:49 one possibility is to define an interface on the fly, with the methods you want, and then return a reification of that interface

23:49 duck1123: or java?

23:49 amalloy: duck1123: by just making up a new class that has those methods

23:49 alexbaranosky: it could looks something like: (provided (.size ^Bar ...bar...) => 40) maybe?

23:49 amalloy: clojure's class-creation demands interfaces

23:50 duck1123: ahh, rspec handles this kind of thing quite nicely

23:50 amalloy: alexbaranosky: (provided (mocking bar IBar (.size [this] 10)))?

23:51 ie, you want the syntax to look exactly like reify

23:51 which makes it easy for users to understand, and easy for you to transform to a reify

23:52 alexbaranosky: amalloy: I'm not as much concerned about ease of transforming to reify, but am definitely very concerned about people understanding the API

23:53 amalloy: alexbaranosky: your => 40 syntax fits better with the rest of midje, but doesn't really "scale" to mocking multiple methods as far as i can tell

23:54 alexbaranosky: amalloy: in midje you can already say things like: (fact (x) => 1 (provided (foo) => 2 (bar) => 3 (baz) => 4))

23:54 amalloy: and neither syntax really handles the possibility that they need to extend a concrete class

23:55 alexbaranosky: extending concrete classes, in my mind is a rare except I haven't done it in months home or at work

23:56 duck1123: I guess your best bet is to adjust your function lines till you can easily pass in mocked out classes for the inner functions and use traditional midje mocking for the rest

23:56 amalloy: agreed, but you're trying to provide a facility for mocking java objects. those objects aren't always designed as clojure-friendly

23:57 alexbaranosky: you make good points

23:57 duck1123: is there a clojure wrapper for jmock?

23:57 alexbaranosky: what do you think of?: (fact (x) => 1 (provided (.foo IFoo f) => 2 (.bar IBar b) => 3 (.baz IBaz bz ) => 4))

23:58 duck1123: I haven't gotten around to playing with that yet

23:58 alexbaranosky: midje could identify these as method calls by their symbol names

Logging service provided by n01se.net