#clojure log - Jan 16 2010

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

0:34 * qbg used dosync inside a macro definition, and feels scared

0:38 Apage43: mm.

0:39 Niftily, calling .invoke on clojure function from within Velocity Template Engine just plain works.

1:47 ndimiduk: I'm working on some java interop. How do I specify as metadata that a function parameter should be of type Class[] ?

1:48 (defn -init [#^Class[] types] ...) is roughly what i'd like to express

1:48 or do constructor argument type lists go somewhere else?

1:50 qbg: Does an array of objects not work for you?

1:50 ndimiduk: i suppose it could

1:51 that would make the class less clear for java consumers

1:54 oh, i should clarify: this is extending a base class which has multiple constructors of single argument with differing types

1:55 so i'd like the appropriate version of -init to be called based on which constructor is invoked

1:56 Apage43: ndimiduk: perhaps you'd do well to write some 'briding' classes in Java, since it sounds like you aren't exposing a terribly 'lispy' API anyhow.

1:57 ndimiduk: hmm

1:57 Apage43: *bridging

1:58 ndimiduk: right

2:00 ah, gen-class says i should specify :constructors {}

2:00 so would I say :constructors {[] [String] [Class<>]} ?

2:56 rikthevik: hey, i'm having trouble getting lein to run my tests

2:56 Caused by: java.lang.Exception: No such var: clojure.test/successful?

2:57 thoughts?

3:02 Jomyoot: How can I get stack trace to compojure

4:18 bagucode: Hello all

4:47 lypanov: damn, elpa isn't the most reliable thing ever...

5:06 how do i get a pretty print out of the available methods for a given namespace?

5:07 (doc *) is neat but i'd expect (doc ns) to work actaully. and for it to pretty print the first line of each doc for the ns-publics result

5:07 clojurebot: "([] [x] [x y] [x y & more]); Returns the product of nums. (*) returns 1."

5:07 lypanov: heh

6:01 dabd: are there any guidelines for writing clojure doc strings?

6:01 for when someone writes clojuredoc...

11:48 michael___: I went to a great presentation by Michael Fogus on Clojure 1.1 and 1.2 features.

11:49 * chouser would have loved to be there.

11:50 * the-kenny too

11:50 michael___: I'd like to dive into some of them, especially the new concurrency constructs like futures and promises. I'd also like to explore reify deftype and defprotocol.

11:50 I'm blanking on good applications for small projects, though.

11:51 Any suggestions? I'd like to do something a little involved and practical, to apply these new features

11:51 We would have loved to have you there, chouser

11:52 chouser: hm, practical and small is a hard combination.

11:52 michael___: I've looked at your Project Euler solutions in the past

11:53 I don't know if Euler is a good source for this, tho

11:53 chouser: michael___: A nice thought. Half a continent away though. :-/

11:54 michael___: chouser: at least we know how to pronounce your name, now, thanks to fogus

11:54 chouser: for deftype all you need is to think of some new structure that you want to play nicely with clojure's builtin fns like seq

11:54 michael___: good point

11:55 Is anyone using these features in their work or own projects right now?

11:57 chouser: perhaps nobody who is here on saturdays :-)

11:58 michael___: LOL

11:58 I'll think about it some more and ask Google some more. Thanks!

12:08 dabd: when u need to bind a variable 'foo' which is based on another similar variable, do you consider good style to give it the same name or is it better something like foo2

12:09 example (defn f [foo] (let [foo2 (some-fn foo)] (println foo2)))

12:09 chouser: dabd: It's a bit of a judgement call of course, but it's not always bad to reuse the same name.

12:10 I guess I'd say there's no much point in sticking a 2 on there if that's the best new name you can com up with. :-)

12:10 dabd: i tend to append an asterisk to the original name but it can be confusing and error prone

12:10 qbg: If the shadowing doesn't affect me, I reuse the name

12:10 (assuming the original name still makes sense)

12:17 lypanov: whats the best way to connect to a mysql db with clojure?

12:17 its for data extraction, no writing.

12:17 need a batch access method therefore.

12:19 tolstoy: lypanov: Can you just shell out to the mysql client?

12:20 (Assuming you don't want to use the contrib.sql / jdbc stuff.)

12:20 lypanov: contrib.sql is an option, i just can't find others with a quick google :)

12:21 tolstoy: I think there's a ClojureQL.

12:21 lypanov: ah, thats the one. thx! reading up on it

12:23 dabd: sometimes I think it would be nicer to have only parenthesis as the delimiters and read macros for vectors #V, maps #M, sets #S, and so on. Does anyone agree?

12:24 OTOH for readability Clojure syntax is great. The single delimiter syntax would make code editing slightly easier IMHO

12:25 I used Common Lisp for some time so I'm a suspect...

12:25 tolstoy: I think of [ and { as '( and find it's easy to get away with thinking like that most of the time.

12:25 chouser: dabd: you'd really want (let #V(a 10 b 20) (+ a b)) ?

12:26 tolstoy: beware that '

12:26 [ and { are semantically a bit closer to (list I think

12:27 tolstoy: I guess that's sorta what I was thinking, but yeah, you're right. Obviously, I use clojure pretty simply.

12:28 dabd: chouser: like I said I used Common Lisp for some time. For instance when ending a function definition in CL I just closed all parenthesis in row on the same line. However with clojure because we have different delimiters I feel the need to close them 'a la' Java.

12:29 rikthevik: has anyone here got experience with "lein test"?

12:29 dabd: each one on a different line so they don't appear all mixed up on the same line

12:29 rikthevik: No such var: clojure.test/successful?

12:29 chouser: dabd: it's a point that's been mae before, though that's the first I've seen your #V suggestion.

12:29 been made

12:30 but please don't put your closing parens on different lines! :-)

12:32 dabd: chouser: if I have several ) in a row I don't put them on the same line but if a } or ] I think it looks ugly to close them all on the same line )))]})))) like this

12:33 chouser: the #V is clearly stolen from Lisp and I'm sure Rich Hickey thought about this when creating clojure and it's syntax

12:34 chouser: I will follow the conventions and close them on the same line though!

12:38 tolstoy: dabd: Wasn't part of the goal with clojure to appeal a little to users of other dynamic languages?

12:39 So you get brackets for arrays, braces for maps, commas....

12:43 stuartsierra: In Clojure 1.0, conj on a vector does not preserve metadata. Is that a bug?

12:43 In Clojure 1.1, conj on vectors does preserve metadata.

12:44 dabd: tolstoy: sure it was

12:45 alec: how can I check if an item is in a list?

12:46 stuartsierra: ,(some #{:a} (list :b :a :c))

12:46 clojurebot: :a

12:47 stuartsierra: ,((set (list :b :a :c)) :a)

12:47 clojurebot: :a

12:48 alec: stuartsierra: hm, ok. I also just stumbled upon (.contains (list :a :b) :a), which seems to work

12:49 stuartsierra: alec: In general, if you're testing whether or not a list includes something, consider using a set instead of a list.

12:50 aldebrn: Can I experiment with clojurebot in a test channel? I want to see if I can ask the humans a question with a case example

12:50 Ah, I can message it directly

12:53 lypanov: ouch. search doesn't show all matches on clojars.org.

12:56 is there any way to get emacs to make its current state a bit more obvious?

12:56 frequently i end up getting lost in weird modes

12:56 the-kenny: lypanov: The modes are shown in the info bar

12:56 lypanov: And you can cancel almost everything with Esc Esc Esc

12:56 (Or C-g)

12:57 lypanov: ah, finally. thank you!

12:57 no... it did it again. vi-mode just randomly ending. !@#@$%

12:58 the-kenny: I don't have any experience with vi-mode, sorry

13:00 aldebrn: ,(for [val '(1 2 3 4 5)] (let [big-enough? #(> %1 val)] (big-enough? 3)))

13:00 clojurebot: (true true false false false)

13:00 aldebrn: Why does that no work if instead of (big-enough? 3) there I called another function that used big-enough? ?

13:01 Chousuke: hm?

13:02 aldebrn: So if I had (foo 3) instead of (big-enough? 3) there, and I had previously defined (defn foo [x] (big-enough? x)) and (defn big-enough? [x] (> x 0)), calling that "for" comprehension would use this latter definition of big-enough?

13:03 Instead of the new big-enough?'s I was defining in the let

13:03 alec: stuartsierra: thanks, that actually made the problem a lot easier. I did't even need to do that check.

13:04 lypanov: the-kenny: i found out why... thought vip-mode == vi-mode

13:04 ben_m: Could anyone who uses Clojure with Emacs/Slime give me a sample .emacs? I just can't get it to work :(

13:05 Chousuke: aldebrn: let bindings are lexical, not dynamic

13:07 lisppaste8: qbg pasted "My .emacs" at http://paste.lisp.org/display/93500

13:07 the-kenny: ben_m: I suggest using elpa.

13:07 qbg: Has stuff you probably don't need

13:07 the-kenny: It's a no-brainer then

13:08 qbg: elpa helps

13:08 ben_m: hmm

13:08 aldebrn: Chousuke, thanks. So the functions I call from a let's expression will not be aware of let rebinding sub-functions that they will use

13:08 ben_m: qbg: thanks

13:08 qbg: I used to use ELPA, but now I manage my own copies

13:09 tolstoy: Does elpa have a mechanism for detecting and then applying updates to packages?

13:09 the-kenny: tolstoy: I modified slime.el and it detected my changes and asked me to recompile it

13:11 Chousuke: aldebrn: yeah. for that, you need the binding macro

13:11 tolstoy: the-kenny: So that solves the case of detecting that there's been an update to clojure-mode, or paredit, etc?

13:11 the-kenny: Not local update, but a new package up at the elpa site?

13:11 the-kenny: tolstoy: No, I don't know if it does that.. sorry

13:12 qbg: I think package-list-packages will fetch the new list from the server

13:12 (or there is another command)

13:12 tolstoy: elpa faq isn't helping....

13:12 Chousuke: aldebrn: note, though, that binding only affects code that actually executes within the binding block. thus, laziness is a caveat

13:12 qbg: Then you can select to install the new packages

13:13 tolstoy: qbg: If you've already installed a package, once you refresh, does it let you know there's a new version?

13:13 qbg: The old version is listed as obsolete and the new version is in the list

13:14 tolstoy: qbg: Ah, cool. I note that their front page says "upgrade". ;)

13:15 ben_m: baaah

13:15 It won't work!

13:15 tolstoy: Ah, I see two versions of erc (for instance). Interesting.

13:16 qbg: ben_m: What are you getting?

13:16 ben_m: Polling "/tmp/slime...." (abort with ...)

13:16 forever though

13:16 I don't get the CL-USER> prompt like I do with sbcl :(

13:17 qbg: What do you see in *inferior-lisp*?

13:18 ben_m: The clojure repl

13:18 ah

13:18 user=> java.io.FileNotFoundException: Could not locate swank/swank__init.class or swank/swank.clj on classpath: (NO_SOURCE_FILE:0)

13:18 robwolfe: ben_m: do you have "require 'slime" after elpa package.el is loaded?

13:18 ben_m: I don't use elpa

13:18 But I do require slime

13:19 qbg: Where is your swank-clojure?

13:19 ben_m: The dir?

13:19 qbg: The jar

13:19 It needs to be on the classpath

13:19 ben_m: I don't have that jar I think

13:19 qbg: Did get swank-clojure from git?

13:20 ben_m: yeah

13:20 qbg: Do you have leiningen installed?

13:20 ben_m: leiningen?

13:20 clojurebot: leiningen is a build tool designed not to set your hair on fire (http://github.com/technomancy/leiningen)

13:20 ben_m: I do not

13:20 qbg: Once you have it, do `lein jar` in the directory

13:20 That will build the jar for you

13:20 ben_m: Oh

13:21 qbg: Luckily leiningen is easy to install

13:21 rikthevik: I'm getting this error with "lein test". No such var: clojure.test/successful?

13:21 thoughts?

13:21 LauJensen: Gents I'm doing an experiment for which I need some help. Has anyone here got access to a public MS Sql databases which I can try to log into, run a select now(); and drop out again ?

13:22 ben_m: So leiningen is ant without the XML?

13:22 qbg: Or something

13:22 rikthevik: ben_m: and maven without the brain damage

13:22 qbg: (makes me think of ASDF)

13:22 ben_m: nice

13:23 I'm no fan of Java tbh, classpath makes me weep :D

13:24 qbg: Do I need swank.jar?

13:24 qbg: Something like that

13:24 the-kenny: swank-clojure.jar

13:25 ben_m: hmm

13:25 qbg: Actually, once you have it built, you can test it before altering your .emacs

13:25 lypanov: ben_m: classpath itself is a brillian idea. but tooling it is hard.

13:25 ben_m: No idea where to run lein jar

13:25 the-kenny: leiningen manages all classpath stuff for me :)

13:25 ben_m: There's no project.clj anywhere

13:25 lypanov: lein help new

13:26 qbg: From whose repo did you clone swank-clojure?

13:26 ben_m: Uh, can't remember :|

13:26 Whose should I clone it from?

13:26 lypanov: hope it wasn't the first google hit...

13:26 ben_m: It might have been.

13:26 lypanov: (the mistake i made last night)

13:26 ben_m: technomancy.

13:26 ben_m: Oh

13:26 lypanov: i used the first google hit, it breaks completely.

13:26 ben_m: I cloned it from joshua or something like that, I think.

13:27 lypanov: jochu.

13:27 qbg: Yeah, that is old

13:27 lypanov: yeah... made the same mistake.

13:27 ben_m: :/

13:27 * ben_m removes everything and starts over

13:27 lypanov: ben_m: you would have heard me say the same thing last night :P

13:27 qbg: ben_m: Some pain now, fun later ;)

13:27 lypanov: took me a bit longer to realize though.

13:28 ben_m: technomancy for clojure-mode etc also.

13:28 technomancy kept telling me last night to read the "clojure-mode readme. it explains everything"

13:28 after 2 hours i realized i was reading the wrong readme...

13:28 qbg: lol

13:28 ben_m: hah

13:30 dabd: why the naming inconsistency empty? vs. not-empty (one ends with ? and the other not)?

13:30 LauJensen: Functions ending with ? are predicates returning true/false, not-empty is not one such

13:31 the-kenny: not-empty returns nil or a coll

13:31 Not a boolean

13:31 dabd: ok. thanks

13:34 ben_m: Maybe I should check out ELPA

13:34 * ben_m sighs

13:34 LauJensen: why the sigh ?

15:26 qbg: Is this view of clojure correct? http://vintage-digital.com/hefner/misc/lisp-programmers.jpg

15:27 defn: i dont think so

15:28 PHP is dead on though

15:28 qbg: If Clojure is the Borg, who wouldn't want to be part of the Borg?

15:28 defn: me, because of the assimilation mostly

15:29 hiredman: http://www.loper-os.org/?p=42

15:29 qbg: Scotty is elisp?

15:29 I guess I can see that

15:30 hiredman: I think you a missing the fact that it is supposed to be from the perspective of a common lisp programmer

15:30 lypanov: i think i want to learn asp.net.

15:30 and make friends.

15:31 defn: yes! making friends!

15:31 i remember that!


15:33 defn: qbg: :(


15:39 somnium: alexyk: ping

15:40 bpsm: ain't nobody here but us chickens

15:40 ben_m: LauJensen: Mind linking your screencast again? I got distracted before.

15:41 LauJensen: Sure - but I'm moving the server from the US to London as we speak

15:41 I'll let you know when I'm done

15:41 ben_m: alright :)

15:48 LauJensen: ben_m: Looks like it'll be about 50 minutes

15:49 lpetit: Hello

15:49 ben_m: LauJensen: Alright, I'll try it on my own in the meantime :)

15:49 lpetit: Who wants to take the task of hosting clojure with Go ? ! :-) http://www.infoq.com/articles/google-go-primer

15:52 bagucode: lpetit: Making the data structures and reader should be straight forward enough. But then there is the issue of compilation. The ASM library and the classloaders provides that for the jvm. What would you use with Go? LLVM would be my choice I guess.

15:53 chouser: why not just generate golang source?

15:53 lpetit: What is LLVM ?

15:53 chouser: it worked well enough for javascript, seems likely it would work for golang

15:54 lpetit: chouser: how do you get, then the dynamicity of a REPL ?

15:54 chouser: oh. well. they claim their compiler is fast, right? :-)

15:55 lpetit: :)

15:55 bagucode: LLVM is a bunch of stuff. It's a portable assembly language with associated tools for optimization and compilation. It's pretty cool stuff actually. Since the compilation infrastructure is all libraries you can use it as a JIT compiler as well.

15:55 chouser: generate sources, compile to a .so, ldload, run

15:55 :-)

15:56 bagucode: LLVM is much cooler, no offline or source generation needed.

15:56 lpetit: chouser: in which state is "clojure hosted on javascript" (don't know the exact name), btw ?

15:56 bagucode: It's like ASM + classloader, but for native code

15:56 lpetit: bagucode: looks very interesting !

15:56 bagucode: But ... what would be the point of implementing clojure on top of Go? Hotspot is already very fast actually. Memory consumption maybe?

15:57 chouser: lpetit: clojurescript. a significant subset of clojure was working, but because lots of parts had to be hand-translated, clojure has moved on and clojurescript has been left behind

15:57 * lpetit votes for bagucode as the team leader of the hosting of clojure by go :-)

15:57 lpetit: chouser: do you consider reactivating the project once cinc has become a reality ?

15:57 chouser: absolutely

15:58 lpetit: wonderful! Oh, I would need it by monday, if possible.

15:58 I once had the idea of calling the eclipse plugin for clojure : "Ectoplasm".

15:59 I guess when cinc has become a reality, this name could pretty well describe the phenomenon : clojure the ectoplasm attacking each and every platform which already has a story for gc and threading ! :)

16:00 chouser: hm, I'd rather it not be so restrictive.

16:00 though maybe it's obvious to people who know gc better than I that simple reference counting won't cut it.

16:01 bagucode: Well, it's certainly much less work to not have to do the GC :)

16:02 lpetit: yeah, even if doable in practice, I guess no gc would be a blocker for most people

16:02 s/in practice/in theory/

16:03 bagucode: I think Apple actually open sourced their multithreaded Objective-C GC. I think it's written in C or C++ so it's usable by pretty much any language implementation.

16:03 I looked at it briefly but couldn't find much documentation

16:03 :(

16:04 chouser: how would llvm interact with golang?

16:04 bagucode: llvm has a C interface so just call that from Go

16:05 It has functions for instruction generation sort of like ASM does

16:05 Then you say something like ExecutionEngine.getFunction(blah blah) and you get a pointer to you new native-compiled function

16:06 ben_m: Woo

16:06 bagucode: I have actually used LLVM from Clojure ;) I'm crazy that way.

16:06 ben_m: LauJensen: nevermind!

16:07 I used ELPA and let it install clojure, works now :)

16:07 LauJensen: k

16:07 jevgeni: hi guys. I tried (+ 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1) with resulted in 0.9999999999999999. I know this is a very old Java problem, but what was the reason it was not fixed in Clojure (compared to Groovy/Scala)?

16:10 bagucode: chouser: I don't know if you remember but I said that one of my motivations for clj-native was that I wanted to use a C library with a large amount of small functions. That was LLVM, I was playing around with it at the time. Both the C and C++ interfaces for it are horrible and I thought that if I could use it from Clojure I could make some sort of assembler dsl that would make it more pleasant :)

16:12 gregh: jevgeni: there's nothing to "fix", that's how computers do arithmetic

16:12 the reason is that 0.1, although it looks nice and round in decimal, can't be represented exactly in a binary fraction

16:13 ben_m: The "fix" is to use a library

16:13 Chousuke: ,(+ 0.1M 0.1M 0.1M 0.1M 0.1M 0.1M 0.1M 0.1M 0.1M 0.1M)

16:13 clojurebot: 1.0M

16:13 Chousuke: Bigdecimals :P

16:13 gregh: an excellent article on the topic is: http://docs.sun.com/source/806-3568/ncg_goldberg.html (What Every Computer Scientist Should Know About Floating-Point Arithmetic)

16:13 ben_m: :D

16:13 qbg: You could also use rationals

16:14 ,(+ 1/10 1/10 1/10 1/10 1/10 1/10 1/10 1/10 1/10 1/10)

16:14 clojurebot: 1

16:14 Chousuke: hmm

16:14 ,(+ 1 1/10

16:14 clojurebot: EOF while reading

16:14 jevgeni: gregh: yes, I know this. however, you don't save 0.1M or 1/10 in databases. I am worried about the integration with the exising datasources and performing operations on these values.

16:14 Chousuke: ,(+ 1 1/10)

16:14 clojurebot: 11/10

16:15 Chousuke: jevgeni: There's nothing Clojure can do about Java's Doubles :/

16:15 gregh: a common way to avoid the problem in situations such as financial calculations, is to store all values in integer numbers of *cents* instead of dollars (for example) and do all integer calculations

16:16 jevgeni: theoretically, can I redefine the + to represent 0.1 as bigdecimals?

16:16 Chousuke: just use 0.1M

16:16 gregh: or integer numbers of tents of cents if you want to handle rounding yourself

16:16 Chousuke: This only applies to literals anyway.

16:16 if you get a double from some API, then you have to deal with the imprecision

16:16 there's no way around it

16:17 You need to complain to the API creators to make one that gives you BigDecimals :P

16:17 hiredman: jevgeni: why don't you have 0.1M or 1/10 in databases?

16:18 jevgeni: hiredman: it's already saved as float number. a big legacy system to integrate)

16:18 hiredman: well

16:19 you are screwed if you are already using floats

16:19 and have been since the beginning

16:19 bagucode: jevgeni: so convert the numbers to rationals or bigdecimals when getting them from the DB then and at least the errors won't compound more?

16:20 ,(rationalize 0.1)

16:20 clojurebot: 1/10

16:20 hiredman: it's the kind of error there isn't any recovering from

16:20 jevgeni: bagucode: thanks for hint

16:21 Chousuke: hmm

16:21 hiredman: you can't tunnel to the past and make things precise

16:21 Chousuke: ,(rationalize 0.18923893)

16:21 clojurebot: 18923893/100000000

16:21 gregh: ,(rationalize (+ 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1))

16:21 clojurebot: 9999999999999999/10000000000000000

16:21 bagucode: :D

16:22 ,(reduce + (map rationalize [0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1]))

16:22 clojurebot: 1

16:23 jevgeni: (class (+ 1.5M 1.5))

16:23 ,(class (+ 1.5M 1.5))

16:23 clojurebot: java.lang.Double

16:24 jevgeni: (class (+ 15/10 1.5))

16:24 ,(class (+ 15/10 1.5))

16:24 clojurebot: java.lang.Double

16:24 alec: can a java array returned by something like String.split be converted into a clojure list?

16:24 lpetit: ,(apply + (map rationalize [0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1]))

16:24 clojurebot: 1

16:25 lpetit: alec: sure

16:26 ,(into () (.split "hello you" " "))

16:26 clojurebot: ("you" "hello")

16:26 lpetit: ,(type (into () (.split "hello you" " ")))

16:26 clojurebot: clojure.lang.PersistentList

16:26 alec: lpetit: ah, cool. thx

16:26 lpetit: you would rather prefer putting it in a vector, though, to preserve the array order :

16:26 > ,(type (into [] (.split "hello you" " ")))

16:26 ,(type (into [] (.split "hello you" " ")))

16:26 clojurebot: clojure.lang.PersistentVector

16:27 lpetit: ,(into [] (.split "hello you" " "))

16:27 clojurebot: ["hello" "you"]

16:27 lpetit: alec: vectors preserve the constant time access to their contents by index. accessing lists by index is done in linear time.

16:28 ,(doc list)

16:28 clojurebot: "([& items]); Creates a new list containing the items."

16:28 lpetit: ,(doc nth)

16:28 clojurebot: "([coll index] [coll index not-found]); Returns the value at the index. get returns nil if index out of bounds, nth throws an exception unless not-found is supplied. nth also works for strings, Java arrays, regex Matchers and Lists, and, in O(n) time, for sequences."

16:28 qbg: ,(vec (.split "hello you" " "))

16:28 clojurebot: ["hello" "you"]

16:28 Chousuke: of course, if you don't need a vector:

16:28 ,(seq (.split "hello you" " "))

16:28 clojurebot: ("hello" "you")

16:29 lpetit: Chousuke: :is it "cheaper" in terms of memory or cpu to use seq instead of vec (assuming you want to consume the whole thing) ?

16:32 bagucode: Good question. Without looking at the source I think that's hard to answer. The seq from the array is a wrapper object right? So that introduces some overhead. The vector is a little heavier object than the array, but on the other hand it is it's own sequence, so it shouldn't add any overhead to call seq on it? I'm just speculating I haven't looked at the implementation so don't listen to me :)

16:35 Chousuke: lpetit: Hm.

16:35 lpetit: vec needs to copy the array, so I think it's slower

16:36 though it might be that vec just assumes ownership of it and "lazily" wraps it in a PersistentVector-like interface

16:36 but I guess seq would be faster

16:37 lpetit: Well, one also has to consider that alec wants to wrap an array. So depending on his use case, snapshotting the array content into a vector may be safer than relying on the array never changing and just having a seq over it

16:37 I also guess that seq over an array only has to store a ref to the array and an index, so yes, certainly much cheaper

16:38 But anyway, wouldn't the array work "as is" with most core functions working on seq, since they call (seq) on their arg, don't they N

16:38 ?

16:38 Chousuke: yeah

16:38 LauJensen: bestinclass.dk is back up again, now serving from London

16:38 Chousuke: I had some adventures with my brand new QNAP NAS today

16:39 I managed to brick my Debian installation on it. had to set up a dhcp/tftp server and restore from a backup firmware image ;/

16:40 Good thing I didn't have to resort to using a serial console, though.

16:41 rebooting things accessible only via the network is rather... stressful

16:47 LauJensen: Yes sir

16:47 bagucode: LauJensen: I just scrolled through your blog archive and saw this "An official from Reddit has asked that sleeps be inserted into the code..." did they get hammered after that article?

16:47 LauJensen: I think so

16:48 I saw a comment on HN saying that they got a traffic boom

16:48 bagucode: Guess you have a lot of readers :)

16:48 LauJensen: Yes - I'm glad I started with a low entry bar, because it means that people not actually read the code, but they feel comfortable enough with it to download and play with it - thats pretty great considering this is Clojure and not some mainstream language

16:50 eh, rephrase "not actually read" = "not just read"

16:51 jevgeni: ,(* 100M 1.1)

16:51 clojurebot: 110.00000000000001

16:51 jevgeni: shouldn't 1.1 be converted to bigDecimal instead on BigDecimal converted to Double?

16:51 instead of*

16:52 alec: how can I combine two sets, ie, #(1 2 3} and #(4 5 6} go to #{1 2 3 4 5 6}

16:53 Chousuke: ,(into #{2 3 4} #{5 6 7})

16:53 clojurebot: #{2 3 4 5 6 7}

16:53 alec: Chousuke: ha, same function that answered my last question... thx

16:53 Chousuke: there's also clojure.set/union I guess

16:54 ~def clojure.set/union

17:23 dabd: is there a function that iterates each successive tail of a seq?

17:24 patrickdlogan: who's got the most current, accurate instructions for setting up slime / swank?

17:24 tried clojure-install in emacs - it said deprecated in favor of swank-clojure

17:24 esbena: patrickdlogan: use swank-clojure instead

17:25 dabd: I defined this trivial function to do it http://pastebin.com/m105bb8a8

17:26 patrickdlogan: esbena: yeah, went to swank-clojure and the README is still from May and says "step 2. invoke m-x clojure-install..."

17:26 esbena: so I should ignore the README?

17:27 esbena: patrickdlogan: I'm pretty sure I just used the installer in Emacs. Then it worked out of the box

17:39 chouser: ,(take-while seq (iterate rest [1 2 3 4]))

17:39 clojurebot: ([1 2 3 4] (2 3 4) (3 4) (4))

17:39 chouser: when did not-empty show up??

17:40 huh. it's old. :-/

17:42 dabd: chouser: take-while returns the sequence of tails. I just want to iterate them. perhaps I should wrap it in a dorun?

17:45 chouser: dorun also just returns them. what do you mean by "iterate them"

17:46 dabd: do something with each tail but not collect them

17:46 kotarak: dabd: doseq

17:46 dabd: what about this (defn do-tails [s f] (doseq [item (take-while seq (iterate rest s))] (f item)))

17:47 kotarak: dabd: that's just (doseq [item s] (f item))

17:48 dabd: ah no. it is not. Forget what I said

17:48 dabd: kotarak: yes I didn't name item properly it should be named tail

17:48 lpetit: ,(doc recursions)

17:48 clojurebot: Pardon?

17:48 lpetit: clojurebot: nevermind

17:51 Raynes: chouser: What are you guys using to write your book?

17:59 chouser: Raynes: knowledge we've gained through decades of research and hard work

17:59 :-)

17:59 Raynes: chouser: Heh heh.

17:59 I meant that rather literally.

17:59 :p

17:59 chouser: I'm mostly using vim. I believe fogus mostly uses emacs.

18:00 Raynes: I tried to use muse mode, but it doesn't seem to work right for me. :\

18:00 It looked awesome too.

18:00 Shame.

18:01 chouser: some of the first stuff was written in etherpad

18:02 Raynes: Using LaTeX or something?

18:03 chouser: Manning has a docbook-like xml format they like, and tools to generate pdfs as well as whatever they need to actually go to print.

18:03 Raynes: I see.

18:03 I'm clueless about book writing. :\

18:04 chouser: so we've developed a tool that converts a somewhat extended version of Markdown to Manning's XML format.

18:05 I was too! Apparently a lot of their books are written and prepared in MS Word.

18:05 Raynes: I've read up on some OOo stuff about book writing. Styling makes my eyes water. It all seems too complicated.

18:07 Muse-mode's documentation is thorough, but awful vague.

18:08 lpetit: dabd: your initial attempt was good too by not creating unnecessary sequences. I've just updated it to take into account that you want to eagerly consume it (so using next instead of rest), and getting rid of the loop to leverage the direct use of recur on the function: http://pastebin.com/m2725cd2d

18:10 dabd: though now that I think about it, keeping your initial version, replacing the initialization of s in the loop (loop [s s]) by (seq s) : (loop [s (seq s)]), and then replacing rest with next should do it. (will save the superfluous call to seq, which is unnecessary but for the initialization of s arg)

18:15 dabd: lpetit: I don't understand the difference between your 1st 2nd suggestions http://pastebin.com/m28155e0c

18:15 mkh: chouser: i bought your book yesterday, any chance of it being published in ePub format

18:16 maacl: I would like to create a function that returns a unique pseudo random length vector of pseudo random ints. A max length of the vector and max value of the ints should be definable. Any hints?

18:16 lpetit: dabd: in the second, (seq s) will be called just once, at loop initialization. in the first, it is called every time

18:18 dabd: lpetit: of course. thx

18:19 Chousuke: ,(vec (take (rand-int 10) (repeatedly #(rand-int 20))))

18:19 clojurebot: [14 12 0 2 2 14 8 13 13]

18:20 Chousuke: maacl: see above

18:20 dabd: lpetit: in practice this elegant functional version is very inefficient: both iterate and seq create sequences unnecessarily http://pastebin.com/m64eeb50b

18:21 maacl: Chousuke: thanks, but my challenge is the unique part, I am guessing a closure is the solution, but I cannot get my head around it

18:22 Chousuke: maacl: hmhm

18:22 maacl: you need to store the vectors in a ref I guess.

18:22 lpetit: dabd: yes, you only want side effects, and you know you want to go through the whole list eagerly, so you don't care about lazy seqs, you just want to iterate as quickly as possible. That's why I was considering that your initial attemp was more suited for defining such a general tool

18:23 qbg: maacl: A random length subseq of a permutation of 0 to n-1?

18:25 maacl: qbg: yes I believe so

18:25 qbg: If you define shuffle, the definition should be trivial

18:26 Something like (take (rand-int <num>) (shuffle (range <num>)))

18:28 maacl: qhg: so e.g. I have 5 vectors with 20 unique values in each and I want 10 unique vectors with a value from 1 to 5 of the vectors

18:28 dabd: lpetit: why is it necessary to call (seq s)?

18:29 qbg: The 10 vectors are of random length?

18:30 lpetit: dabd: (seq s) will ensure s is transformed into a seq, *and also* if s is an empty coll or an empty lazy seq, the result of calling seq is guaranteed to be nil. (remember that '() is not considered as logical false in clojure)

18:31 maacl: qbg: yes

18:32 qbg: Are the sets of values in the 5 vectors disjoint from each other?

18:32 maacl: it is like a cartesian product except not one item from each set but a random number of items with a max = the number of sets

18:32 dabd: lpetit: can u show me an example where this would not work correctly? http://pastebin.com/m5c4aa68f

18:33 chouser: mkh: I'll ask

18:33 mkh: chouser: thanks

18:34 qbg: Would taking items randomly from the concatenation of all 5 vectors work?

18:34 lpetit: dabd: hey, it will work correctly, not-empty is based on calling seq, look:

18:34 ~source not-empty

18:36 maacl: qbg: nope, if there is just one element in the vector it has to be from the first

18:36 qbg: the first set that is

18:36 dabd: lpetit: ok. thx

18:36 lpetit: dabd: but you're calling it every time, even so calling next in recur guarantees that you will either have a logical true, either nil (which is logical false), so there is just the initialization of the loop where u need to call (seq s) to ensure you have a correct logical false (nil) if s is empty

18:36 qbg: And if there are two elements in the vector?

18:37 maacl: qbg: they have to be from the first and second set

18:38 qbg: ah, i could just do the different relevant products and join them

18:39 qbg: If that works, why not

18:40 dabd: lpetit: this is getting slightly confusing. why should I worry about logical values if not-empty returns nil for an empty collection or the collection otherwise?

18:41 alexyk: can you nest a defn, you have to do an fn?

18:41 or have to do an fn instead

18:42 qbg: Why would you want nest a defn?

18:42 patrickdlogan: trying to connect the dots between ELPA and github for swank-clojure...

18:42 lpetit: dabd: my point was not about using seq directly or using not-empty (this is basically the same thing), but about the fact that calling them is only needed once, since calling next will *ensure* that you either have an non empty lazy seq, or nil

18:42 alexyk: ??

18:42 patrickdlogan: ELPA installed 1.1.0 of swank-clojure...

18:43 alexyk: hm, lots of FP is done with auxiliary functions, e.g. carrying an accumulator

18:43 patrickdlogan: github shows just one branch, 1.0

18:43 alexyk: the aux is only needed in the parent

18:43 and hence good to nest and hide

18:43 qbg: You could use let/letfn

18:44 * alexyk surprised clojiristas don't get nested functions

18:44 qbg: nested functions are good, but defn makes a global binding

18:45 hiredman: alexyk: def operates in the global scope

18:45 alexyk: hiredman: ok

18:45 hiredman: and local bindings of names are immutable

18:45 so having def operate locally would be just weird

18:46 so use let or letfn

18:47 qbg: Just be careful that you don't do unbounded recursion.

18:51 dabd: lpetit: got it. I had to look at the implementations of not-empty and next and finally figured what u meant. So u need to pay attention to which functions use seq under the hood when looping

18:52 so this is the final version: http://pastebin.com/m4926bb67

18:52 lpetit: dabd: it's in the public API/contract of 'next and 'seq to return nil on empty colls/lazy sequences.

18:53 dabd: sure. going to bed now, cu

18:54 dabd: lpetit: thx

19:01 tolstoy: Anyone here using netbeans/enclojure?

19:03 Doesn't seem to want to install the plugin in netbeans 6.8. Surely, 6.8 is compatible....

19:07 Ah, has something to do with github downloading.

19:29 * konr realizes how much suffering can be avoided by spending some time studying the API

20:00 ajuc: hello, anybody compiled lately penumbra with leiningen

21:31 mebaran151: is there an easy way to turn a clojure hashmap into xml?

21:32 chouser: hm... recursively?

21:34 mebaran151: yeah

21:34 like the way we have write json

21:34 hiredman: mebaran151: like a clojure.xml hashmap?

21:34 mebaran151: I have a hash-map: I'd like to just output it to a flash client

21:34 thought xml would be the easiest way to do it

21:35 it seems like clojure.xml would have something like what I need but I haven't found it yet

21:35 hiredman: json is most likely the easiest way to do it

21:35 clojure.xml has emit

21:35 chouser: I don't know of a generic map-to-xml, though it wouldn't be too hard to make.

21:35 hiredman: but you can;t use it on an arbitrary hashmap

21:36 mebaran151: hiredman: what kind of hashmaps can I use it on?

21:36 hiredman: the kind of hashmaps clojure.xml/parse produces

21:37 flash is more or less javascript, why not use json?

21:37 mebaran151: I haven't been using contrib, and I thought maybe the xml ns had what I needed

21:38 also e4x makes these documents a little easier to work with

21:38 hiredman: you can just use clojure-json if you don't want to use contrib

21:38 mebaran151: extra lib though?

21:39 hiredman: yes

21:39 mebaran151: I should just probably use json-str in contrib

21:58 ben_m: ,pastebin

21:58 clojurebot: java.lang.Exception: Unable to resolve symbol: pastebin in this context

21:58 ben_m: ?pastebin

21:59 Hmm

21:59 Will just use a generic one ..

21:59 chouser: lisppaste8: url?

21:59 lisppaste8: To use the lisppaste bot, visit http://paste.lisp.org/new/clojure and enter your paste.

21:59 ben_m: http://sprunge.us/jRCW

22:00 I'm trying to follow a tutorial ...

22:00 Compiling this gives no errors, but when I run it, I only get an empty window :/

22:02 hiredman: what window manager?

22:03 I have heard ion and java don't play nice together

22:03 ben_m: Musca

22:04 tiling too

22:04 ltyphair: compiz turned on has given me trouble before. the java window would end up under the panel

22:04 ben_m: But I doubt that's the problem

22:04 Nah, no compiz.

22:04 hiredman: ben_m: why do you doubt it?

22:04 ben_m: I had other Java programs running

22:05 Not in Musca specifically, but other tilers.

22:07 the-kenny: ben_m: uhm.. you're calling the function "counter-app", right?

22:07 hiredman: works for me

22:07 ltyphair: for what it worth the code works on gnome.

22:11 ben_m: the-kenny: yes?

22:11 Hmm alright then

22:11 Everything about my PC acts in mysterious ways, so this does not surprise me.

22:30 Is there a shortcut in the REPL to get the last result? Like */**/*** in CL

22:35 hiredman: *1 *2 *3

22:36 ben_m: ah, thanks :)

22:38 hiredman: (doc e*)

22:38 clojurebot: Excuse me?

22:38 hiredman: (doc *e)

22:38 clojurebot: "; bound in a repl thread to the most recent exception caught by the repl"

22:40 konr`: it seems that my JVM is computing data on an infinite sequence - is there a way to recover without killing slime (therefore losing the session data)?

22:41 ben_m: C-c C-c 0

22:41 ?

22:45 konr`: wow

22:45 thanks, ben_m

22:45 wilig: technomancy: Yay! swank-clojure is now (read-line) enabled.

22:45 konr`: I used to ignore that debug menu

22:45 ben_m: Heh, it can do so much more if you use Common Lisp.

22:51 mattrepl: is there a known issue with leiningen's test command?

22:52 aldebrn: liebke, I'll post this to the group, but maybe I'm doing something stupid: when I start clj (from the latest Incanter snapshot build) and (use 'incanter.core), Clojure can't find the "shuffle" function (from contrib.seq-utils).

22:53 If I try to (use 'clojure.contrib.seq-utils), I get an IllegalStateException, but after which I can see shuffle, e.g., (doc shuffle)

22:54 So, I can work around this by using the REPL, but it prevents me from running scripts that use shuffle

22:54 liebke: aldebrn: okay thanks, I'll take a look. Were you using the pre-built distribution or building it from source?

22:54 aldebrn: Pre-built

22:54 liebke: okay, I'll test it out

22:55 aldebrn: Thanks for your selfless hard work

22:55 liebke: :)

22:58 aldebrn: I'm getting the error. What platform are you running on?

22:58 aldebrn: Fedora 11 64-bit

22:59 liebke: do you have a CLASSPATH set?

22:59 aldebrn: java version "1.6.0_0" OpenJDK Runtime Environment (IcedTea6 1.6)

22:59 No CLASSPATH appears to be set

23:00 liebke: I don't have fedora, but I'll test it on redhat 64-bit

23:01 aldebrn: You said you were getting the "IllegalStateException: group-by already refers to: #'incanter.core/group-by in namespace: user" error?

23:02 liebke: I said?

23:03 aldebrn: "liebke> aldebrn: I'm getting the error." <-- did you mean you're not getting an error?

23:03 liebke: oops yeah, I meant I'm not getting the error :)

23:03 is that the error you're getting?

23:04 aldebrn: Yes, when I try (use 'clojure.contrib.seq-utils)

23:04 liebke: ah yes, I've seen that one. That's because it also has group-by defined

23:05 you need to use require instead of 'use' for either incanter.core or seq-utils

23:05 aldebrn: Ahh, so does incanter.core, got it

23:05 Ok

23:05 liebke: yeah, name collision

23:13 aldebrn: liebke, sorry to bother you again, how would I use (require) with seq-utils?

23:15 mattrepl: aldebrn: (require [clojure.contrib.seq-utils :as seq-utils])

23:15 then seq-utils/group-by

23:15 you can also do (use [clojure.contrib.seq-utils :only [<stuff> <you> <need>]])

23:16 and that should be :require and :use if used in a namespace definition

23:18 aldebrn: mattrepl, thanks, something somewhat strange is happening: (use 'clojure.contrib.seq-utils) works fine (by itself), but (use [clojure.contrib.seq-utils :only [shuffle]]) gives this horrific ClassNotFoundException: clojure.contrib.seq-utils (NO_SOURCE_FILE:1) ?

23:19 Similarly with your example using (require), am I typing something wrong?

23:19 mattrepl: right, I gave you a bad example since it's incorrect for an ns definition as well as from the repl

23:19 you need to quote clojure.contrib.seq-utils and shuffle

23:19 liebke: aldebrn: try (require '(clojure.contrib [seq-utils :as s]))

23:20 aldebrn: Ahh, damned quotes

23:20 Thank you thank you

23:20 liebke: and then you can refer to functions using the s prefix, like s/group-by

Logging service provided by n01se.net