#clojure log - Feb 28 2009

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

0:10 durka42: what does "the oft-requested letrec" do?

0:13 ayrnieu: durka42 - all the bindings established by let are visible within their definitions.

0:14 durka42: so you can let things like fibs?

0:14 ayrnieu: well, that isn't a very interesting case, because it's only one binding.

0:15 (letrec [even? #(if (zerop %) true (not (odd? (1- %)))) odd? #(if (zerop %) false (not (even? (1- %))))] (even? n))

0:17 durka42: so all the bindings have to be forward declared or some such magic?

0:18 ayrnieu: letrec isn't a function; it isn't that the definition of even? is evaluated and then the definition of odd? is. The magic is just the usual business of deciding when bindings are made and what they're visible to.

0:20 CL has a LET that doesn't expose its bindings until after they're mind, and a LET* that exposes them sequentially. So (let ((a b) (b a)) ...) renames a B and A defined outside this let, whereas the LET* variant would give you two names for outer-b

0:23 so does clojure have letrec now, or is it still oft-requested?

0:24 durka42: rhickey added an issue

0:24 i take it is not a synonym to the scheme letrec

0:25 ayrnieu: why do you take that?

0:28 durka42: i thought scheme letrec named the let so you could refer to it from within itself

0:29 * durka42 does not know schem

0:29 durka42: e

0:29 ayrnieu: scheme's letrec is as I described. The EVEN?/ODD? example comes from t-y-s-i-f-d.

0:29 teach yourself scheme in fixnum days.

0:30 scheme also has named lets, but clojure has these already.

0:30 durka - you might implement letrec in clojure as an exercise. At least at a toplevel macro, it should be very easy.

0:33 danlarkin: why wouldn't clojure's let just gain letrec functionality instead of gaining letrec? Is it that much less efficient?

0:34 msingh: hello is there any example code to look at that uses java sound? i'm interested in writing a small multiplatform audio comm app for voicing because there is nothing that i've tried works on linux

0:34 ayrnieu: danlarkin - it is *different* functionality.

0:35 danlarkin: ayrnieu: oh, it breaks something that normal let gives you?

0:36 ayrnieu: ,(let [a 1 a (inc a) a (inc a)] a)

0:36 clojurebot: 3

0:36 danlarkin: I thought it just added more functionality: the ability to have recursive definitions

0:36 durka42: does this page apply? http://neilmitchell.blogspot.com/2007/03/let-vs-letrec.html

0:36 The rule is that in a letrec you introduce the names you are defining before computing their values (so the x = x refers to itself), but with let you only introduce the names once you get to in (so the x = 1 is still in scope).

0:38 danlarkin: I guess my understanding of letrec was a little off

0:38 ayrnieu: ,(let [a 1] (let [b (inc a) a 1] [b a]))

0:38 clojurebot: [2 1]

0:39 ayrnieu: both of these examples would be different in with letrec.

0:40 rhickey could decide that clojure's `let bind the way letrec does (the way he's already decided that it bind in the way of CL's LET* instead of its LET), but this is not a simple move 'upward'.

0:41 durka42: sorry, how would that last example be different? (inc a) would apply to the second a, which is still 1

0:42 ayrnieu: it's a shifting around of hassles. I think it's not unreasonable to say that letrec's hassles are more bearable in clojure that its present hassles. But if he does decide to do this, he should decide pretty quickly. It's a breaking change that hard to look for.

0:42 sure, the second a should be something else.

0:43 ,(let [a 1] (let [b (inc a) a :parrot] [b a]))

0:43 clojurebot: [2 :parrot]

0:43 durka42: if the inner let was letrec, ClassCastException

0:45 ayrnieu: anyway, you can write letrec in clojure, definitely as a top-level macro. Have (let [even? #(...) odd? #(...)] (defn integer-filter [...] ... even? ... odd?)) resolve to (do (forward-declaration odd?) (defn GENSYM_even? ...) ... (let [even? GENSYM_even? odd? GENSYM_odd?] ...))

0:53 banisterfiend: hey guys anyone know a tutorial that 'll tell me how to get clojure up and running on a debian linux system?

0:54 ayrnieu: banister - clojure.org -> wiki -> getting started.

0:54 durka42: ~pl

0:54 clojurebot: have you heard about the bird? is<reply>The bird, bird, bird, the bird is the word.

0:54 durka42: ~transform

0:54 clojurebot: It's greek to me.

0:55 durka42: clojurebot: transform is http://github.com/hiredman/odds-and-ends/blob/8a84e6ddbad9d71f714ba16c3e1239633228a7eb/functional.clj

0:55 clojurebot: Alles klar

1:04 * danlarkin likes "ugh, read the source. this started as a very specific function and turned into a very generic one."

2:01 bradbev: I'm trying to use files in my project, like (ns memorytool.unit-tests (:refer memorytool.simheap)), and I want to do (simheap/foo 1 2). I can't figure out how to use :as.

2:03 Chouser: (:use [memorytool.simheap :as simheap :only ()])

2:03 or more conventionally, (:require [memorytool.simheap :as simheap])

2:04 bradbev: ah, thanks very much. That's the only thing I miss about Clojure's documentation - small examples of common usage

2:04 durka42: ~api examples

2:04 clojurebot: examples is http://en.wikibooks.org/wiki/Clojure_Programming/Examples/API_Examples

2:04 Chouser: yeah.

2:04 durka42: (not complete)

2:05 Chouser: also, contrib

2:05 bradbev: ah, that's cool - I didn't know about that

8:30 blbrown: rhickey, how do you feel about strong static typed languages like haskell or scala. They offer completely different styles from clojure/lisp. Are there places to use one style or the other

8:31 ...question directed to anyone else that is up, also

8:31 Chousuke: I like haskell's system.

8:31 blbrown: and ideally with haskell's type inference, you don't have to necessarily set the type for each function, etc

8:32 Chousuke: I think type inference is necessary for static typing not to be a nuisance :P

8:32 blbrown: yea

8:33 Chousuke, are there are apps where you might use haskell and then apps where you might use haskell. Actually I could see myself using scala for a server project I want to write

8:34 scala is being used at Twitter, but I don't have all of the details

8:35 Chousuke: hmmh

8:35 It's difficult to say outright when static typing is better than dynamic typing.

8:36 blbrown: or vice versa

8:36 Chousuke: yeah.

8:37 bOR_: (apply concat \A 1 "a")

8:37 ?

8:37 wonder what you can't do statically that you can do dynamically.

8:37 blbrown: Chousuke: this is just my own subjective opinion, but clojure is certainly going to be a lot lighter and easier to work with. I am using clojure for GUIs and web development. I could see where scala/haskell could be used more for backend/server development

8:38 I hear a lot, that lisps are good at bottom up programming

8:38 rhickey: blbrown: the whole trick with type systems is expressivity - do they let you do what you want? Are the benefits they provide worth the complexity, time and effort? Do they introduce rigidity into the system as a whole? I'm not opposed, and think Haskell is fascinating

8:38 Chousuke: With dynamic typing it's easy to misuse a function. in Haskell at least the type system ensures that functions are used where they make sense.

8:38 and nonsensical stuff is caught before runtime

8:39 on the other hand, overriding the type system when it's wrong about something is not as easy.

8:40 blbrown: Chousuke, it also gives you a bit of flexibility

8:40 bOR_: much still to learn in the computer science department for me :).

8:41 blbrown: whateve the case, architecture wise, there is no reason why you can't built a multi-language app. Clojure and Haskell. Clojure and Scala. Clojure and Java

8:41 ...based careful analysis and a need to do so, of course

8:43 Chousuke: You said you use Clojure for GUIs and web development; I think dynamic typing fits interactive programs well.

8:44 blbrown: exactly

8:44 Chousuke: you might have many input sources and callbacks and whatnot, and dynamic typing allows for a simpler interface because you don't have to worry about typing.

8:45 blbrown: clojure is the new smalltalk, hehe

8:47 rhickey: E.g., what is the 'type' of Clojure code-as-data? All those nested heterogeneous collections etc. It's not hard to understand, but difficult to express using types (at least without abandoning them to a universal unifying type)

8:50 bOR_: taking a break from writing, and reading up on wikipedia / type system to catch a bit of the background :).

8:50 blbrown: hmm, so the coding style associated with clojure doesn't really lend itself to having to define the types, which is fine.

8:53 Lau_of_DK: Guys - Im having a little trouble incorporating jMEPhysics 2 with jME 2.0 - Any one here who's got any experienco ?

9:04 Chouser: blbrown: I don't know that clojure's collections are any less suited for static typing than Java's, it's just that we never bother declaring or casting.

9:05 it might be an interesting excercize to try to write a DSL for asserting collection types.

9:05 blbrown: Chouser, I need to write a larger app in haskell and see if there are differences

9:06 leafw: Chouser: about the latter ... I had some not-so-nice experiences developing with clojure. For example, unless one is developing the program interactively, parts of the program may never be executed -- and bugs creep in that only show at run time. And some of this bugs are of the class/type kind, that a compiler or an IDE should catch.

9:06 Chouser: The simplest implementation would just be runtime checks, but it would allow you to play with the syntax to find something succinct and pleasing.

9:06 leafw: IMO, clojure is missing a nice IDE. What is the state of enclojure for net beans? And has net beans a proper text editor (like vim or emacs) integrated?

9:06 Chouser: leafw: yes, but if code is never run there can also be errors that the compiler and IDE won't catch.

9:07 blbrown: leafw, it is how you are coding that might introduce those bugs. For example, using TDD. Code a little, test a little, code a little helps a lot with clojure and other lisps

9:07 Chouser: a static typing compilier may catch some, but if you still need unit tests, and those unit tests would have caught the error too, what's the benefit of the static typing?

9:07 blbrown: same is kind of true for python or ruby

9:07 leafw: blbrown: I know, but one needs a nice IDE to do that. I should change to emacs just for that ... I use vim most of the time.

9:08 blbrown: I use emacs and vim, I haven't needed anything else

9:08 of course, eclipse for project management

9:08 leafw: Chouser: I know; static typing is like a premature optimization, and an IDE should attempt to catch them all anyway.

9:08 Chouser: there's jvi that works with netbeans. last I tried it with enclojure it didn't work so well, but that may have changed.

9:09 blbrown: leafw, I see your point and had the same issue with python, when I started with that 10 years ago. But learned to use different coding styles when working with dynamic languages

9:09 Chouser: I submitted a patch ages ago, but I don't know if it ever went in.

9:09 leafw: guess I spent too much time doing things, even if slowed down, than testing IDEs that would speed me up.

9:09 blbrown: I had the same situation with python, is one of the reasons I don't use it so much (except for Blender).

9:09 blbrown: and I never was a big fan of debuggers, so I normally don't use those anyway. Unless debugging a complex web app

9:10 leafw: blbrown: debuggers for C are a must; at least for me.

9:10 blbrown: ...one thing I thought about trying, kind of related. Is using a design by contract development style

9:11 leafw: blbrown: most of the time I develop in a exploratory way; no constraints (which has its good and its bad sides)

9:11 Chouser: leafw: most of my C experience was network device drivers. debuggers were almost completely useless, because as soon as you breakpoint the code, the world has already changed.

9:12 leafw: xD indeed. I am lucky then that all I do is crunching numbers.

9:12 bOR_: question about a stack overflow I am causing with merge-with.

9:12 (apply merge-with concat (mapcat adaptedness (subvec (vec (gather :born)) 0 20)))

9:12 works fine

9:12 but somewhere between a vector of 2500-3000, it gives up.

9:13 I've the code here, so I can parse more details if you need them.

9:13 {(#{\A \B \C \D \E \F \G \H} #{\A \C \D \E \F} #{\A \C \D \E \F \G \H} #{\B \D \E \F \G \H} #{\A \B \C \D \E \F \H} #{\A \B \C \D \E \G \H} #{\A \F \H} #{\A\ \E \F \H} #{\A \B \C \D \E \G \H}) (5.660244012764965 5.935697382497301), (#{\A \C \D \E \F \G \H} #{\A \B \C \E \F \H} #{\A \B \C \D \E \F \G \H} #{\B \C \ \D \E \F \G} #{\A \B \C \D \F \G \H} #{\A \B \C \D \E \G \H} #{\A \B \C \D \F \G \H} #{\D \E \F} #{\A \C \D \E \

9:14 that is its output: a hash-map in which the key is a particular pattern/genotype, and the val is a list of viral loads associated with that genotype.

9:15 so it is doing what I want to do.

9:15 but not for all 5000 hosts :).

9:15 drewr: Chouser: On the contributors page, can you change mtndrew0 -> aaraines?

9:16 Chouser: drewr: Based on the word of a random IRC nick? :-) Sorry, I don't know the rules.

9:16 drewr: haha

9:17 That was my sf ID, but since we're using Google now, I thought I'd use my Google one.

9:17 ...and hate to bother rhickey for trivial changes like that.

9:18 Chouser: I think that's a good change to make, as then it matches your name on the issues page, but I don't know what kind of auth rhickey needs for that. Possibly email from that address asking for the change? I don't know.

9:18 drewr: That's fine, I'll email.

9:20 Make sure you check the headers of my message though. :-)

9:24 bOR_: hmmm. managed to circumvent the stack overflow by splitting my population in 3, doing the apply merge-with concat on each subpopulation and then doing an apply merge-with concat on the three answers.

9:25 Chouser: ick

9:26 bOR_: aint going to win any pretty-prizes :P.

9:26 Chouser: bOR_: can you put together a small runnable example that shows the problem?

9:26 bOR_: should be possible. I'll make a pot of tea and do that :).

9:30 rhickey: bOR_: mmmm, tea

9:32 bOR_: hehe

9:32 water finished cooking, example done

9:32 pasting it now :)

9:32 (def noworld (map #(hash-map (rand-int 10) [%]) (range 25000)))

9:32 ef yesworld (map #(hash-map (rand-int 10) [%]) (range 15000)))

9:33 (apply merge-with concat yesworld)

9:33 (apply merge-with concat noworld)

9:33 that ef should be a def

9:33 the yesworld works fine, the noworld gives a stackoverflow :)

9:34 somewhere at concatting 2000 values to a single hashkey breaks it.

9:34 Chousuke: maybe try to make it less lazy?

9:35 bOR_: how would I do that?

9:35 Chouser: bOR_: nice, thanks for the example.

9:35 Chousuke: bOR_: use doall

9:36 like that, your world is just a lazy seq, so perhaps it'd help to realise it.

9:36 that puts it all in memory at once though.

9:36 bOR_: well, in the model, my world is a large vector of agents.

9:37 is that the part you want me to make less lazy? not sure if I can change much there.

9:37 Chouser: ,(apply merge-with concat (replicate 25000 {1 2}))

9:37 clojurebot: Eval-in-box threw an exception:java.lang.reflect.InvocationTargetException

9:37 Chouser: hm. that overflows for me

9:38 Chousuke: hmm :/

9:39 bOR_: shouldn't it be {1 [2]} ?

9:39 Chouser: yes

9:39 bOR_: can't concat 2.

9:39 nod

9:40 Chouser: overflows either way, though, which is interesting.

9:42 bOR_: yeah, I wondered why. it has to remember three hashmaps. the collector, the first of the seq, and the rest of it. not sure why that would overflow.

9:42 Chouser: (reduce concat (replicate 25000 [2]))

9:43 bOR_: stack overflow as well here.

9:44 Chouser: yep, it's concat on more than 2 args that's recursive

9:44 bOR_: at quite a bit lower numbers than apply concat (replicate ..

9:44 ah.

9:44 Chouser: oh, but... hm...

9:44 bOR_: am I supplying more than two args?

9:44 hmm.

9:45 Chouser: oh!

9:45 hm.

9:45 no

9:59 as soon as you realize a concat seq, it calls 'rest' on its first arg, which realizes the next lazy-seq, ... *boom*

9:59 bOR_: hehe.

10:00 is it absolutely neccesary that it does that?

10:01 Chouser: seems likely there's another way to do it, but I haven't thought of it yet.

10:03 rhickey: (reduce concat ...) != (apply concat ...), for same reasons as (reduce str ...) != (apply str ...)

10:04 bOR_: noticed that. at first I switched to reduce rather than apply to see if that helped.

10:05 (I know I don't know the difference well enough between the two, but that there was a forum post that explained it quite well if I needed to know the difference better)

10:05 rhickey: what's the failing case with apply?

10:07 bOR_: (apply merge-with concat (replicate 2500 {1 [2]}))

10:08 rhickey: bOR_: no problem here - are you trying to print it or something?

10:09 bOR_: hmm. if you use a larger replicate number than 2500?

10:09 I'll see what happens if I just want it stored in a def.

10:09 yes.

10:09 matters if I just enter it in the repl, or send it to a def

10:10 ahh.

10:10 lemme see if that is the only problem in the original case as well.

10:11 yep. it is the printout that happens in the repl that causes the stackoverflow.

10:11 rhickey: (count ((apply merge-with concat (replicate 250000 {1 [2]})) 1))

10:11 StackOverflowError

10:12 bOR_: what is with the (( ?

10:12 don't see that too often in code.

10:13 hmm.

10:13 never mind my confusion :)

10:13 rhickey: concat is such a bad operation for this

10:13 bOR_: it is only in a reporting function that I call once every 5 minutes.

10:14 rhickey: user=> (count ((apply merge-with into (replicate 250000 {1 [2]})) 1))

10:14 250000

10:15 bOR_: into seems to work fine :)(

10:16 what makes concat bad to use in this case?

10:25 anyway, thanks for solving it. The endresult works fine: (mKsdge:#2703:^0.927:@6.40 mKsdqq:#1105:^0.515:@5.53 mKsdhj:#781:^0.422:@6.41 mKsdiP:#3\ :^0.252:@6.51)

10:28 rhickey: bOR_: it's expensive to add to the end of a list - we don't build up lists by saying (concat (concat (concat (concat () '(1)) '(2) ) '(3) ) '(4))

10:28 which is effectively what you are asking for with reduce concat

10:36 bOR_: still a bit above my comfort level, but I'll keep it in mind. can't tell for example why into does fix this, but I'll figure that out over time.

10:38 Chouser: vectors are efficient for adding onto the right-hand side, which is what into does on a vector.

10:38 bOR_: ah. getting it. and concat is adding at the end of a list.

10:39 so if the place in the list doesn't matter to me, conj would have been fine as well.

10:40 because adding lefthand side in lists, is fine.

10:40 nod.

10:40 Chouser: right. into and conj always add in the way that's efficient for the collection being used.

10:41 bOR_: I'll remember.

10:47 Chouser: the implementation of 'for' is hard to understand.

10:47 rhickey: Chouser: sorry

10:48 Chouser: :-)

10:48 * rhickey shares blame with Chouser

10:48 Chouser: I've successfully patched it either without fully understanding it, or have since forgotten what I knew.

10:49 I really want to tease out the shared structure between it an doseq.

10:49 * Chouser continues to mull...

10:50 clojurebot: svn rev 1313; swtiched to url.openConnection().getLastModified

10:57 thr: rhickey: I suppose you hear this hundreds of times a day, but I just started learning clojure (comming from C# and Python, wierd combo I know) and I've got to say this is... amazing, thanks so much for all your work!

10:57 rhickey: thr: you're welcome!

11:11 thr: Btw, Am I allowed to ask "newbie"-style questions about clojure in here? Reading about it and trying out examples and find something that is a bit ambigius to me

11:12 Chouser: thr: sure

11:12 thr: I have this example that adds an extra metadata tag to shout: (defn #^{:tag String} shout [#^{:tag String} s] (.toUpperCase s))

11:12 Displaying it with ^#'shout seems to work fine

11:12 but the thing that got me was the fact that #^{:tag String} is infront of the symbol s in the argument list also

11:13 removing the #^{:tag String} from the argument vector, everything still seems to be the same when running ^#'shout in the repl

11:14 Chousuke: the latter actually applies to s

11:14 thr: Yeah I figured that, but where is it any good ?

11:14 I mean, you can't access s anywhere

11:14 leafw: can one specify the return type of a function? That is news to me

11:14 Chousuke: type hinting.

11:14 thr: Chouser: aha!

11:14 Thanks

11:15 Chousuke: though That's usually done with #^String isn't it? :/

11:15 Chouser: those are type hints. If Clojure can't tell what method to call because of insufficient type hints, it will figure it out at runtime.

11:15 Chousuke: yep, that's a shortcut for what he's got.

11:15 blbrown: stupid general question: with clojure (defn abc [something] (.doIt something)) ...(abc something1-obj) ... (abc something2-obj) ...being able to call abc on two different objects. would that be considered 'polymorphism' or something else. And should lisp be used in this fashion. Or is defmethod a better tool for that

11:16 Chouser: thr: the defn macro actually can access the metadata on s

11:16 thr: Thanks a bunch for the help guys, most appriciated

11:18 Chousuke: blbrown: I guess that's polymorphism, yes. and it's perfectly fine

11:20 blbrown: defmethod is for when you want *different* behaviour based on some function of the parameters

11:20 Chouser: if something1-obj and something2-obj are two different classes, with their own doIt() method definitions, that's normal Java polymorphism.

11:20 blbrown: Chousuke, I am working on a small test framework. I can create simple mock objects for the test cases and then pass the mock objects to my library functions. But in the real world, I can just use the real objects

11:21 kind of an interesting approach

11:21 Chousuke: Chouser: except they don't even have to have a common parent.

11:21 or implement a common interface.

11:21 blbrown: Chouser, yea, what chousuke said

11:22 Chousuke: for testing java?

11:22 blbrown: and I guess with other lisp's it may not be as prevalent because those lisp aren't wrapped around an object oriented language runtime

11:23 Chousuke: there are many clojure test frameworks that do just fine without mock objects :)

11:23 blbrown: Chousuke, I don't really need mock objects, but I could if need be

11:25 Chousuke, defmethod seems more like how erlang's pattern matching works

11:28 Chousuke: defmethod does no pattern matching though.

11:29 but I don't know Erlang so I can't say much

11:30 blbrown: Chousuke, it seems like it

11:30 cemerick: is it the case that array classes cannot currently be used as part of gen-class method or constructor signatures?

12:15 blbrown: wtf is waterfront

12:16 gnuvince_: An editor

12:24 blbrown: ah

12:52 danlarkin: Lau_of_DK: Nantes?

13:08 Lau_of_DK: danlarkin: What does that mean ?

13:09 danlarkin: it's a city in France

13:12 Lau_of_DK: Its not bad - Dont know the city though - How 'bout Tokyo ?

13:15 dk.bestinclass.sofiaba> (Vector3f. 1 1 1)

13:15 #<Vector3f com.jme.math.Vector3f [X=1.0, Y=1.0, Z=1.0]>

13:15 dk.bestinclass.sofiaba> (Vector3f. (apply float [1 1 1]))

13:15 ; Evaluation aborted.

13:15

13:15 Whats the trick ?

13:26 Chouser: what you have there is the same as (Vector3f. (float 1 1 1))

13:26 Lau_of_DK: Yea ... so whats the trick ?:)

13:26 Its a destructuring of some kind I need

13:36 Chouser: (defmacro mapmac [t f c] (cons t (map (eval f) c)))

13:36 (mapmac Vector3f. #(do `(float ~%)) [1 1 1])

13:38 cmvkk: ,(- 1.33 1)

13:38 clojurebot: 0.33000000000000007

13:40 cmvkk: is that just some weird floating point thing or what?

13:57 durka42: looks like floating point stuff to me

13:58 cmvkk: is there any good way to take x.33 for any x and reliably return 0.33?

13:58 maybe it's just me, but i feel like that ought to be feasable...

14:00 durka42: you could use fixed-point math...

14:00 ,(- 1.33M 1M)

14:00 clojurebot: 0.33M

14:00 cmvkk: oooh

14:00 durka42: which is weird because...

14:00 ,(- (BigDecimal. 1.33) (BigDecimal. 1))

14:00 clojurebot: 0.3300000000000000710542735760100185871124267578125M

14:01 cmvkk: heh

14:01 durka42: apparently bigdecimal literals are not just bigdecimal literals

14:01 ,(= 1.33M (BigDecimal. 1.33))

14:01 clojurebot: false

14:02 cmvkk: well

14:02 ,(BigDecimal. 1.33)

14:02 clojurebot: 1.3300000000000000710542735760100185871124267578125M

14:03 cmvkk: it isn't the same number anyway.

14:03 durka42: right that's why i was confused

14:03 i guess it's because 1.33 literal is converted to a double first and then a bigdecimal

14:03 dreish: That's the exact value of the floating-point number 1.33.

14:03 durka42: instead of

14:03 ,(BigDecimal. "1.33")

14:03 clojurebot: 1.33M

14:03 cmvkk: oh hmm

14:11 thr: How are clojure vectors implemented? I assume lists are linked lists, but vectors?

14:11 dreish: They're actually trees.

14:11 thr: Ok, thanks

14:12 dreish: you know what tree algorithm they're implemented as?

14:12 (just curious, not that it matters for me at this point ;p)

14:13 dreish: I can't remember what it's called, but they're 32-way trees. You can see the code in PersistentVector.java

14:13 It's pretty clever.

14:13 thr: Ok, thanks a bunch - yeah figured it'd be clever ;p

14:13 just curious of the inner workings for no other reason than it's fun to know

14:13 dreish: Indices 0-31 go in the root node, then 32-63 in the first child of that node, etc.

14:14 I think. I might be describing it incorrectly.

14:14 thr: Hm... I'd figure it would be a b-tree with 31 slots per node

14:15 Because I think the way you said would give horrible performance when searching

14:15 not sure though, semi-professional-guess

14:15 dreish: Really?

14:15 You always know exactly what path to follow to get to a given index.

14:16 thr: Ah, I totaly missunderstood you

14:16 I thought you ment 0-31 (root) -> 32-63 (31) etc.

14:17 dreish: The code in clojure/lang/PersistentVector.java is more authoritative than anything I could say about it.

14:18 thr: Yeah Ill go check it out, love digging around in the inner works of stuff

14:18 dreish: That's one nice thing about Clojure -- it's small enough that that's easy to do.

14:18 thr: Yeah, I've just been toying with it for not very long, and it's my first Lisp but I do really enjoy it so far

14:19 kotarak: thr: may be of interest to you: http://blog.higher-order.net/2009/02/01/understanding-clojures-persistentvector-implementation/

14:20 * thr get's all giddy

14:20 thr: thanks :)

14:21 pjb3: so, there's no way to use binding with out a root binding, right?

14:21 ,(binding [x 1] x)

14:21 clojurebot: java.lang.Exception: Unable to resolve var: x in this context

14:22 dreish: Oh, of course, the root node _becomes_ the first child node once the tree expands past 32 items.

14:24 thr: yeah that is clever

14:25 And the implementation is only ~200 lines? Goddamn I'm impressed

14:26 rhickey: pjb3: you can use binding without a root binding, but not without a var: (def *v*) ... (binding [*v* foo]...)

14:26 Lau_of_DK: kotarak: Sweet article, thanks

14:27 kotarak: Lau_of_DK: it's not by me, of course. I just saw some weeks ago in reddit.

14:27 pjb3: rhickey: right, ok

14:27 Lau_of_DK: rhickey: The 0.5F issue we discussed isnt a pressing as I thought, it seems in most cases Java will automatically convert doubles to float when needed

14:27 cmvkk: i need a data structure i can use as a queue but still has good random access. I was using a vector but it keeps overflowing the stack. Maybe i'm doing it wrong?

14:28 dreish: cmvkk: PersistenQueue.

14:28 t

14:28 rhickey: dreish: PQ doesn't have random access

14:28 dreish: Oh, I didn't notice that.

14:29 Wouldn't it be easy to add, since it's just a seq on a vector plus a vector?

14:29 cmvkk: i was pushing with conj and popping off the beginning with subvec. is the fact that this blows the stack expected?

14:34 rhickey: cmvkk: currently, subvecs stack, i.e. subvec on a subvec on a subvec builds a chain, will fix...

14:41 Lau_of_DK: Its the cemerick! :)

14:42 cemerick: THE cemerick?

14:42 I've noticed a couple of people with handles like that -- the_joe_smith, etc.

14:43 Chouser: The Astute Chas, of the House of Emerick.

14:43 * Chouser goes back to chasing after the kids.

14:54 Lau_of_DK: cemerick: Since you got that mention from Norvig I figured you'd go with The Cemerick from now on :)

14:55 cemerick: heh. The fanboy glee has since faded. :-)

14:56 WizardofWestmarc: mention from Norvig?

14:56 * WizardofWestmarc obviously missed something awesome.

14:57 mattrepl: what Norvig mention is this?

15:01 arohner: mattrepl: http://norvig.com/ibol.html

15:01 http://blog.snowtide.com/2009/02/26/whoa-peter-norvig-used-some-of-my-code

15:06 mattrepl: nice, congrats, cemerick. didn't connect your real name to you when read first time

15:06 arohner: what's the syntax if I want a macro to refer to a symbol?

15:06 ~'foo ?

15:06 clojurebot: excusez-moi

15:07 dreish: For symbol capture, yes.

15:07 Lau_of_DK: I have a macro which generates code, which produces some data, I want to call this macro from a function, but I dont want the resulting code, which generates data, I want the data - How do I do? (eval (mymac foo bar)) doesnt do it

15:07 cemerick: mattrepl: thanks

15:07 dreish: arohner: It's filthy, but I do it all the time. :)

15:08 arohner: dreish: I'm doing it for a one-off that will only be used on this page

15:08 it cleans up the code significantly IMO

15:08 dreish: Yeah, sometimes it really is useful.

15:08 cemerick: Lau_of_DK: try (eval '(mymac foo bar))

15:09 ,(eval '(and false true))

15:09 clojurebot: DENIED

15:09 cemerick: eh, it doesn't allow eval

15:09 cmvkk: heh

15:09 WizardofWestmarc: Hah that's really cool cemerick :)

15:09 cmvkk: why doesn't the macro get evaluated automatically?

15:09 durka42: Lau_of_DK: what does the eval do? i would expect that to work

15:10 kotarak: Lau_of_DK: why is it a macro generating data not a function?

15:10 Lau_of_DK: Its the only way to go because I need some destructuring

15:10 clojurebot: svn rev 1314; avoid chaining in subvec of subvec

15:10 cmvkk: yeah but, when a macro returns code, that code is evaluated right then, right?

15:11 ooh thanks rhickey

15:11 rhickey: cmvkk: its' still not a queue though

15:11 dreish: That was sudden. :)

15:12 Lau_of_DK: Cemerics trick, did it

15:12 cmvkk: no; well i don't know how else to do what i want to do in any sort of efficient way

15:12 rhickey: since memory is not reclaimed from front

15:12 Lau_of_DK: cmvkk: I thought so - but no

15:13 cmvkk: oh. i don't suppose it would be a good idea to use (into [] (rest myvec)) instead?

15:13 durka42: (eval '(mymac foo bar)) is the same thing as (mymac foo bar), isn't it?

15:13 maybe (mymac 'foo 'bar)

15:13 rhickey: cmvkk: no, would be very bad perf

15:13 cmvkk: yeah, that's what i thought

15:14 but anything rest returns is O(n) random access?

15:14 arohner: does the #() form work inside of macros?

15:14 ayrnieu: ,`(does #(%) work?)

15:14 clojurebot: (sandbox/does (fn* [sandbox/p1__2847] (sandbox/p1__2847)) sandbox/work?)

15:14 rhickey: cmvkk: right, seqs are linear access

15:15 arohner: ayrnieu: I did that, but got "can't use name as qualified parameter"

15:15 ayrnieu: arohner - what do you get that from?

15:15 oh, actually, I see

15:16 arohner: and translating to "normal" (fn [x#] x#) works fine

15:17 * rhickey has plan for labels-like letfns, do people really care a lot about this?

15:21 ayrnieu: `(does (fn [%] %) work?)

15:21 ,`(does (fn [%] %) work?)

15:21 clojurebot: arg literal not in #()

15:21 ayrnieu: huh.

15:21 ,`(does (fn [a] a) work?)

15:21 clojurebot: (sandbox/does (clojure.core/fn [sandbox/a] sandbox/a) sandbox/work?)

15:21 durka42: (fn [a] a) != #(%)

15:23 dreish: rhickey: There's no technical reason with a little reworking nthrest couldn't be made O(1) for seqs on random-access structures, right? Just hasn't been done?

15:24 rhickey: dreish: for what purpose?

15:24 seq + subvec

15:24 dreish: rhickey: None right now. It was just a thought -- I don't really care when if ever it happens.

15:29 ayrnieu: dreish - even if it were O(1), a series of nthrests on a random-access structure would require memory allocation. nthrest makes sense for sentineled data structures -- C strings, cons lists, where every subrest is already a proper data structure.

15:47 Lau_of_DK: http://paste.lisp.org/display/76291 <-- Could someone, with macroskillz like rhickey, please tell me why this boorks - I really dont understand how evaluation is handled

15:48 kotarak: (eval `(>RGBA ~v))

15:50 Lau_of_DK: Unable to resolve v in this context

15:51 ayrnieu: Lau - look at (macroexpand-1 '(>RGBA v))

15:52 you don't need to use eval; the bare macro is sufficient.

15:55 Lau_of_DK: ayrnieu: Thats gives me that ISeq error

15:57 ayrnieu: OK, now try (ColorRGBA. (map (fn [x] `(float ~x)) 'v)) :-)

15:58 you're doing work at macroexpansion time. You don't have the value of v at macroexpansion time -- you just have 'v itself.

16:00 kotarak: clojurebot: eval

16:00 clojurebot: Pardon?

16:00 kotarak: clojurebot: eval is evil

16:00 clojurebot: c'est bon!

16:01 kotarak: clojurebot: eval is also sometimes useful - but only sometimes

16:01 clojurebot: 'Sea, mhuise.

16:01 durka42: clojurebot: eval is also DENIED

16:01 clojurebot: Ack. Ack.

16:01 Lau_of_DK: Hmm, Im further now, but my setup is too complicated to see if its entirely working atm, but big thanks to ayrnieu and kotarak :)

16:02 kotarak: np

16:03 Lau_of_DK: Guys - its working, love this community

16:04 I new have a beautiful 3d island, fully detail textured, rendered on a slowly moving pacific ocean! :)

16:04 k

16:04 slashus2: screenshots?

16:05 Lau_of_DK: Hang on

16:06 slashus2: Lau_of_DK: Are you sure that you had to use a macro in that case?

16:08 WizardofWestmarc: hm, strange

16:08 trying to get clojure working in my ubuntu vm... and when I load slime it looks for util.clj

16:09 slashus2: (defn >RGBA [vektor] (ColorRGBA. (map (fn [x] (float x)) vektor))) won't work?

16:09 Lau_of_DK: http://wiki.github.com/Lau-of-DK/sofiaba

16:10 slashus2: There u go - And yea, I needed a macro, which will be used several places for more than just this purpose

16:10 durka42: awesome

16:10 it looks... grainy

16:11 Lau_of_DK: Yea - texture is too detailed

16:11 I think it'll work once I scale it up to full playable size

16:13 durka42: what's the speed like?

16:13 Lau_of_DK: Its like... awesome

16:13 Before I added the water it ran at about 800 fps, I havent tested, but I'll add an fps counter soon, Im just in the middle of wrapping and extending functionality

17:01 dpthfltr: ok this is going to be a very very simple question ;) I have two strings and I want to create a seq that contains both.

17:01 what function can I use ?

17:02 rhickey: dpthfltr: (list s1 s2)

17:02 * dpthfltr bows to rhickey

17:27 hiredman: ,(into-array Character/TYPE "foo")

17:27 clojurebot: #<char[] [C@14d0183>

17:30 Lau_of_DK: http://github.com/Lau-of-DK/sofiaba/tree/master, for those following this, Ive pushed a massive change provinding quite a few wrappers, screenshots on the wiki - I stripped jmephysics, because its quite problematic in its current state

17:31 rhickey: name game again - I'm thinking of letfns for Clojure's letrec/labels

17:32 Lau_of_DK: example? Im not following

17:33 rhickey: http://paste.lisp.org/display/76297

17:34 ayrnieu: rhickey - why not 'flet' ? It implies something different in CL, but so does LET ; and {'let* 'let, 'labels 'flet} seems consistent.

17:35 and you can pronounce it instead of sort of mumbling it.

17:35 Lau_of_DK: rhickey: Rich does this have a wider application that Im not seeing, because to me it seems like its just adding bloat to Clojure

17:36 ayrnieu: s/implies/means/

17:36 rhickey: Lau_of_DK: mutually recursive local fns are not currently possible

17:38 Lau_of_DK: oh I see, its like a built in trompoline

17:38 gnuvince_: rhickey: would letfns have a different syntax? something like (letfns [f [x y] (+ x y), g [a b c] (* a (- c b))] body)?

17:38 Lau_of_DK: letfns sounds good to me, it fits well with the rest of clojure

17:38 gnuvince_: Or regular [f (fn [] (...))] ?

17:39 ayrnieu: letrec [also pronounceable] would have the usual syntax, and also work for mutually recursive data structures.

17:40 gnuvince_: Oh, I see you already posted code

17:41 ayrnieu: let-fns corresponds to let-if

17:41 gnuvince_: letfns is fine by me. labels doesn't really scream functions.

17:42 rhickey: gnuvince_: sample: http://paste.lisp.org/display/76297

17:43 gnuvince_: right, labels is definitely out, flet has reverse implications

17:43 letrec is more general

17:43 this is for fns only

17:43 gnuvince_: rhickey: does it support multiple-arity functions?

17:44 (letfns [(f ([x] x) ([x y] (+ x y)))] ...)?

17:44 rhickey: gnuvince_: sure

17:45 gnuvince_: Then it looks just damn fine to me :) The name is well chosen, the syntax is pretty good.

17:45 rhickey: I like flet, concerned about the reverse implication

17:45 Lau_of_DK: flet is awful

17:45 :)

17:46 rhickey: I always wished that flet did what labels did, hate the name labels

17:46 ayrnieu: anyone bothered by flet has gotten over being bothered by let

17:46 Lau_of_DK: oh, I just realized I hate it because its a danish name for certain way of styling your hair. :)

17:46 rhickey: there's also letf

17:47 letfn (not plural)

17:48 ayrnieu: let-fn again, like let-if

17:48 rhickey: ayrnieu: are you asking for a dash?

17:48 gnuvince_: between letfns and letfn, I think I'd go with letfn

17:50 ayrnieu: rhickey - I'd prefer that to letfn

17:51 rhickey: ayrnieu: dash unlikely, sorry. if-let when-let etc are two-step things

17:53 * rhickey looking at notes from 3 years ago, sees letf and letfn

17:53 gnuvince_: rhickey: you have notes from 3 years ago?

17:54 rhickey: yeah, all the Clojure design was done in Mac apps Notebook and OmniGraffle, Notebook has nice creation date view

17:55 dozens of variants of fn syntax on same page :)

17:55 gnuvince_: cool

17:55 Do you have notes on where you expected Clojure to be three years from then? :)

17:56 rhickey: nope, just tech specs, no way to have planned what happened

17:58 gnuvince_: I hope you're happy with where you are, it's truly amazing the explosion Clojure has seen in a little over a year in the public eye.

17:58 rhickey: gnuvince_: it's crazy

18:00 gnuvince_: bbl, diner

18:07 duncanm: i'm trying to use slime on linux, and i see this error when i load it up: java.lang.Exception: Unable to resolve symbol: lazy-seq in this context (core.clj:70)

18:10 slashus2: Is there a safe way to do io inside of a transaction? I was looking at the io! macro.

18:11 rhickey: slashus2: you can send to an agent which does the io after the transaction commits, otherwise no, because transactions can retry

18:12 hoeck: duncanm: are you using latest slime & latest clojure (github/svn versions)?

18:13 duncanm: i mean the latest jochu-swank-clojure, not slime, sorry

18:14 slashus2: Okay, didn't think of sending it off to an agent.

18:20 clojurebot: svn rev 1315; added letfn, supports mutually recursive local fns

18:23 slashus2: something like (send (agent @overall-count) println) sometimes prints two numbers beside each other in the output.

18:24 I am trying to do the producer consumer simulator.

18:25 Trying to print out when the producer produces a new number.

18:30 Lau_of_DK: hoeck: I updated SofiaBA heavily, and initially I had to write out jMephysics, because its unstable in its current state - sorry if I got your hopes up

18:30 Its not dropped, its just postponed a little bit

18:31 slashus2: http://pastebin.com/d61e802a3

19:51 Chouser: we could just hook the svn change feed directly to reddit

19:51 rhickey: heh

19:52 yeah, some of it isn't going to do anything but make people bored/annoyed

19:52 ayrnieu: This Week in Clojure

19:53 Chouser: *ahem* not to demean your latest feature, of course. :-)

19:53 rhickey: one more wart removed

19:53 gnuvince_: Speaking of TCO (again), is there any word if Sun is going to include it in JDK7?

19:55 rhickey: unlikely in 7 I think, but there's an implementation in MLVM already

19:55 Chouser: I'm much more interested in tagged numbers

19:55 rhickey: I haven't tried MLVM yet, nor do I know what I'd have to do to enable it

19:56 Chouser: though I guess TCO would be a PR win.

19:56 rhickey: Chouser: tagged numbers even further away I'm afraid

19:56 Chouser: am I right in thinking they would removed the need for most of the explicit primitive declarations?

19:58 rhickey: Chouser: TCO would be genuinely nice, not for loops, but for chained function calls on indefinite input, state machines etc

19:58 Chouser: tagged numbers have their own tradeoffs, #1 being that they lose a few bits vs. the machine word

20:01 [11:17am] Chouser: but this does not:

20:01 Cl-USER 4 > most-positive-fixnum

20:01 536870911

20:05 gnuvince_: So numbers would be 29 bits if they were tagged?

20:06 rhickey: gnuvince_: depends on the tagging scheme

20:06 gnuvince_: byte, short, int, long

20:06 Hmmm

20:06 ayrnieu: byte, short, int, long, tagged fixnum

20:07 rhickey: http://blogs.sun.com/jrose/entry/fixnums_in_the_vm

21:10 hiredman: I don't suppose anyone has tried/got to work serving content from an inputstream with ring?

21:36 Chouser: whee! http://paste.lisp.org/display/76305

21:37 gnuvince_: damn!

21:38 hiredman: ;_;

21:38 ayrnieu: well, at least it pretty-printed

21:39 hiredman: ugh

21:39 Chouser: I pretty-printed it manually. :-/

21:39 hiredman: how can I pack a binary array into a string?

21:40 gnuvince_: speaking of which, whatever happened to the pretty printing project?

21:40 hiredman: er

21:40 byte array

21:41 cmvkk: what, like base64 encoding or something?

21:41 Chouser: hiredman: String has a constructor that takes byte[]

21:41 rhickey: Chouser: hmm... an early version of the Clojure compiler removed (let []) and (if true ...)

21:42 hiredman: Chouser: yeah, but it doesn't seem to work well with a byte[] filled with jpeg data

21:42 Chouser: hiredman: sounds like a poor fit for a String. why do you want it?

21:43 ayrnieu: he's pretending that sockets are files, is why.

21:43 hiredman: because ring can serve content from a string

21:43 Chouser: ayrnieu: files can't store bytes??

21:43 hiredman: sounds like ring could use a new feature.

21:43 cmvkk: what's ring?

21:43 hiredman: yeah

21:44 I would really like to serve right from the inputstream I have

21:44 ~ring

21:44 clojurebot: ring is http://github.com/mmcgrana/ring/tree/master

21:45 hiredman: looks like adding that might be easier then I thought

21:46 actually

21:46 it looks like it should already work

21:56 ah

21:56 excellent

21:56 that does work

21:56 I must have been doing something wrong before, but now ring serves out of a CipherInputStream just fine

22:16 Drakeson`: Which virtual machine hosting you recommend/had success with? (to deploy clojure web applications, etc.)

23:13 mattrepl: Drakeson: http://slicehost.com is nice

23:16 Drakeson: thanks

23:30 cp2: Drakeson i have a vps with http://cheapvps.co.uk/

23:30 if you dont have a lot of money to spend, they are worth it

23:30 provided you can deal with managing it yourself

23:43 Drakeson: cp2: great. thanks. I want something that I can manage myself.

23:45 cp2: [sorry to ask this stupid question] is the term "VPS" what I have to search for?

23:46 cp2: huh?

23:47 Drakeson: I mean, is VPS hosting what I am looking for?

23:47 cp2: well, i guess

23:47 you said virtual machine hosting

23:47 vpses are virtualized dedicated servers

23:47 there are several on a big honkin' server

23:48 Drakeson: I was looking for the right term to google it. virtual machine hosting wasn't the right term ;)

23:48 cp2: heh

23:48 yeah, vps would be better

23:48 Drakeson: cp2: cool. thanks.

23:48 cp2: also, i would check http://www.webhostingtalk.com/

23:49 lots of reviews and such about providers

23:50 Drakeson: nice, there is a whole VPS hosting board there (in webhostingtalk)

23:50 cp2: yep

Logging service provided by n01se.net