#clojure log - Feb 11 2009

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

0:13 fynn: Hello.

0:13 hey, no need to quit so fat

0:13 I'm just looking for some estimates of clojure's performance

0:14 hiredman: netsplit

0:14 I have no hard numbers

0:14 I here it is fast enough

0:14 I think Chouser said it was too fast ofr him

0:14 hear

0:15 technomancy: fynn: Clojure can run the Kessel Run in under twelve parsecs.

0:15 ayrnieu: fynn - some estimates: http://groups.google.com/group/comp.lang.lisp/msg/75cd9bd772f1ed39

0:15 technomancy: that's fast~

0:15 !

0:15 fynn: ah here you are

0:16 technomancy: fynn: but I'm coming from Ruby and Elisp... so I'm probably not the best person to talk about performance.

0:16 hiredman: ayrnieu: late on in that thread someone says faster then sbcl

0:16 albino: as is usually stated, the normal problem is it's startup time

0:16 fynn: technomancy: yeah, I'm coming from Ruby myself

0:16 I mean, I did a lot of it.

0:17 technomancy: fynn: as long as your work is parallelizable then the advantages of clojure vs java should pay off

0:17 hiredman: yeah, the start up time, which is why you leave open repls around

0:17 fynn: "Overall, the speed ain't bad, it's about 10x faster than perl, python,

0:17 ruby, but x10-x20 slower than most of the Common Lisp Compilers (SBCL,

0:17 CMUCL, LispWorks, ACL)."

0:17 technomancy: but compared to Ruby it's blazing

0:17 fynn: (that's not saying much :P)

0:18 albino: fynn: what are you going to write with it that you need such speed?

0:18 fynn: technomancy: how does the parallelization thing factoring in?

0:18 albino: manipulations of very large data structures.

0:19 technomancy: fynn: well clojure apps are trivial to throw more cores at, and that's not true of most languages

0:19 hiredman: http://groups.google.com/group/comp.lang.lisp/msg/88c5fb880d2b1148

0:19 "In general one can suggest to give type hints to speed up things.

0:19 For a little test function that Rainer Joswig gave here in c.l.l some

0:19 weeks ago I got from x15 more runtime than sbcl to half the runtime of

0:19 sbcl with a few type hints. "

0:19 fynn: technomancy: why? I didn't think it was purely functional.

0:20 technomancy: I know what you said is true of Haskell for instance, but not sure why it holds for Clojure.

0:20 technomancy: fynn: there are side-effects allowed, but they're easy to separate out from the rest of your code

0:21 hiredman: and you don't need to worry about locking

0:21 ayrnieu: drakeson - no, clojure still uses CamelCase. And any dashful syntax would suffer from the built-in syntax that java interop enjoys.

0:21 fynn: OK, so basically it sounds that wrt parallelization, Clojure should have the same advantages of the purely functional.

0:22 technomancy: fynn: right. it's *possible* to intermix side-effects into regular code, but that would be Doing It Wrong.

0:22 Drakeson: ayrnieu: parenscript somehow works around javascripts camelCases.

0:22 technomancy: it's pretty easy to keep them where they belong

0:23 blbrown: ,(doc +)

0:23 clojurebot: "([] [x] [x y] [x y & more]); Returns the sum of nums. (+) returns 0."

0:23 Drakeson: what would go wrong if clojure did the same?

0:23 blbrown: ,(doc gen-and-save-class)

0:23 clojurebot: java.lang.Exception: Unable to resolve var: gen-and-save-class in this context

0:23 blbrown: does that function exist anymore

0:23 hiredman: nope

0:23 fynn: technomancy: interesting. and through all that, it's dynamic.

0:23 hiredman: AOT compilation got rid of it

0:23 fynn: being able to use type hinting is pretty powerful.

0:24 hiredman: Drakeson: among many things it would make javadoc's less useful, sense everyting would have a different name

0:24 ayrnieu: although a predictable name.

0:25 hiredman: the very tight java <-> clojure interop is a huge win

0:25 technomancy: Drakeson: I think it's an issue of motivation rather than technical challenges

0:25 hiredman: the amount of stuff that ships in the jre is nuts

0:26 technomancy: ...though half of it is deprecated.

0:26 hiredman: :P

0:26 blbrown: too bad that a lot of the examples in the clojure book don't work

0:26 hiredman: blbrown: the wikibook?

0:26 blbrown: hiredman, programming clojure book, it seems to out of date. A lot of the functions dont exist anymore

0:27 ayrnieu: blbrown - it's only content-complete.

0:27 hiredman: uh

0:27 technomancy: blbrown: check the project on github

0:27 hiredman: *shrug*

0:27 * hiredman hasn't bought it

0:27 technomancy: blbrown: that's being kept more up-to-date; it's got tests and everything

0:27 Drakeson: technomancy: I know, there is no technical challenge in that. refer :rename could accept a form instead of a map.

0:28 hiredman: Drakeson: well, if it is something you want bad, write a macro for it

0:28 I think it is silly

0:29 but, whatev floats your boat

0:29 ,(let [boat 1](class (float boat)))

0:29 clojurebot: java.lang.Float

0:30 technomancy: nice

0:30 Drakeson: :)

0:30 fynn: what's the best resource to learn Clojure?

0:31 hiredman: writing clojure

0:31 ayrnieu: fynn - good resources include: the wiki, the book, this channel, clojure projects.

0:31 Drakeson: fynn: have you watched the tutorials on blip.tv?

0:31 hiredman: I started with project euler

0:32 fynn: Drakeson: bah, I'm a Real Programmer, I don't watch tutorials ;P

0:32 ayrnieu: so call it a 'screencast'. Those are pretty cool.

0:32 fynn: this book? http://www.pragprog.com/titles/shcloj/programming-clojure

0:32 ayrnieu: Yes.

0:32 fynn: oh, a screencast, most certain I will watch.

0:33 technomancy: oh wow, there's a lot more stuff on blip.tv now

0:33 fynn: anyways, trying to figure out what's special about Clojure

0:33 hiredman: technomancy: url me please, I am lazy

0:33 Drakeson: fynn: then definitely watch those screencasts.

0:33 technomancy: hiredman: well I haven't looked at this since november, so take "new" with a grain of salt: http://clojure.blip.tv/posts?view=archive&nsfw=dc

0:34 blbrown: technomancy, can I just change 'gen-and-save' to 'gen-class' here. http://github.com/stuarthalloway/programming-clojure/blob/a3c829f5726c0ab1e565aff86a2e68eca8539a47/examples/junit.clj

0:34 hiredman: I doubt it

0:34 post AOT gen-class is rather different

0:34 fynn: I see only 8 tutorials there...

0:35 hiredman: they are not really tutorials

0:35 Drakeson: what the ones by rich hikey :)

0:35 hiredman: last I checked

0:35 Drakeson: bah. s/what/watch

0:35 hiredman: they where rhickey explaining why he created clojure

0:35 and what is cool about it

0:35 mrsolo_: those screencasts aren't tutorial, agree

0:36 hiredman: clojurebot: mock object?

0:36 clojurebot: Your mock object is a joke; that object is mocking you. For needing it. -- rhickey

0:37 blbrown: hiredman, yea, it is pretty different...great

0:39 hiredman: gen-class is :(

0:39 blbrown: means I have to read stuff, darn

0:40 hiredman: but yeah, proxy won't work for JUnit

0:40 clojurebot: gen-class?

0:40 clojurebot: No, hiredman, you want gen-interface + proxy

0:40 Chouser: blbrown: http://clojure.org/compilation

0:41 The code will be *very* similar, using gen-class instead of gen-and-save...

0:41 how you call it will be different: you'll have to get your classpath right and call 'compile'

0:43 fynn: what would happen to the JVM if Sun is in too deep of a trouble?

0:43 ayrnieu: Rome will be unbuilt in a day, is what will happen.

0:44 hiredman: dunno, ibm has their own jvm

0:44 the apache foundation has theirs

0:44 there is the openjdk

0:44 Drakeson: fynn: JVM is already released as open source, and there are other people working on that. Like, project "Iced Tea" (backed by redhat, I guess)

0:44 fynn: isn't the IBM JVM actually faster than the Sun JVM

0:45 albino: Harmony

0:45 fynn: Drakeson: well, if it's fully opensourced than I guess people could always maintain the codebase.

0:45 albino: oh and JRocket

0:45 hiredman: IBM is full of dudes with beards, I bet their jvm makes bacon and eggs too

0:46 openjdk is not completely open

0:46 icedtea is a project to address that

0:46 Drakeson: hiredman: yet icedTea is.

0:46 hiredman: harmony is completely open

0:46 fynn: if Sun goes under, we'll all have to grow a beard :(

0:46 hiredman: and under the apache license

0:47 instead of sun's modified gpl

0:47 Drakeson: hiredman: http://en.wikipedia.org/wiki/IcedTea

0:47 hiredman: Drakeson: thank you for a wiki page I have read al ready

0:47 albino: Harmony is the basis for android IIRC

0:47 hiredman: no

0:48 albino: oh?

0:48 which one then?

0:48 hiredman: the harmony class libraries are used on android

0:48 albino: right, sorry not as specific, but what I was getting at

0:48 hiredman: android uses some other vm

0:49 albino: so basically java won't die with sun

0:49 ayrnieu: also: Rome is still around.

0:49 albino: if ever :)

0:49 * hiredman should try harmony again

0:49 hiredman: last time the vm would not build do to a bunch of linuxisms

0:50 due

0:50 ozy`: I wonder if google would buy sun when it's finally about to croak

0:50 hiredman: ugh, this is not the night for my typing

0:50 albino: someone would surely try and buy up solaris, maybe ibm

0:51 would be interesting to see Microsoft try and buy up some of the assets

0:51 Drakeson: hiredman: which one was under apache license?

0:52 albino: Drakeson: http://harmony.apache.org/

0:52 hiredman: ^-

0:52 Drakeson: what about openjdk?

0:52 hiredman: modified gpl

0:54 albino: Is Harmony written in C?

0:54 The VM I mean

0:54 Raynes: Must not be vary harmonial.

0:54 hiredman: http://freejdk.org/faqs/openjdk_license.html

0:54 I thought c++

0:55 Drakeson: hiredman: thanks

0:57 hiredman: I did nothing, but you are welcome

0:57 blbrown: Chouser, do you see the compiliation issue there, anything I am missing. http://paste.lisp.org/display/75247

0:58 hiredman: ugh, I forgot the harmony build does some dependency fetching stuff

0:59 blbrown: Sun's JVM is c++

0:59 hiredman: the last time I tried building harmony I think I was try to use ikvm too

0:59 Raynes: blbrown: Most of it is written in C if I remember right.

1:00 hiredman: blbrown: the directory structure needs to match the class name

1:00 I would use :genclass in the ns macro instead of seperately

1:01 blbrown: Raynes, no it isn't, hotspot is C++. The class libraries might be written with C. E.g. Java's FFI (the name escapes me right now)

1:03 Raynes: No I'm pretty sure a lot of it is written in C. :\

1:03 blbrown: I am looking at it, openjdk nov 2008

1:04 Raynes: Then, a lot of people are wrong.

1:04 blbrown: http://en.wikipedia.org/wiki/HotSpot

1:04 Raynes: blbrown: I believe you.

1:04 ozy`: a lot of people don't know or don't care about the difference between C and C++

1:05 Raynes: I'm just saying, a lot of people are wrong.

1:09 blbrown: hiredman, what would I change in my example, I am following the compilation docs, and getting the same error.. I have a directory: test/. and then test/OctaneTestGen.clj

1:10 hiredman: blbrown: what is your classpath?

1:11 blbrown: good point

1:12 hiredman, .... .:./test:src:/ and then the clojure libraries

1:13 hiredman: is junit in your classpath?

1:13 blbrown: yep

1:13 hiredman: also, ./classes/ needs to be in your classpath

1:13 blbrown: what is ./classes

1:14 ayrnieu: ,*compile-path*

1:14 clojurebot: nil

1:14 blbrown: ahhh, interesting

1:14 hiredman, yea, it was classes in the classpath

1:14 hiredman: classes is where the compiled classes get put

1:14 you can set *compile-path* to change that

1:15 blbrown: I missed that in the docs

1:15 ayrnieu: *compile-path* is, rather. It isn't emphasized enough that this must A) exist, to put things into, and B) be in your classpath, even if you won't use what you've just put it in there.

1:15 blbrown: gracias

2:06 jesse: hi, I'm new to clojure. Porting some python code. Can anyone tell me the proper way to do something like this in clojure:

2:06 west, north, east, south = 0,1,2,3

2:06 an enum type thing

2:07 ayrnieu: just use symbols.

2:07 ,'(west north east south)

2:07 clojurebot: (west north east south)

2:07 jdz: or keywords

2:07 hiredman: keywords might be the clojure choice

2:07 jdz: (def directions [:west :north :east :south])

2:08 hiredman: you have something more complicated then that example a hash

2:08 (def directions {:west 0 :north 1 :east 2 :sourth 3})

2:08 or whatever

2:09 jdz: naah, my example is better

2:09 hiredman: jdz: your example doesn't map from keyword to number

2:09 ayrnieu: yes it does, hiredman.

2:09 hiredman: ,( [:west :north :east :south] 0)

2:09 clojurebot: :west

2:09 hiredman: works

2:10 but most liekly you want to go the other way

2:10 jdz: well, it's the other way around: it maps from number to keyword

2:10 ayrnieu: you can also go the other way with that.

2:10 hiredman: you can

2:10 jdz: but that is what i think more useful mapping

2:10 hiredman: sure

2:10 but is it as natural as

2:10 ,({"west 1} :west)

2:10 clojurebot: Eval-in-box threw an exception:EOF while reading string

2:10 hiredman: ,({"west 1}" :west)

2:10 clojurebot: Eval-in-box threw an exception:Unmatched delimiter: )

2:10 hiredman: whatever

2:11 you get my meaning

2:11 jdz: in reality one would probably want to have both: the map that maps from names to numbers, and the array that maps numbers to names (for calculations)

2:14 but returning to the python example, i guess it's just 4 variables

2:14 and you define variables with def in clojure

2:15 (for some meanings of variables)

2:15 jesse: ok, how do I use a symbol after defining it?

2:15 hiredman: uh

2:15 ayrnieu: jesse - you just name it.

2:15 hiredman: ,'w

2:15 clojurebot: w

2:15 hiredman: ,'west

2:15 clojurebot: west

2:15 ayrnieu: ,['a :a] ;; <-- no special work.

2:16 clojurebot: [a :a]

2:16 jesse: (west) --> Unable to resolve symbol: west in this context

2:16 hiredman: uh

2:16 ayrnieu: jesse - there's no 'define' step with symbols; jdz only bound a list of symbols to a name.

2:16 hiredman: the is a function call

2:17 west is not a function

2:17 it is a symbol

2:17 symbols may or may not name functions

2:17 jdz: i think a tutorial on lisp would be handy at this point

2:17 hiredman: Yes.

2:17 jesse: heh, i guess

2:18 hiredman: clojurebot: lisp?

2:18 clojurebot: lisp is the red pill

2:18 hiredman: clojurebot: sicp?

2:18 clojurebot: sicp is http://web.mit.edu/alexmv/6.001/sicp.pdf

2:20 jesse: ok, let me try again...

2:20 (def west 0)

2:20 (def north 1)

2:20 (def east 2)

2:20 (def south 3)

2:20 (def my_dir west)

2:20 (prn my_dir)

2:21 hiredman: woa

2:21 jesse: how do i make that shorter?

2:21 hiredman: paste bin

2:21 jesse: didn't go through? woops :)

2:21 hiredman: it did

2:21 jesse: looks good on my end...


2:21 hiredman: that is a lot more declaration then I care to see

2:21 jesse: why? just six lines?

2:21 hiredman: more then three

2:22 jdz: jesse: so why do you want to make it any shorter if it's just six lines?

2:22 jesse: There's more that follows the same pattern

2:22 This is in Directions.py

2:22 hiredman: jesse: def is used for things that do not change

2:22 jesse: I use it all over the place

2:22 jdz: ,(let [[west north east south] [0 1 2 3] my-dir west] (prn my-dir))

2:22 clojurebot: 0

2:22 hiredman: so (def my_dir west) is silly

2:22 lisppaste8: ayrnieu pasted "functions as readable maps" at http://paste.lisp.org/display/75250

2:23 hiredman: since I guess you will be changing direction?

2:23 jesse: In python I would call Directions.west instead of remembering values

2:23 as in my_dir = Directions.west

2:23 hiredman: ok

2:23 make a hash

2:24 (def directions {:west 1 :etc 2})

2:24 then you do

2:24 (:west directions)

2:24 -> 1

2:25 jesse: cool, looks good

2:25 hiredman: and for god's sake, http://web.mit.edu/alexmv/6.001/sicp.pdf

2:26 jdz: jesse: you can't write code in one programming language by directly mapping constructs from other programming language (unless they are both imperative algol-like)

2:26 jesse: as ayrnieu showed, you don't need any numbers at all for directions

3:11 alinpopa: good morning to all

5:02 timothypratley: in core.clj I see (create keys) but I can't find where 'create' is defined

5:11 ah stupid me sorry ignore that question

6:17 AWizzArd: How can I alias a namespace inside its setup (ns xyz ...)?

6:18 ,(doc alias)

6:18 clojurebot: "([alias namespace-sym]); Add an alias in the current namespace to another namespace. Arguments are two symbols: the alias to be used, and the symbolic name of the target namespace. Use :as in the ns macro in preference to calling this directly."

6:19 AWizzArd: So, this suggests to use :as, and I also tried (ns foo (:as bar))

6:19 ,(ns foo (:as bar))

6:19 clojurebot: java.lang.Exception: No such var: clojure.core/as

6:19 jdz: AWizzArd: why do you want to do that?

6:19 AWizzArd: because my namespace is (ns de.longcompanyname.gui.tools.LoggingTool)

6:19 jdz: and?

6:20 AWizzArd: and I don't always want to type this long beast

6:20 jdz: that's when you use alias

6:20 AWizzArd: (alias 'log 'de.longcompanyname.gui.tools.LoggingTool) works, but I thought this can be done directly inside the (ns ..)

6:21 jdz: aliasing is the tool for users of the namespaces, not the authors

6:21 so to speak

6:21 you don't know what the users of said namespace want to name them in short

6:21 and you should not impose your nicknames on others

6:21 Chousuke: you don't need to refer to the full namespace in the file that defines it anyway

6:21 only when you :use or :require it in another namespace, and you have :as in those cases :)

6:22 AWizzArd: yes ok, makes sense

6:22 Moin Achim

6:23 for testing purposes I will then use (alias ..) during development

6:23 achim_p: hi!

6:23 jdz: AWizzArd: i use in-ns during development personally

6:23 Chousuke: AWizzArd: why do you need alias inside the namespace itself though? :/

6:24 after the (ns foo ...) form is evaluated, foo becomes the default namespace, and does not need to be explicitly qualified

6:24 so making an alias for it would be useless.

6:24 AWizzArd: I want this alias to be available in user

6:25 Chousuke: ah, well, I think you can just (require '[yournewnamespacewithalongname :as nn]) in the user namespace

6:25 I never remember the syntax right though.

6:59 AWizzArd: atoms make sense for Singletons that should be changeable during runtime, yes?

7:04 Chousuke: why not refs?

7:04 or well, I guess it depends on what you need.

7:08 a global atom might make sense for some function or value that is generally constant, but might need to be changed sometimes

7:21 timothypratley: user=> (isa? *e java.lang.Throwable)

7:21 false

7:21 what am I doing wrong?

7:24 user=> (class *e)

7:24 clojure.lang.Compiler$CompilerException

7:25 oh.....

7:25 user=> (isa? (class *e) java.lang.Throwable)

7:25 true

7:25 opps!

7:27 durka42: try instance?

7:28 timothypratley: even better! thanks

7:34 AWizzArd: When I write small scripts in Clojure which I want to run from the command line, how can I do this then? Can I also pass command line args?

7:39 For example, if I have a file foo.clj that just contains a (print "Hallo"), how do I run it then from the shell?

7:50 Holcxjo: AWizzArd: java -cp .../some/path/clojure.jar clojure.main helloworld.clj

7:51 AWizzArd: see java -cp .../some/path/clojure.jar clojure.main -h

8:01 leafw: is there any reason why doing an (import '(java.io File)) inside a binding block that also includes usage of that File class, fails? the File class is not found.

8:01 AWizzArd: Holcxjo: thx

8:46 leafw: a user is reporting to me that (load-file "D:\path\to\file") fails ... with D\ unknow char or something. Does anybody here use windows? I can't test such thing.

8:46 oooh never mind. I saw the problem.

8:47 forest: \\ ?

8:47 AWizzArd: yup

8:47 jdz_: doesn't / also work on winblows nowadays?

8:56 leafw: jdz_: yes, it does. But I forgot here to .replace('\\','/') ...

8:56 and when +'ing strings, the backslashes broke hell.

8:58 also:is there any way to set the number of threads for the thread pool of a pmap command? Would be nice to be able to set it. As I see it, it's hardcoded to (+ 2 (.. Runtime getRuntime availableProcessors).

9:11 AWizzArd: leafw: it's indeed hardcoded... however, in principle this value makes sense.

9:12 let_f_: dioesnt set have union, difference etc?

9:13 leafw: AWizzArd: it doesn't when one doesn't want to bring a machine to its knees. I.e. I may want to leave the GUI reponsive, with one or two cores for it.

9:13 jdz_: AWizzArd: yeah, but it would be cool to let pmap use only, say, 6 of 8 cores

9:13 leafw: I think it's possible to add an extra initial arg to pmap, but that would break exisiting code.

9:14 i don't know how to add 'key' extra args.

9:14 jdz_: another solution is for pmap to use a var which could be bound

9:14 leafw: jdz_: indeed.

9:14 that sounds nicer.

9:15 like *max-cores* or so.

9:15 cooldude127: let_f_: yes, they are in clojure.set

9:16 (doc clojure.set/union)

9:16 clojurebot: (doc clojure.set/union)

9:16 clojurebot: clojure is a very attractive hammer with a nice heft to it

9:16 cooldude127: ok then

9:16 ,(doc clojure.set/union)

9:16 clojurebot: "([xset yset]); Returns a set that is the union of the two sets."

9:22 let_f_: i find it annoying i cant find functions that operate on a specific type easily, like dir(set) in python.

9:22 i see i didnt know there were such namespaces in the core

9:23 can i lsit all fucntions ina namespace?

9:23 cooldude127: let_f_: probably, but i'm not immediately sure how

9:23 and the reason you can do that in python is because all those are methods that are attached to a class

9:24 this is not object-oriented programming, nor is there static typing, so there is no obvious way to figure something like that out

9:25 let_f_: but there is if for some functions if they are in a namespace

9:25 i could obv make a function that operatos on a object in python and it wouldnt be listed with dir(object)

9:25 cooldude127: let_f_: yes, if it was a standalone function

9:25 let_f_: cant i map over a set and keep it a set?

9:26 Chouser: http://clojure.org/namespaces

9:26 let_f_: user=> (map inc #{1 2 3})

9:26 (2 3 4)

9:26 cooldude127: let_f_: map i think returns a seq, so if you still need a set, just call set on the result

9:26 Chouser: ,(into #{} (map inc #{1 2 3}))

9:26 let_f_: (set (map f set-))

9:26 clojurebot: #{2 3 4}

9:26 cooldude127: ,(set (map inc #{1 2 3}))

9:26 clojurebot: #{2 3 4}

9:26 let_f_: yes but it clutters

9:26 cooldude127: let_f_: that's how you do it

9:27 map is lazy, so it returns a seq

9:27 let_f_: ok

9:27 Chouser: ,(keys (ns-publics 'clojure.set))

9:27 clojurebot: (rename-keys union select project join intersection map-invert difference rename index)

9:28 cooldude127: Chouser: damnit, i was just looking that up

9:28 jdz: ,(map first (ns-publics 'clojure.set))

9:28 clojurebot: (rename-keys union select project join intersection map-invert difference rename index)

9:28 cooldude127: i had found ns-publics, came back to do it, and i see it's already there

9:28 jdz: yeah, what chouser said :)

9:34 let_f_: why is inverting a map in set?

9:34 user=> (clojure.set/map-invert {1 2 3 4})

9:34 {2 1, 4 3}

9:36 Chouser: clojure.sets is actually about doing "relational" stuff

9:37 sets/index, for example, takes a set of maps and returns a map of maps indexed however you specify.

10:14 clojurebot: svn rev 1272; Revert: improved Maven integration, patch from hlship [issue 70], broke destination directories

10:14 svn rev 1273; added class name to No matching ctor message

10:26 Chouser: the new Counted interface makes the clojure classes chart unreadable. :-P

10:32 gnuvince: Chouser: link?

10:33 Chouser: ummm...

10:34 http://chouser.n01se.net/misc/tmp.png

10:34 the arrows from column 3 to 4 are dense, but can be followed with the eye

10:35 from column 4 to 5, though, I can't tell where they're going

10:37 danlarkin: especially from, say, AFn -> Obj

10:39 Chouser: right, or IPersistentSet down to ... ???

10:39 danlarkin: ouch, yeah

10:40 walters: Chouser: can you just widen it?

10:41 it only takes up about half of my 1920x1200 monitor =)

10:41 Chouser: walters: maybe. how well do you know dot? :-)

10:41 jdz: walters: your 1920x1200 does not compare to my 2560x1600 monitor :)

10:42 walters: Chouser: last played with it years ago unfortunately

10:42 jdz: heh

10:42 jdz: and generating .pdf or some other vector format would be great

10:43 Chouser: the most recent released version is at http://tinyurl.com/clojure-classes -- there's an SVG format there

10:45 rsynnott: ooh, pretty

10:46 Chouser: what'd you use to generate it?

10:48 jdz: rsynnott: see the URL

10:51 Chouser: clojure -> dot -> inkscape -> gimp

10:51 :-/

10:51 AWizzArd: I have a coll of objects and want to add them to a hashmap with a specific key. Is there something more idiomatic than:

10:51 ,(apply merge (map #(assoc {} %1 %2) [:a :b :c] (range 3)))

10:51 clojurebot: {:c 2, :b 1, :a 0}

10:51 Chouser: ,(zipmap [:a :b :c] (range 3))

10:51 clojurebot: {:c 2, :b 1, :a 0}

10:52 AWizzArd: goood :)

10:52 Chouser: :-) used it for the first time a couple days ago.

10:54 rsynnott: ah, impressively concise!

10:57 ozy`: ,(doc zipmap)

10:57 clojurebot: "([keys vals]); Returns a map with the keys mapped to the corresponding vals."

10:58 AWizzArd: Chouser: great that you remembered it. I really want/need it now.

11:03 Is there a reader mac.. syntax for hashtables in Java? Such as { e1, e2, e3 } for Arrays?

11:04 leafw: AWizzArd: nope.

11:04 walters: no...but if you really need it you can fake it by using an anonymous inner subclass of HashMap

11:04 leafw: AWizzArd: or, at leas,t never came across it in years.

11:05 walters: new HashMap<String,Object>() { { put("foo", 10); put("bar", new Object()); }}

11:05 drdo: How can i create a type?

11:10 let_f_: is it possible to define a method Show like in haskell so everytime a thing is returned its proper representation isnt showed but a prettyprinte one?

11:11 Chouser: if you use the repl in contrib, I believe you can override the function used by default to print

11:18 Holcxjo: Chouser: Next question: how do you use the repl in contrib? :-) Especially from slime?

11:18 let_f_: good question :)

11:18 it is good for dsls

11:19 Chouser: sorry, I've not used the repl from contrib, and I've not used slime.

11:21 Holcxjo: Plus of course: Why are there two repls?

11:23 Chousuke: someone thought the default one wasn't good enough? :)

11:23 rsynnott: Holcxjo: slime provides its own repl, so might be tricky

11:23 what extra stuff does the contrib one do?

11:23 Chouser: (use '[clojure.contrib.repl-ln :only (repl)]) (repl :print #(println "Custom:" (pr-str %)))

11:24 that works at a plain shell prompt (and probably in inferior lisp mode or whatever its called)

11:24 rsynnott: with slime you're not using inferior lisp mode, though

11:25 AWizzArd: Wasn't there a complete implementation of CLs FORMAT?

11:25 let_f_: i want all permutations of 3 nested ranges, how?

11:26 Chousuke: AWizzArd: yeah

11:26 ~format

11:26 clojurebot: It's greek to me.

11:26 Chousuke: hmm

11:26 AWizzArd: there is this format from Java, which should be sufficient for most things

11:27 Chousuke: clojurebot: format is http://github.com/tomfaulhaber/cl-format/tree/master

11:27 clojurebot: c'est bon!

11:27 AWizzArd: But iirc someone said a few days ago that, ah yes

11:27 rsynnott: next step, a complete implementation of the CL extended loop :)

11:28 Chousuke: hmm, nice

11:28 "cl-format is 100% compatible with the Common Lisp standard as specified in CLtLv2 with the exception of the support directives for the pretty printer."

11:28 Chouser: let_f_: (clojure.contrib.combinatorics/cartesian-product [1 2 3] [4 5 6] [7 8 9])

11:29 or (for [a [1 2 3], b [4 5 6], c [7 8 9]] [a b c])

11:29 or doseq

11:31 Chousuke: ooh, he's working on a pretty printer too :/

11:31 let_f_: can someone link to the simplest possible implementation of a lisp-interpreter?

11:33 AWizzArd: let_f_: that would be Scheme. Try wikipedia.

11:33 The standart of Scheme is just a few pages

11:33 Chousuke: hm

11:34 Holcxjo: It used to be smaller than the index of CLtL2 but has become more complex with R5RS and R6RS I believe

11:34 Chousuke: I saw a ~two-hundred line lisp interpreter written in C once :/

11:34 but I can't remember wehre

11:35 it didn't even have garbage collection :)

11:36 AWizzArd: what I find funny is the Lisp version of 99 bottles in CL: http://99-bottles-of-beer.net/language-common-lisp-114.html

11:37 Chouser: "almost a language of its own" is clearly an understatement.

11:38 rsynnott: the loop (rather than format) version would be clearer, still a language of its own, but less impressive/intimidating-looking

11:39 * rsynnott tends to avoid the weirder format stuff

11:39 Chouser: loop is also pretty much its own language

11:39 in CL, not Clojure of course

11:45 AWizzArd: Also in Clojure, but it's dramatically much simpler.

11:46 Chouser: what? maybe 'for' and 'doseq' have their own (very simple) language, but loop only has the same (also very simple) destruturing as let, fn, etc.

11:47 so is this better or worse? http://chouser.n01se.net/misc/tmp2.png

11:47 AWizzArd: vs?

11:47 danlarkin: oh jeez

11:47 Chouser: vs. http://chouser.n01se.net/misc/tmp.png

11:47 danlarkin: worse I think

11:48 AWizzArd: I vote for tmp.png

11:48 Chouser: tmp.png isn't sufficient, though. it's absolutely unusable for several edges.

11:50 knobo: Has anyone made a clojure application for mobile telephones?

11:51 Chouser: There's a hello-world for android. Not sure about JME.

11:51 knobo: I have a small app, that I would like to install on my sony ericsson, but I don't know how to du it.

11:52 AWizzArd: knobo: if you find out how to do it, then please write a how-to in the google group

11:52 knobo: AWizzArd: I'll do that.

11:53 AWizzArd: knobo: the first thing I would try to do is to download the right sdk. If your handy can run a full jre it would be the jdk. If it supports the JME then download that, or for google handys Android.

11:53 And you should compile your code into a .jar file, which you can then bluetooth to your phone.

11:54 I also have a SE handy, and that one would need the JME. Thats what I guess.

11:54 the sdk for the ME comes with a simulator I think

11:54 but this could fail, as the ME has ridiculous size limitations of your programs

11:55 as if phones won't have gigs of memory today

11:57 How can I partition [x1 x2 x3 x4 x5 x6] into ([x1 x3 x5] [x2 x4 x6])?

11:58 rsynnott: Chouser: clojure's destructuring still beats cl's, though

11:58 Chouser: ,(split-at 3 (range 6))

11:58 clojurebot: [(0 1 2) (3 4 5)]

11:58 gnuvince: Chouser: wrong ordering

11:59 Chouser: oh!

11:59 sorry

12:00 ayrnieu: AWizzArd - call it 'deinterleave'

12:00 AWizzArd: yes ;)

12:00 well, one can do some magic with iterate, to have the indexes and can then mod or something like that

12:01 Chouser: ((fn [s] [(take-nth 2 s) (take-nth 2 (rest s))]) (range 6)), but that's not very satisfying.

12:01 knobo: AWizzArd: thanx for the hints.

12:01 ayrnieu: just write a recursive function for it.

12:02 drdo: How can i create a new type?

12:02 Chouser: drdo: why do you think you need a new type?

12:03 drdo: Chouser: Let's not get started on that

12:03 Chouser: drdo: generally algorithms in Clojure make use of combinations of vectors, lists, maps, etc.

12:04 you can tag any of those with metadata if you want to differentiate one kind from another

12:04 ,((fn [s] (map #(take-nth 2 %) [s (rest s)])) (range 6))

12:04 clojurebot: Eval-in-box threw an exception:java.lang.reflect.InvocationTargetException

12:04 Chouser: clojurebot's having issues. that should work.

12:05 drdo: So i cannot create a type indistinguishable from a built-in type?

12:05 Chouser: drdo: sure you can, but it's fairly uncommon, which is why I asked "why" :-)

12:06 use can use 'proxy'

12:06 drdo: Ok, so how can i?

12:10 lisppaste8: AWizzArd pasted "short example of proxy for drdo" at http://paste.lisp.org/display/75268

12:12 ayrnieu annotated #75268 with "more comprehensive example" at http://paste.lisp.org/display/75268#1

12:15 Holcxjo: AWizzArd: (for [idx (range 2)] (map #(nth % idx) (partition 2 [1 2 3 4 5 6])))

12:15 But that's also quite verbose

12:21 AWizzArd: Btw, ayrnieu, were futures added to Clojure?

12:21 ayrnieu: src/clj/clojure/core.clj:future-call

12:22 AWizzArd: my clojure.jar is from Feb 5 and I don't have it ;)

12:24 ayrnieu: he pushed it two days ago, I think.

12:41 let_f_: anyone use yahoo boss api?

12:41 i dont get how to ownload the api

12:45 cemerick: rhickey: is there any reason to think that AOT compilation will produce smaller classfiles at some point in the future?

12:48 danlarkin: ,(with-meta :foo {:bar true})

12:48 clojurebot: java.lang.ClassCastException: clojure.lang.Keyword cannot be cast to clojure.lang.IObj

12:54 danlarkin: shouldn't that be okay?

13:10 Chouser: danlarkin: no, keywords don't support metadata.

13:11 they're interned, so there's really only one copy

13:11 danlarkin: hrmph

13:11 Chouser: ,(identical? :foo :foo)

13:11 clojurebot: true

13:11 Chouser: symbols, on the other hand, are not interned and so you can have many copies.

13:11 ,(identical? 'foo 'foo)

13:11 clojurebot: false

13:11 ayrnieu: ,(identical? :foo ::foo)

13:11 clojurebot: false

13:12 Chouser: ayrnieu: yeah, but that's something else entirely. :-)

13:12 danlarkin: I guess I'll use symbols then :) Thanks almighty chouser

13:12 or all knowing, rather

13:12 Chouser: yikes. "helpful" would be fine, thanks. ;-)

13:13 kotarak: ,(identical? :user/foo ::foo)

13:13 clojurebot: false

13:13 ayrnieu: ,*ns*

13:13 clojurebot: #<Namespace sandbox>

13:13 ayrnieu: ,::foo

13:13 clojurebot: :sandbox/foo

13:17 rsynnott: stop torturing the poor machine :)

13:17 Chouser: ,(identical? ::foo :sandbox/foo)

13:17 clojurebot: true

13:18 Chouser: ,(when 'ok? (println "I'm ok"))

13:18 clojurebot: I'm ok

13:19 rsynnott: it's a very friendly one

13:20 'minion' in #lisp gets annoyed when people talk to it too muc

13:23 erohtar: danlarkin: u here?

13:23 danlarkin: erohtar: ya

13:24 erohtar: danlarkin: sorry to bug u all the time

13:24 danlarkin: having trouble using clojure-json with the latest clojure - specifically it breaks on rev 1263

13:24 danlarkin: i get this error just trying to require it -

13:25 danlarkin: (require '(org.danlarkin [json :as json]))

13:25 danlarkin: java.lang.NoSuchMethodError: clojure.lang.MultiFn.<init>(Lclojure/lang/IFn;Ljava/lang/Object;)V

13:25 at org.danlarkin.json.encoder__init.load(Unknown Source)

13:25 at org.danlarkin.json.encoder__init.<clinit>(Unknown Source)

13:25 at java.lang.Class.forName0(Native Method)

13:26 and MultiFn.java has changed between 1262 and 1263 - looking at it now

13:27 danlarkin: erohtar: try to use a paste bin for pasting more than a line or two, please. I'm on r1273 of clojure and (require '(org.danlarkin [json :as json])) works fine for me...

13:28 erohtar: danlarkin: what about contrib, do u use anything there?

13:28 danlarkin: only in test.clj

13:30 erohtar: danlarkin: i cant understand it.... all im doing is a require on the repl, literally... and it works wiht rev 1261 and not with 1262 onwards

13:31 danlarkin: erohtar: if you comment out the add-encoder macro in json.clj will it work?

13:31 erohtar: hmm

13:31 danlarkin: i am using the jar

13:31 danlarkin: let me try with code

13:32 danlarkin: erohtar: have you rebuilt the jar since upgrading clojure?

13:32 durka42: fwiw, seems to work for me with latest

13:33 erohtar: danlarking: duh - i have not

13:34 danlarkin: erohtar: I think you may need to :)

13:34 erohtar: danlarkin: lemme do that now

13:34 danlarkin: im not this stupid usually :) long time no java

13:36 danlarkin: erohtar: and are you passing -Dclojure.jar=/path/to/clojure.jar to ant? that will AOT compile the clojure code

13:37 erohtar: danlarkin: recompiling it now

13:38 danlarkin: that worked, thanks!

13:39 danlarkin: shall i stay with the jar, or go with a git submodule that uses ur clojure code?

13:39 danlarkin: umm that's up to you

13:40 too many factors would influence that decision for me to make it for you

13:42 Lau_of_DK: Good evening all

13:43 kotarak: Hi Lau

13:55 erohtar: danlarkin: from a performance stand point, do jars (since theyre compiled) work faster than clj?

13:56 danlarkin: erohtar: jars created with AOT compiled clojure code will load faster, but not perform faster

13:56 Chouser: compilation and packaging to jars are two independent things

13:56 rsynnott: compiled on load anyway, no?

13:56 erohtar: and i guess the compiled on load stuff gets cached somewhere

13:56 ?

13:57 Chouser: rsynnott: yes

13:59 rsynnott: probably a good move

14:00 sbcl took the same approach (no interpreter used, though as of a year or so ago there is one if you REALLY want it)

14:00 and the result is JIT-able JVM bytecode, yep?

14:01 durka42: hmm, if one could write a compiler that was faster than the zip decompression algorithm, that would be pretty incredible

14:01 rhickey: anyone with JDK 6 and not OS X who could try something for me in the lazy branch?

14:03 Lau_of_DK: sure, if its not more complicated than I can figure out :)

14:04 rhickey: Lau_of_DK: build the latest lazy and try this a few times in a row at the repl:

14:04 (time (reduce + 0 (filter even? (map inc (range 1000000)))))

14:04 Lau_of_DK: k, which command can I use to checkout that branch ?

14:04 clojurebot: svn rev 1274; [lazy] use seq rather than relying on implicit seq of first/more in core sequence fns

14:05 Lau_of_DK: svn checkout http://clojure.googlecode.com/svn/trunk/ clojure-read-only -b something?

14:05 ayrnieu: svn co http://clojure.googlecode.com/svn/branches/lazy

14:07 brianh: rhickey: "Elapsed time: 521.42046 msecs"

14:07 250000500000

14:07 Lau_of_DK: user=> (time (reduce + 0 (filter even? (map inc (range 1000000)))))

14:07 "Elapsed time: 590.581693 msecs"

14:07 250000500000

14:08 brianh: on 64bit

14:08 Lau_of_DK: on 32bit Ubuntu 8.10

14:08 rhickey: (System/getProperty "java.version") ?

14:08 brianh: "1.6.0_12"

14:09 Lau_of_DK: user> (System/getProperty "java.version")

14:09 "1.6.0_10"

14:09 rhickey: brianh: you ran it a few times?

14:09 Here's what I'm getting on OS X:

14:09 Clojure

14:09 user=> "Elapsed time: 602.594 msecs"

14:09 250000500000

14:09 user=> "Elapsed time: 89.123 msecs"

14:09 317819756

14:09 brianh: no just once

14:09 rhickey: user=> "Elapsed time: 0.063 msecs"

14:09 0

14:10 Lau_of_DK: I get 703, 210, 0.2765

14:10 Dunno why the first increased compared to before

14:10 rhickey: Lau_of_DK: I don't care about the times, but the results are trach?

14:11 trash?

14:11 Lau_of_DK: 250000500000

14:11 user=> (time (reduce + 0 (filter even? (map inc (range

14:11 1000000)))))

14:11 "Elapsed time: 210.677824 msecs"

14:11 1123959150

14:11 user=> (time (reduce + 0 (filter even? (map inc (range

14:11 1000000)))))

14:11 "Elapsed time: 0.276501 msecs"

14:11 2


14:11 rhickey: right, same problem - thanks!

14:11 Lau_of_DK: np

14:12 rhickey: brianh: you too?

14:12 brianh: one sec

14:15 rsynnott: it's actually giving different results?

14:15 Lau_of_DK: It sure is :)

14:15 rhickey: rsynnott: yeah, it looks like hotspot is choking on closed-over clearing - aargh

14:16 It's a bytecode sequence javac would never generate

14:16 Lau_of_DK: Does that mean its a bug in hotspot?

14:16 rsynnott: but a legal sequence in JVM bytecode?

14:17 rhickey: rsynnott: yes, legal

14:17 JDK 5 has no problem with it

14:18 but JDK 6 has more optimization

14:18 brianh: rhickey: sorry, forgot that i had switched back to the trunk jar

14:18 so disregard earlier

14:19 * Chouser is done downloading the branch and ready to test. :-P

14:19 Chouser: oh, nope. screwed it up.

14:25 brianh: rhickey: switched back to lazy

14:25 after 5 consecutive runs

14:26 seeing: "Elapsed time: 408.459176 msecs"

14:26 250000500000

14:27 rhickey: brianh: interesting, works on 1.6.0_12

14:28 brianh: i have a 1.6.0_06 i can test it on if u want

14:28 32 bit

14:28 hiredman: ouch

14:29 that took a very long time on openjdk7

14:30 "Elapsed time: 1063.158457 msecs" for the first run

14:31 wwmorgan: It looks like () now evaluates to nil when before it evaluated to (). Why was this changed?

14:34 rhickey: wwmorgan: separate problem - I'll look into it

14:34 Lau_of_DK: I think I fixed it, could you please try the latest lazy?

14:34 clojurebot: svn rev 1275; [lazy] declare closed-over fields non-final for once-only fns

14:35 mofmog: when's 1.0 comin?

14:36 rhickey: mofmog: when I get it right :)

14:36 mofmog: heh

14:36 WizardofWestmarc: rhickey: aside from lazy, what's still left that you want in 1.0?

14:36 mofmog: i guess a better question is how much longer until someone can write a tutorial that doesn't require the proviso "Do not use the latest Clojure build"

14:37 ayrnieu: tutorials are fine, the problem is libraries.

14:38 rhickey: mofmog: unless you are doing a tutorial on some bleeding edge feature, that's been possible all along. This latest very disruptive stuff is happening in branches

14:38 mofmog: oh i see

14:38 programming clojure beta has a provision in the introduction like that

14:41 kotarak: I thinks that more, that things may change, not that they are broken. Eg. the defmulti syntax changed. So the examples from the book might not work anymore.

14:41 technomancy: is 1.0 just waiting for the streams and lazy branches, or is there more?

14:41 rhickey: mofmog: the writing of the book covered a transition period where breaking changes were introduce subsequent to a release, so people that grabbed the release and the latest had different worlds. Now it should be less needed, but a good idea on his part to point people to a particular version - that will be true when they have names like 1.0 and 1.1 too

14:41 Lau_of_DK: rhickey: 2 secs

14:42 brianh: rhickey: i'm still not seeing a problem

14:42 user=> (time (reduce + 0 (filter even? (map inc (range 1000000)))))

14:42 "Elapsed time: 948.399866 msecs"

14:42 250000500000

14:42 user=> (System/getProperty "java.version")

14:42 tomsw: to what extent are clojure forms memoised? For example, if I have a loop that does 100 things with the value of (/ width cols), need I put it in a let to avoid multiple evaluation?

14:42 brianh: "1.6.0_06"

14:42 user=>

14:42 after ~5 times

14:42 Lau_of_DK: rhickey: Its fixed here, runs 3 times, same result

14:42 rhickey: Lau_of_DK: great, thanks all!

14:43 hiredman: ugh

14:43 my second run is still running

14:45 maybe my c2d is showing it's age

14:46 or not

14:47 java is using 0.0% of cpu time

14:47 hmmm

14:47 kotarak: hiredman: your clojure is too lazy. ;)

14:47 danlarkin: hiredman: missing a closing paren? :)

14:47 hiredman: it has been running for around 16 minutes

14:47 rhickey: the problem was closed-overs were declared final, but clearing them is a mutation. HotSpot was leveraging the final declaration to reorder things (which it's free to do). So, my bad - HotSpot is fine (whew!)

14:48 hiredman: maybe the machine is clocking itself down

14:48 kotarak: hiredman: is it a laptop? Turn off energy saving.

14:48 hiredman: *shrug*

14:49 technomancy: rhickey: have you found any actual new bugs in hotspot yet?

14:49 hiredman: this is my desktop at home (I am at work right now) so I am not even in front of the machine, but firefox is taking 20% of cpu time

14:49 Lau_of_DK: rhickey: Are you having any thoughts on combining the lazy branch with the master?

14:49 hiredman: *sigh*

14:49 computers

14:51 rhickey: Lau_of_DK: well, I certainly feel better about it now than I did 20 minutes ago :)

14:53 Lau_of_DK: hehe

14:54 Ive heard critics say that it will make code less elegant, with numerous calls to (next!) and such, do you have an oppinion about that rhickey ?

14:54 ericthorsen: should not (with-in-str "(" (read *in* false -1)) return -1

14:55 kotarak: ericthorsen: no, it throws...

14:55 ericthorsen: (with-in-str "" (read *in* false -1)) => -1

14:55 ericthorsen: (with-in-str "" (read *in* true -1)) => throws

14:55 ericthorsen: kotarak: I guess I thought I could tell the reader eof is not an error and return the value i passed?

14:57 kotarak: They are both eof exceptions yes?

14:57 rhickey: Lau_of_DK: I don't think so - have a look at core.clj in lazy and decide for yourself

14:57 kotarak: ericthorsen: oeh, sorry don't know by heart.

14:58 ericthorsen: kotarak: with-in-str "" (read *in* true -1)) throws EOF

14:59 Lau_of_DK: rhickey: ok

14:59 rhickey: Lau_of_DK: where are these critics of which you speak?

15:00 ericthorsen: kotarak: let me double check my version of clojure........

15:00 Lau_of_DK: rhickey: They'll present themselves if they're willing to stand by their words, I was referring a private conversation so I cant really implicate them without their consent :)

15:02 Chouser: I believe Lau_of_DK is referring to things I said about the streams branch (not the lazy branch).

15:02 kotarak: ! sounds like stream...

15:02 Lau_of_DK: Oh thats right - my bad! :)

15:03 rhickey: Chouser: that makes sense - I'm a critic of streams code myself :)

15:04 Lau_of_DK: rhickey: I thought that streams was what allowed you to be fully lazy, so I must have gotten the two mixed up

15:04 Chouser: I'm looking forward to the scope stuff, and I'll be quite content with fully-lazy.

15:04 rhickey: What you are seeing in lazy and streams is the kind of work I used to be able to do in private the couple of years before I released Clojure. Patience is the rule

15:05 Chouser: I'd be willing to go along with streams if our BDFL goes that direction, but I definitely have misgivings.

15:05 Lau_of_DK: (doc BDFL)

15:05 Chouser: ~BDFL

15:05 clojurebot: It's greek to me.

15:06 Lau_of_DK: rhickey: Im very patient, and also very interested- Watching a language take shape like this is most exciting... man I sound like a geek :)

15:06 Chouser: clojurebot: BDFL is Benevolent Dictator For Life (a.k.a. Rich Hickey)

15:06 clojurebot: c'est bon!

15:06 rhickey: It ends up that for best perf with fully-lazy, you need to grab the seq and not rely on first/more calling seq - the double indirection is a big hit

15:06 so, a fair amount of when-lets in core code, more casual code can ignore the difference

15:07 so, map like this:

15:07 ([f coll]

15:07 (lazy-seq

15:07 (when-let [s (seq coll)]

15:07 (cons (f (first s)) (map f (more s))))))

15:08 Lau_of_DK: This may be a really dumb question, but if I always need to work with seq, then doesnt that make the call itself redundant?

15:09 Chouser: ah, call seq once, not multiple times on the same call.

15:09 rhickey: Lau_of_DK: coll is not necessarily a seq, nor is the result of more

15:09 Chouser: right

15:09 Lau_of_DK: Ah ok

15:09 rhickey: Chouser: hotSpot can't optimize through the chained call

15:09 Lau_of_DK: And 'more' instead of 'rest' because first is constantly changing right? I like...

15:10 rhickey: Lau_of_DK: (rest x) == (seq (more x))

15:10 i.e. eager

15:11 Lau_of_DK: sure - but (s (seq [1 2 3])) isnt (= 1 (first s)) and (= 2 (first s)) both true when run in sequence?

15:12 rhickey: Lau_of_DK: you are confusing this with streams, (first s) always returns the same thing, same as ever

15:12 Lau_of_DK: k

15:12 Yes youre right, I am - only cause I like the streams approach

15:12 :)

15:16 rhickey: I encourage everyone to try the lazy branch and give feedback, been little so far

15:17 Lau_of_DK: rhickey: Got something like .org/streams regarding lazy, so I know what Im looking for when trying it out?

15:17 kotarak: rhickey: will there be a lot of changes for existing code?

15:17 rhickey: Lau_of_DK: http://clojure.org/lazier

15:19 kotarak: http://clojure.org/lazier

15:19 let me know if that *doesn't* answer any questions

15:19 Lau_of_DK: rhickey: I like the intro to that article :)

15:20 Just to be clear, when you say something is fundamentally eager, what is meant by that?

15:23 rhickey: Lau_of_DK: in order to satisfy its interface, it needs to see if there is another item

15:24 hiredman: rest never returns an empty seq

15:24 rhickey: hiredman: there's still no such thing as an empty seq in Clojure

15:24 seq or nil

15:24 Lau_of_DK: rhickey: So in that way he's right actually :)

15:25 hiredman: ...

15:27 rhickey: Lau_of_DK: rest never returns a unicorn either

15:27 hiredman: clojurebot: rest?

15:27 clojurebot: certainly brianh

15:27 hiredman: uh

15:27 * hiredman blinks

15:28 hiredman: clojurebot: rest is <reply>rest never returns a unicorn

15:28 clojurebot: Ik begrijp

15:28 Lau_of_DK: haha, a unicorn ? :)

15:28 technomancy: the question is what function *does* return a unicorn... you probably need contrib for that, right?

15:28 Lau_of_DK: rhickey: Going from that article, the lazy stuff looks downright awesome, cant wait to dig in

15:29 jbondeson: technomancy: clojure.contrib.mythical.clj

15:29 hiredman: I imagine you could just use the jre unicorn creation framework

15:29 but I am not sure

15:29 it makes pretty heavy use of annotations

15:30 danlarkin: UnicornFactoryFactory

15:30 Youhou: rhickey: were you intending to do more work on the zipper implementation, or do you consider it pretty much what should be there in core?

15:32 rhickey: Youhou: I'd rather see someone contrib a nice implementation of finger trees

15:32 Youhou: rhickey: finger trees? I glossed over them as I was going through papers. Hmm.

15:33 rhickey: http://www.soi.city.ac.uk/~ross/papers/FingerTree.html

15:33 Youhou: rhickey: I'm trying to use the zipper, but in the current state I find it is very hard to use in real applications (looks nice in tiny demos though)

15:33 rhickey: Youhou: I know Chouser and cgrand have used it profitably in some contrib code

15:34 Youhou: rhickey: ah, interesting -- they actually define folding operations. That was my biggest problem with zippers.

15:34 rhickey: I also found that the zipper is essentially a hidden comonad -- and without supporting infrastructure it quickly gets tedious if you want to do things to it (passing seeds around quickly gets cumbersome)

15:34 hiredman: "However, one could argue

15:34 that this support sometimes leads programmers to use lists when a more general

15:34 sequence type would be more appropriate

15:34 "

15:35 a general sequence type huh?

15:35 Lau_of_DK: rhickey: The implications of the last filter-example in your article, are they that everything is now automatically memoized and that I would hit those Heap explosions as often? :)

15:35 * hiredman found a paper on finger trees

15:36 rhickey: Lau_of_DK: everything has always been memoized with lazy-cons, this just solves the close-over issue

15:37 Lau_of_DK: ok, even better

15:38 hiredman: of course the paper is full of haskell

15:38 *sigh*

15:38 Youhou: rhickey: ok, now I remember. I read this paper, or at least skimmed through it. I didn't find the structure to be of interest. All I need are n-ary trees which I modify and fold (traverse). I don't actually need any of the properties of finger trees.

15:41 gnuvince: Stupid question here: how does one implement things like finger trees in Clojure? In Haskell you'd use data, in an object oriented language you'd use a class. What's the prefered way to do this in Clojure, use the basic data types with a few select functions?

15:42 Lau_of_DK: Hows that a stupid question?

15:42 gnuvince: Lau_of_DK: I figure I'm missing something painfully obvious

15:42 rhickey: Youhou: ok. I'd still like finger trees and treaps: http://www.cs.cmu.edu/afs/cs.cmu.edu/project/scandal/public/papers/treaps-spaa98.pdf

15:42 ayrnieu: gnuvince, http://gist.github.com/55662

15:44 Youhou: rhickey: what I'll try to implement (and contribute) is traversal (foldts, to be exact, as in http://okmij.org/ftp/papers/XML-parsing.ps.gz) for zipper trees.

15:45 Problem is, it needs to be monadic (comonadic) to be exact, to avoid ugliness in passing the seed around. I still don't know how to implement that properly in Clojure.

15:47 rhickey: Youhou: have you looked at: http://code.google.com/p/clojure-contrib/source/browse/trunk/src/clojure/contrib/zip_filter.clj

15:47 ayrnieu: gnuvince - so deftype, there, just updates a central repo of type information to facilitate pattern-matching over types. The constructors are left to the user.

15:48 Youhou: rhickey: I looked at chouser's code in clojure-contrib -- yes, zip_filter, and the XML specialization. But what he does is only useful for static trees. If you want to "modify" the tree during traversal, you can't just map a function over a seq of children, you have to use the zipper functions to move around.

15:49 rhickey: so the zip_filter stuff is a simplification -- useful if your tree doesn't change. Which isn't my case.

15:49 Chouser: Youhou: that's a little detail I hadn't considered until the last week or two.

15:50 All of my early use cases were for extracting data, but of course it's reasonable to want to make adjustments and get back a new tree.

15:50 Youhou: Chouser: I actually completely missed it until recently. And then I noticed that zf/children looks cool, but actually gives me a number of different trees, not children in the same tree.

15:50 Chouser: right

15:51 well, of course they're different trees because they're all immutable

15:51 gnuvince: Jan Rychter

15:51 oops, sorry

15:51 Chouser: but I can see that it'd be useful to for a step in the filter to modify the tree in some way other than traversal, and have that new tree passed to the next step.

15:51 Youhou: Chouser: well, I implemented Kiselyov's foldts for zippers -- and it works fine -- but it isn't pretty and isn't general. I'm afraid generalizing it will require some sort of a monadic approach.

15:52 ayrnieu: gnuvince - you can think of type declarations in Haskell (Mercury, O'Caml, Lisp after you do a little bit of work) as just establishing constructors and destructors. The constructors you use like a normal function, the 'destructors' extend the pattern-matcher. The magic is only in making this efficient, safe.

15:52 Youhou: Chouser: I'm working on a web framework, which is component-based and operates on a tree of widgets (think DOM). I do need to modify that tree.

15:54 Chouser: Youhou: you could use any one result from a zip-filter expression as the basis for a modification, but then you'd have to start the zip-filter process over again on that one new tree.

15:54 gnuvince: ayrnieu: and underneath, it's vectors and whatnot?

15:55 jbondeson: rhickey: i take it you're looking for a persistent treap?

15:55 Chouser: I haven't thought through yet how new trees would be passed through the chain of filter expressions, what options would be useful and such.

15:55 rhickey: jbondeson: yes

15:55 Youhou: Chouser: it hit me when I wanted to recursively descend down my tree -- I wanted to map a function on children. But you need to get the result from one map step and feed it to another, collecting real output on the side as you go. Monadic computation, I'd say.

15:56 ayrnieu: gnuvince - sure.

15:57 gnuvince: ayrnieu: at this point, is it the responsability of the library to ensure that a user doesn't use seq operations to modify the data strucuture in a possibly incoherent manner?

15:58 Chouser: Youhou: you wanted to map on the final nodes returned by the whole filter expression, right, not on intermediate stages of the filter?

16:00 ayrnieu: gnuvince - safety and representation really are separate issues. You can write a library that deals with a type and say "if you only operate on this type with this library's functions, you'll be coding in a state of grace". You can do this in C.

16:00 Youhou: Chouser: what do you call a "filter expression"? I don't actually use the xml stuff, I just have zipper trees with structs in them. And I tried using some functions from zip_filter (children and descendants, from what I recall). As for the trees, I need to walk through them making changes along the way, there is no specific stage when that happens.

16:01 Anyway -- I'll report back with a working foldts once I solve this.

16:02 Chouser: hm.. apparently I need to grok monads more deeply before I pursue this. :-)

16:02 gnuvince: ayrnieu: so the contract with the user is "use my functions and you'll be fine, if you try to fiddle with the internals, you're on your own"?

16:05 ayrnieu: gnuvince - this is always the case :-) You can try to make your type more opaque by only offering keys to the user (think of file descriptors in unix -- they're just numbers, they obviously don't contain the i/o information in themselves), or by storing the data in an unprintable java object. You can try to reveal errors earlier by type-checking. Maybe Clojure can help you out with this, linguistically.

16:14 Youhou: Chouser: that is exactly what I'm trying to do right now. It doesn't help that people mostly write about monads using mathematical concepts (unnecessary) and they all use Haskell notation (which I find confusing and unclear). I have feeling that the underlying concept is simple, it's just presented in a complicated manner.

16:14 Chouser: Youhou: there are a couple monad implementations for Clojure, which might be helpful on the notation front.

16:15 ayrnieu: http://paste.lisp.org/display/43723 is how I delt with state in Hedgehog Lisp, in which (def x y) means that x is y forever and no fooling with 'refs', 'STM', etc.

16:19 basically a (-> state ...) macro, extended with control flow and with an (_ "don't mangle this expression" (println "current state:" state) )

16:25 let_f_: how many gigabites are all the images on the internet?

16:27 durka42: quite a few

16:27 danlarkin: two problems: 1) gigabits or gigabytes? 2) unanswerable

16:28 durka42: or gibibytes

16:49 let_f_: petabytes

16:50 Holcxjo: More like exabytes or even more

16:52 Chousuke: too many :(

16:55 zargon_: Hi! Thought experiment: Writing a game without destructive updates, where we have 100+ "objects" in screen at a frame-rate of 50fps. In pure functional programming each "object" state change would result in a new object instead of modifying the original one. When implementing such a game in clojure what would the effects be? Wouldn't there be a massive amount of object creation and associated garb

16:55 age collection?

16:57 technomancy: zargon_: yes, this will result in huge amounts of garbage creation

16:57 but it doesn't matter

16:57 GC for ephemeral objects is obscenely cheap

16:57 zargon_: "ephemeral"?

16:58 kotarak: What was the amount of the ant simulation on the Azul box?

16:58 technomancy: zargon_: short-lived

16:58 kotarak: I want to say 20 GB/second?

16:58 kotarak: Something like that, yes...

16:58 technomancy: 7% CPU usage over ~600 cores

16:59 zargon_: technomancy: I do a lot server side programming in Java an there are times where GC stops execution for many seconds, that wouldn't be the case for our hypothetical game, you say?

16:59 wwmorgan: zargon_: it seems like something that would be easy enough to test/measure

16:59 technomancy: zargon_: also: these objects will share internal structure, so the new objects only need to create basically a diff with the old one it's based on

17:00 zargon_: there are multiple GC strategies in the JVM. some of them pause, some don't IIRC

17:00 I'm sure you could avoid pauses like that

17:00 zargon_: hmm

17:01 * technomancy finds irony in telling a Java programmer how the JVM works

17:01 zargon_: i'll have to look into the various snake implementations seen on the mailing list ...

17:01 technomancy: considering I've never written any Java. =)

17:03 is the lazy branch built off the streams branch, or are they independent?

17:03 Chouser: independent

17:06 danlarkin: I finally saw an explanation of what it means to be "basically free"

17:06 it averages out to less than one cpu instruction per ephemeral object

17:07 so they round down :)

17:07 technomancy: heh

17:07 hiredman: ...

17:14 lisppaste8: ayrnieu pasted "need A) a macroexpand-all so that the errors in this can be considered, or B) reduce submacros to one tree-walker" at http://paste.lisp.org/display/75306

17:15 c|p: hello all

17:16 ayrnieu: if the errors are in fact in that code and not in clojure.

17:17 "java.lang.IllegalArgumentException: Wrong number of args passed to: user$if--GT-" on (defn-> match [char] (if-> (look= char) (get-char) (thru ...)))

17:40 (OK, it isn't an error in clojure, it's just macro hell. So you should have a 'flat' DSL like in that hedgehog example. But dynamic variables are probably a better way to do this.)

17:47 scottj: I'm reading p211 of b6 of Programming Clojure and it says that you can't write defstruct as a function because def can't be called at runtime.

17:47 (defn defstruct2 [name & keys] (eval `(def ~name (create-struct ~@keys))))

17:47 * technomancy has called def at runtime

17:48 ayrnieu: scottj - it assumed that you would not use eval.

17:48 kotarak: eval is baaaad

17:48 eval is almost always not one wants.

17:48 what one wants

17:49 scottj: so when I need to use eval in a function, that's an indicator I should use a macro?

17:49 hiredman: generally

17:49 kotarak: scottj: Whenever you have to control the evaluation of the arguments, you need a macro.

17:49 ayrnieu: you cannot replace every use of eval with a macro.

17:53 scottj: in this case, are there any big differences between using eval with a function and a quoted symbol, and using a macro with a symbol?

17:53 kotarak: scottj: yes. The eval depends on runtime information. The macro cannot depend on runtime information.

17:54 scottj: (apply defstruct2 (some-user-input-here))

17:56 scottj: ok, thanks all.

17:57 * cooldude127 hates floating point numbers

18:01 c|p: i agree

18:01 ratios are much ccoler

18:01 cooldude127: i get stuck with floats when i start having to square root stuff

18:02 and that is the magic that results in a number that should be 0 becoming 0.43 !!!

18:02 or others

18:04 OMG THIS IS SO STUPID! 0.0 != 7.771561172376096E-16

18:05 but for all intents and purposes, they are the same

18:05 until you try to divide 1 by each of them

18:05 and then i start to cry

18:05 technomancy: yes, floats are inherently flawed

18:05 cooldude127: someone help me fix this. i'm begging you!

18:05 technomancy: some believe the only upside to them is that the word "mantissa" is fun to say.

18:05 cooldude127: lol

18:06 i will sell my left kidney to the first person to offer a good solution to this ;)

18:06 technomancy: cooldude127: "fix"? the fix is not to use floats when accuracy is required.

18:06 cooldude127: technomancy: the problem is i don't have a choice really

18:06 lisppaste8: replaca pasted "eval in macro" at http://paste.lisp.org/display/75310

18:06 cooldude127: unless you have a square root function i can use that keeps things in ratios

18:07 replaca: This eval discussion brings up a question I've had for a while. What happens when I want to use a var at compile time when evaluating a macro? I found myself using eval, but was thinking there was a more idiomatic way.

18:07 as shown in the paste right there

18:10 hiredman: clojurebot: google how to write a square root function

18:10 clojurebot: First, out of 256000 results is:

18:10 The Niklas Lindblad Organisation � Blog Archive � Write Your Own ...

18:10 http://nlindblad.org/2007/04/04/write-your-own-square-root-function/

18:10 Chouser: ,@(resolve 'map)

18:10 clojurebot: #<core$map__3634 clojure.core$map__3634@128d900>

18:11 Chouser: replaca: ^^

18:11 obviously only works for Vars, though, not locals

18:12 cooldude127: that square root function might work actually. looks like what i remember from sicp

18:12 except i can use ratios

18:12 which i think would actually work in scheme

18:13 replaca: Chouser: ahh, so here I'd use "(resolve 'symbol-map)" instead of "(eval symbol-map)"?

18:13 Chouser: oh

18:13 um

18:13 replaca: Chouser: (since I'm doing the quoting further out)

18:13 Chouser: I didn't look at your example very closely

18:13 replaca: Chouser: :-)

18:13 Chouser: why not just ~symbol-map ?

18:14 um

18:14 still not closely enough, sorry.

18:14 replaca: Chouser: because that evals at run time and I'm using the symbol-map at compile time to build the structure

18:14 Chouser: basically I'm building a struture that binds dome variable depending on a table

18:15 *dome -> some

18:17 hiredman: actually

18:18 wikipedia has a page devoted to methods for finding square roots

18:18 Chouser: ok, symbol-map will be a symbol that names a var?

18:18 if so, then you could say @(resolve symbol-map)

18:18 replaca: Chouser: yeah, in practice it will be "write-option-table"

18:19 as defined above

18:19 Chouser: but if somebody passes in a literal map, the eval would work by resolve will blow up

18:19 replaca: Chouser: hmmm, interesting

18:19 so eval may actually be best here?

18:20 it's only a compile time cost

18:20 anyway

18:21 cooldude127: ok clojure's driving me crazy with the fact that it doesn't have it's own math functions

18:22 i'm getting sick of Math/everything-i-need!

18:22 lol

18:22 kotarak: replaca: the eval won't work with locals.

18:22 Chouser: neither will resolve :-)

18:23 replaca: actually, you might be better off looking at the definition of 'binding' and doing something similar

18:23 kotarak: Maybe this is a sign, that is Not a Good Idea?

18:23 Chouser: as kotarak has demonstrated, I believe

18:23 dinnertime. bbl.

18:24 kotarak: Huh? I have demonstrated something?

18:24 replaca: by locals you mean "local to the function that contains the instance of the macro to be expanded"?

18:25 kotarak: 1:5 user=> (defmacro foo [x] `(do ~@(map (fn [y] `(println ~y)) (eval x))))

18:25 #'user/foo

18:25 1:6 user=> (let [x [1 2 3]] (foo x))

18:25 java.lang.UnsupportedOperationException: Can't eval locals (repl-1:6)

18:25 replaca: (in this case, I need to modify it to work like the defn of binding anyway, but I still will need the table I think)

18:25 kotarak: eval has its uses. But they are rare.

18:25 replaca: ahh, that makes sense, cause the local doesn't exist at compile time anyway!

18:26 kotarak: Bingo.

18:26 replaca: so it wouldn't match this case

18:26 kotarak: Why is it so important to have the binding at compile time?

18:26 (Just asking stupid questions, without knowing the background...)

18:27 replaca: in this case cause I'm using the table to build the structure of the resulting macro expansion

18:27 think: table driven code generation

18:27 though there are other ways I could solve this example

18:28 but the problem got me thinking

18:29 (in fact in this case, I could just hard-code it, cause it doesn't really need to be table driven - that's just spurious elegance)

18:32 kotarak: (my-opinion "I almost never need eval. In fact I have eval only at one point in all of my code. And that's a Repl, so one of the few legitimate uses of eval.") Of course: YMMV, but I'm deeply suspicious of code using eval. In my cases, this was always a sign, that I did something wrong or wanted to be too clever....

18:33 replaca: that's why I brought it up :-)

18:34 generally, however, this notion of "table driven code generation" seems interesting and potentially useful

18:36 cooldude127: is there a way to check if something is an integer? do i need to do (instance? Integer)

18:36 ?

18:42 Chouser: ,(integer? 2.5)

18:43 oh, he's gone. anyway, 'integer?', cooldude127

18:43 replaca: Chouser: you eat fast!

18:43 Chouser: replaca: this place is a zoo. leaving again in 2 minutes.

18:44 replaca: :-)

18:44 Chouser: replaca: but since you're trying to build binding, you might just use clojure.lang.Var/pushThreadBindings, just like the 'binding' macro itself does.

18:45 then you could pass in literals, locals, or whatever.

18:45 bbl! :-)

18:45 replaca: yeah, that's my eventual theory

18:45 hiredman: ,(loop [] (recur))

18:45 cooldude127: Chouser: thank you, that's much cleaner

18:45 replaca: cul8r!

18:45 clojurebot: Execution Timed Out

18:46 hiredman: clojurebot: really?

18:46 clojurebot: excusez-moi

18:47 hiredman: because to me it looks like java is still running that loop

18:47 replaca: hiredman: you need to host clojurebot on a faster machine!

18:48 hiredman: .cancel on a future doesn't do what I want

18:48 so clojure's future doesn't seem like it will be used just yet with clojurebot

19:02 cooldude127: yay i have a sqrt that uses ratios!

19:02 fuck you floats!

19:03 sohail: sqrt says: "I can do more sqrts/sec than you"

19:04 technomancy: cooldude127: you're four days late: http://achewood.com/index.php

19:05 lisppaste8: cooldude127 pasted "sucky sqrt" at http://paste.lisp.org/display/75315

19:05 cooldude127: although i'm not gonna lie, this is disappointing

19:06 ^

19:07 Chouser: yeah, I'm not sure that's strictly accurate.

19:07 hiredman: well

19:07 cooldude127: Chouser: it's an approximation. an ugly approximation

19:19 square roots are disgusting

19:19 sohail: cooldude127, how are you approximating

19:19 iterative?

19:19 cooldude127: sohail: whatever newtons method is

19:20 sohail: iterative

19:20 cooldude127: i'm trying to figure out a way that can give me clean integer results for perfect squares, and at the same time use ratios for non perfect squares

19:20 sohail: good luck

19:21 cooldude127: yeah kill me

20:22 clojurebot: svn rev 1276; added multi-arg clojure.set/union/difference/intersection, patch from jawolfe

20:27 p_l: Has anyone tried running clojure applications on Android?

20:32 hiredman: there are reports that it works in the emulator

20:34 p_l: hmmm... nothing specific yet? I guess I'll have to play with it a little - there's some market for Android and I'd prefer to avoid writing in "normal" Java :)

20:35 hiredman: there are some patches on the mailing list to reduce start up time on android

20:37 p_l: hmm.. I'll have to go through it, as soon as I get the SDK working

20:37 Chouser: I believe clojure still requires a small patch to work with android

20:38 but with that patch it has been shown to work on an actual device.

20:40 p_l: thanks for info

20:42 durka42: ~logs

20:42 clojurebot: logs is http://clojure-log.n01se.net/

20:44 hiredman: ,(loop [] (recur))

20:44 clojurebot: Execution Timed Out

23:20 danlarkin: man, I *really* love destructuring bind

23:21 thearthur: how to i call java.lang.system.exit

23:22 danlarkin: thearthur: (System/exit 0)

23:22 thearthur: :)

23:22 thanks

Logging service provided by n01se.net