#clojure log - May 11 2009

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

0:11 unlink1: Does lazy-seq create a recur target?

0:12 cads: yeah, maybe I'll write all my source with an awk header that processes the file when clojure loads it

0:13 but it might be better to do it in the reader :)

0:13 is that stuff documented/

0:18 hiredman: unlink1: I believe so

1:09 eyeris: I need to reference a static field that is defined in a Java interface named Cell. I am unable to import the interface, using the ns macro but if I refer to a field as Cell/field_name, I get an exception due to the Cell namespace not existing.

1:11 cmvkk: i didn't realize you could refer to a static field in an interface anyway.

1:12 eyeris: http://poi.apache.org/apidocs/index.html

1:12 See the fields inherited from org.apache.poi.ss.usermodel.Cell?

1:13 cmvkk: yeah...

1:14 can you reference those fields in java itself?

1:14 eyeris: I don't know. I don't have much java experience :/

1:15 cmvkk: i think you might actually need to reference the fields in a class that implements Cell.

1:15 (this is pure untested speculation on my part, but why would an interface have concrete values? that's not what they're for)

1:16 eyeris: Referring to the field in an implementing class worked.

1:16 Thanks.

1:19 cmvkk: apparently you can have concrete fields in an interface like that. hmm.

1:19 guess it's possible you just can't access them from clojure.

1:19 eyeris: In this case, it makes some sense.

1:20 The interface is used to represent a MS Excel cell, while the implementing classes represent two different file formats.

1:20 But the cell types don't change.

1:20 cmvkk: right.

1:20 eyeris: Like I said, "some" sense :0

1:49 unlink: any bitterness in that api?

3:28 What's the point of clojure.core/when?

3:31 cp2: ,(when (= 1 1) (println "1 is 1"))

3:31 clojurebot: 1 is 1

3:31 cp2: ,(when (= 1 2) (println "1 is 1"))

3:31 clojurebot: nil

3:31 cp2: etc

3:31 unlink: ,(macroexpand-1 '(when :a :b))

3:31 clojurebot: (if :a (do :b))

3:32 unlink: I mean, it doesn't seem to add any value over if

3:32 cp2: well yeah

3:32 its just for convenience

3:32 unlink: But how is it more convenient?

3:32 cp2: cleaner code in some respects

3:32 its really personal preference

3:35 hiredman: if requires an explicit do

3:35 when does not

3:35 hoeck: unlink: I was using when in common lisp code alot, because it wraps the then-expr in a do block, and so saves some nesting and typing when using multiple then-expressions

3:35 unlink: What confuses me is how it's used synonymously with if in clojure/core.clj.

3:35 hiredman: if the else exp returns nil, when is the idomatic choice in clojure

3:36 well, if it is nil

3:37 unlink: When is if idiomatic?

3:37 hiredman: if is idomatic when you have something and something else

3:37 (if foo a b) should be if (if foo a nil) should be when

3:38 unlink: I see

3:38 hiredman: it isn't a huge thing

3:38 unlink: So when do I use if-not and when do I use when-not?

3:38 hiredman: it's in the manual of style :P

3:38 same

3:38 I dunno why you would ever use if-not

3:38 unlink: that's what I mean

3:39 actually

3:39 In Python, I sometimes do (if-not (nil? a) (do something-with a) (something else))

3:39 (well, in Python syntax)

3:40 hiredman: I am teh first to admit the manual of style does not address all issues

3:41 but it does address when

3:41 unlink: Oh, you were being serious about a manual of style?

3:41 hiredman: no, just rhickey called using when idiomatic

3:42 The All Inclusive Clojurebot Compendium of Coding Style

3:42 unlink: gotcha

3:42 Cark: the AICCS, a must read...

3:43 good morning =)

3:43 hiredman: the awks

3:43 AWizzArd: Hey Cark

3:43 hiredman: akes?

3:43 unlink: Is 1 function : 1 class intended to forever be The Way Clojure Works (TM)?

3:44 hiredman: I dunno, but it does not seem like something that is a good idea to depend on

3:45 Cark: well my guess is that it will stay that way, so functions can implement interfaces

3:45 and for closures state too

3:45 hiredman: hmmm

3:46 Cark: mhhh actually i'm not sure about the latter, how are closures closed over in clojure ?

3:46 hiredman: no idea

3:46 AWizzArd: Cark: what are the alternatives?

3:46 unlink: ,+

3:47 ,(do +)

3:47 hiredman: :(

3:47 Cark: i don't know, i know they are objects in c#

3:47 unlink: :-(

3:47 hiredman: ~ping

3:47 Cark: then you have the stack for real lisps

3:47 thez stack frame i mean

3:47 unlink: ,(lazy-seq (recur))

3:47 hiredman: clojurebot must be lagged or something

3:47 unlink: needs to be woken up

3:48 anyway, this is slightly disturbing: user=> (new clojure.core$_PLUS___3332)

3:48 #<core$_PLUS___3332 clojure.core$_PLUS___3332@2d1e233>

3:49 clojurebot: Test

3:49 hiredman: huh

3:49 unlink: ,(println "I'm awake")

3:49 hiredman: maybe I broke something

3:49 unlink: is it hosted on google code?

3:49 hiredman: ,a

3:49 unlink: s/code/appengine/

3:49 hiredman: no

3:50 it's weird, no exceptions or anything in the repl

3:50 unlink: in clojurebot's?

3:50 hiredman: yeah

3:50 clojurebot: hello?

3:50 clojurebot: #<core$_PLUS___3330 clojure.core$_PLUS___3330@1b51af1>

3:50 #<core$_PLUS___3330 clojure.core$_PLUS___3330@1b51af1>

3:50 hiredman: uh oh

3:50 clojurebot: PONG!

3:51 Execution Timed Out

3:51 unlink: hahahaha

3:51 clojurebot: I'm awake

3:51 java.lang.Exception: Unable to resolve symbol: a in this context

3:51 BUENOS DING DONG DIDDLY DIOS, fRaUline hiredman

3:51 hiredman: ok

3:51 ~ping

3:51 clojurebot: PONG!

3:51 AWizzArd: ~ max people

3:51 clojurebot: max people is 164

3:51 hiredman: something lodged in his pipe maybe

3:51 unlink: ,(reduce (new clojure.core$_PLUS___3330) (range 10))

3:51 clojurebot: 45

3:53 unlink: Anyway, that makes me cringe.

3:54 hiredman: so don't do it

3:55 unlink: I don't think whether I do it changes whether the underlying issue bothers me or not.

3:56 hiredman: what issue?

3:56 that functions are classes?

3:57 unlink: right

3:57 hiredman: why is that an issue?

3:58 unlink: I mean, I can't think of a more efficient way of implementing them on the JVM.

3:58 hiredman: well, generally they are only instanciated once

3:59 except maybe anonymous functions

3:59 but even with those, object allocation is cheaper on the jvm then with c++

3:59 unlink: Function invocation = instantiation?

3:59 hiredman: nah

4:00 opqdonut: Function invocation = .invoke(args..)

4:00 hiredman: function invocation is a method call

4:00 hoeck: I think the clojure function implementation maps perfectly on the closures == objects analogy

4:00 hiredman: or .run or .call(Object)

4:00 unlink: ok

4:01 hiredman: ,+

4:01 clojurebot: #<core$_PLUS___3330 clojure.core$_PLUS___3330@1b51af1>

4:01 hiredman: that is an instance

4:01 .(.invoke + 1 2)

4:01 unlink: It has obvious advantages with Java interop, but means degraded performance compared to, for example, OCaml's implementation.

4:01 hiredman: ,(.invoke + 1 2)

4:01 clojurebot: 3

4:02 jdz: unlink: why?

4:02 hiredman: Callable is tailor made for function objects

4:02 unlink: At a minimum, all bindings which are closed on must be on the heap.

4:04 jdz: unlink: so how do you pass closures to different threads in OCaml?

4:05 if the bindings are not on the heap

4:05 unlink: OCaml cheats.

4:05 It knows when it can get away with putting them on the stack.

4:06 hiredman: ~literal [1] clojure

4:06 clojurebot: cheating

4:06 jdz: you know, JIT does some crazy things, too

4:06 you never know what it comes up with sometimes

4:06 __mac: Doesn't the 1.6 hotspot do escape analysis to put local stuff on the stack

4:06 ?

4:07 opqdonut: additionally, jvm really isn't a general purpose virtual machine

4:07 you can't mess with the stack for one

4:07 AWizzArd: jdz: is that good or bad? :)

4:07 jdz: AWizzArd: both.

4:07 AWizzArd: (to not know what it will come up with)

4:07 ic

4:07 jdz: i mean, i'm old enough to not care about that stuff

4:07 but i can understand some people being nervous

4:07 AWizzArd: :p

4:08 jdz: when they don't have full control/knowledge of the underlying stuff

4:08 __mac: I'm hoping I will stop caring about that stuff one day. I have developed an unhealthy fascination with llvm...

4:08 jdz: now i feel really releaved that i can rely on amazing things others have created, like JVM and Clojure

4:09 and CL implementations :)

4:09 unlink: I never got past the (which CL implementation should I use) phase.

4:10 __mac: sbcl ;)

4:10 AWizzArd: or Allegro Enterprise

4:10 unlink: Actually, that's sort of a lie.

4:10 I got past that phase after losing interest in CL.

4:10 __mac: So the correct answer is "none, use clojure"?

4:11 AWizzArd: unlink: so after you lost interest in CL you found knew which CL you should use? ;)

4:11 unlink: Yeah...not currently using any other lisps.

4:11 AWizzArd: -found

4:12 unlink: AWizzArd: Yes, but if I evaluated that by trying to use CL I would get an NPE.

4:12 AWizzArd: unlink: when you interact with our world your are indirectly using other Lisps. The universe was coded in Lisp: http://www.gnu.org/fun/jokes/eternal-flame.ogg

4:14 jdz: c'mon, it's common knowledge that our world was cobbled together with perl in the very late night of 7th day

4:15 and nobody can fix it because it's a big pile of mess

4:16 unlink: But I heard all these jokes so many years ago :(

4:17 jdz: which jokes?

4:17 hiredman: oh wow

4:17 that ogg crashes mplayer

4:17 Great

4:18 unlink: must be too old

4:18 hiredman: hah

4:19 I found a post on the mplayer list complaing about the same ogg

4:20 __mac: You all probably saw this already, but it's still good stuff:

4:20 http://xkcd.com/224/

4:26 unlink: I find it amusing that lazy-seq creates a recur target, since a recur pointing to one can only ever cause it to diverge.

4:27 opqdonut: err?

4:27 a lazy-seq needn't be infinite

4:28 unlink: How is a recur pointing to lazy-seq ever useful?

4:28 hiredman: lazy-seq wraps in a fn

4:28 I think

4:29 which is where the recur target comes from

4:29 unlink: oh you're right

4:29 (list 'new 'clojure.lang.LazySeq (list* '#^{:once true} fn* [] body)))

4:32 Wow, LazySeq is so magical.

4:32 ,(class (rest (lazy-seq [1 2 3])))

4:32 clojurebot: clojure.lang.APersistentVector$Seq

4:32 hiredman: yep

4:32 ~literal [1] clojure

4:32 clojurebot: cheating

4:32 unlink: ?

4:33 hiredman: it's a joke

4:33 clojure's (and other lisps) simplicity often feels like cheating

4:33 ~clojure

4:33 clojurebot: clojure is the brand

4:33 unlink: oh

4:33 hiredman: ~clojure

4:33 clojurebot: clojure is like life: you make trade-offs

4:33 hiredman: ~clojure

4:33 clojurebot: clojure is far closer to perfection then python

4:33 hiredman: hmmm

4:34 unlink: I'm surprised that rest of a LazySeq isn't some other opaque object like another LazySeq

4:34 hiredman: somewhere in there it will say "clojure is cheating"

4:34 it can be

4:35 if the lazy-seq yields (cons 'foo (lazy-seq 'something))

4:35 unlink: well, right

4:41 why does lazy-seq need to be implementedin Java?

4:43 hiredman: ~def clojure.lang.LazySeq

4:44 unlink: I mean, I've read that

4:44 talios: is there a "clojure" way of getting resources off the class path? Using (.getResourceAsStream (.getClass some.class) "/foo") seems to work (has issues with compiled clojure thou), but I get the feeling there should be something more clojure based?

4:44 hiredman: maybe a performance thing?

4:46 talios: I have been using that with aot compiled clojure with no issues

4:49 talios: I was trying it using clojure.lang.RT as the class, which worked but wouldnt find my resources, and it doesn't seem to find my own classes that the clojure compiler is generating, unless I work out some kinda two-pass thing

4:50 actually - using clojure.lang.RT worked when running locally, but not when deployed to my web container, I suspect class loader poopage

4:51 hiredman: (.getResourceAsStream (clojure.lang.RT/baseLoader) "version") is actually what I am using

4:51 talios: Ill try that using the loader

4:53 hiredman: if you are using your own gen-class you need to not do the getresource durring the compile, only durring runtime

4:53 (when-not *compile-files* ...

4:54 talios: mmm - didn't know that (when-not trick! that could be handy

5:04 gah - it -was- working, not I just get nulls. hrm.

5:05 unlink: ~def clojure.core.ns

5:05 aw

6:07 cads: hey, I was wondering if anyone here knows about clojure.set, and the relational set operations defined there

6:11 we have union and intersection and difference, and select, which operate on sets, but there is also rename, join, and project which seem to work with sets of maps

6:14 can we better represent set theoretic constructions and operations in terms of operations on rel-sets?

6:54 unlink: Does such a macro as http://dpaste.com/42928/ exist in the standard library, or is it just a good idea?

7:15 AWizzArd: Hello rhickey. I wanted to ask you how easy it would be to get a hook into the compile function. Interesting for me would be to reach some level of basic code obfuscation: removing docstrings, renaming functions and the resulting .class files.

7:15 Is that easily possible or would that require a loot of work?

7:16 (existing code obfuscators may not be able to do that)

7:17 rhickey: AWizzArd: things like that are definitely not a priority. I guess you could get come mileage from Java obfuscators? The only thing I think will come any tome soon would be dropping docs strings, useful for memory-limited targets

7:17 time

7:32 AWizzArd: Removing the docstrings would already be a good thing.

7:32 rhickey: is it possible to run compile not on files on disk, but instead on what exists in the image?

7:33 rhickey: AWizzArd: there isn

7:33 t really an image,

7:33 AWizzArd: I can write a function which makes up gensym'ed aliaes of all function names in a namespace and then ns-unmaps the original names

7:33 rhickey: everything is already compiled once running

7:34 AWizzArd: and can one write those compiled objects to disk?

7:35 rhickey: AWizzArd: this (obfuscation) isn't something I want to spend time on

7:36 AWizzArd: i mean i could write such a function, and it may work if one could write the compiled objects to disk

7:37 for example if there is a function foo then i could do a (intern *ns* (gensym) (get (ns-interns *ns*) 'foo)) and then (ns-unmap *ns* 'foo)

7:37 eevar2: obfuscation is a daft idea anyway

7:37 *concept

7:37 AWizzArd: agreed

7:37 rhickey: AWizzArd: doesn't compile write compiled files to disk?

7:39 AWizzArd: rhickey: it does, but it loads my .clj files on disk. What I have in mind would be a process like: I load my files from disk, now everything is compiled. Then I replace the names of all functions (in ram) and write those to disk. If that can be done somehow.

7:40 rhickey: AWizzArd: why does it load .clj files from disk?

7:40 AWizzArd: Currently I can replace my function names in ram. But on disk in my .clj files all names stay the same. So a call to compile would take a secret.clj and produce a secret__init.class or something like that.

7:41 rhickey: I start a fresh clojure and do: (ns foo) (defn bar [] 100)

7:41 Then: (binding [*compile-path* "/my/build/dir/"] (compile 'foo))

7:41 ==> java.io.FileNotFoundException: Could not locate foo__init.class or foo.clj on classpath

7:45 I imagine to have a file foo.clj with the contents: (ns foo) (defn bar [] 100) Now in my build process I would (load "foo"). Then (intern *ns* (gensym) (get (ns-interns *ns*) 'bar)) and then (ns-unmap *ns* 'bar). Now I can call bar and it returns 100.

7:45 If I could now store that manipulated namespace to disk it may do what I want.

7:55 ittayd: Hi, I have a question about multimethods

7:57 AWizzArd: Yes?

7:58 ittayd: The documentation has an example for defining an area multimethod

7:59 the dispatching value is :Shape

7:59 and then to define area for rectangles:

7:59 (defmethod area :Circle [c]

7:59 is used

7:59 does this mean that :Shaped is applied on c and then isa? is used to match :Circle?

8:01 AWizzArd: what first happens when you call area is that the dispatch function (defmulti area :Shape)

8:01 gets called

8:01 :Shape can be a function in Clojure

8:01 one could have said instead: (defmulti area (fn [object] (get object :Shape)))

8:02 When you have (def H {:a 1, :b 2, :c 3}) then (get H :a) ==> 1

8:02 But (:a H) is also ==> 1

8:03 ok so far?

8:04 In the example on the Clojure website r is {:Shape :Rect :wd 4 :ht 13}

8:05 (area r) === (area {:Shape :Rect :wd 4 :ht 13})

8:05 ittayd: yes

8:05 AWizzArd: and (:Shape {:Shape :Rect :wd 4 :ht 13}) ==> :Rect

8:05 so, (area r) will first call :Shape

8:05 And that returns a value. In this case it returns :Rect

8:06 Now after that happened Clojure will look up all defmethod's.

8:06 One of those is: (defmethod area :Rect [r] (* (:wd r) (:ht r)))

8:07 That is the one that gets executed

8:07 [r] is the parameter - that gets bound to the orginial input of the call to area. That was {:Shape :Rect :wd 4 :ht 13}.

8:07 ittayd: thanks for the explanation

8:07 AWizzArd: np, hope it shed some light into multimethods

8:08 ittayd: sure did. it would be useful if this explanation of the flow appeared in the docs.

8:10 AWizzArd: ittayd: for another example look at http://paste.lisp.org/display/68846

8:12 ittayd: nice and confusing

9:07 AWizzArd: rhickey: did you get my email (it may have landed in a filter)?

9:35 chessguy_work: 'morning

9:37 AWizzArd: Hi chess

9:37 chessguy_work: so i think i'm going to take on a chess project in clojure

9:37 a truly symbolic chess engine

9:38 should be fun

9:52 wow don't everyone get all excited at once :)

9:56 AWizzArd: ah, but that sounds good, yes

9:57 Will it be an open source project?

9:57 * rhickey waiting for a Clojure Go engine...

9:57 kotarak: :D

9:58 hiredman: obviously all the money is in closed source chess engines...

9:58 AWizzArd: hiredman: maybe chessguy_work should also make a closed source one. It is possible that he can come up with the strongest chess engine ever.

9:59 I was very surprised about Rybka. Some companies were working for 20 years, with international chess experts, but the Rybka programmer came up with a new idea and within 6 months he got the strongest program. Duh!

10:01 chessguy_work: heh

10:02 rhickey, one step at a time

10:02 as for whther or not it will be open source....we'll see

10:03 gnuvince: chessguy_work: do you have a blog?

10:03 chessguy_work: not one i keep updated

10:03 gnuvince: ok

10:03 It would've been interesting to follow your progress

10:03 chessguy_work: just hang around here :)

10:04 and/or the mailing list

10:04 gnuvince: Let me know if you find optimization techniques ;)

10:04 chessguy_work: what sort of optimization techniques are you interested in?

10:05 gnuvince: chessguy_work: pretty much anything that can bring a Clojure program within 1.5-2x the speed of an equivalent Java program.

10:05 See this: http://gnuvince.wordpress.com/2009/05/11/clojure-performance-tips/

10:05 chessguy_work: oh

10:05 i'm more interested in algorithmic techniques

10:05 gnuvince: chessguy_work: in the case of my project, I don't know what algorithmic techniques I could use to improve the efficiency of the program

10:06 chessguy_work: what project would that be?

10:06 gnuvince: It reads data from a ByteBuffer and transforms it into Clojure data structures.

10:06 liebke: gnuvince: nice tips

10:06 chessguy_work: oh sorry

10:06 gnuvince: chessguy_work: clj-stracraft. There's a quick background in the post.

10:06 chessguy_work: i guess i should have read your link

10:07 AWizzArd: gnuvince: do you constantly update that site?

10:07 gnuvince: AWizzArd: I try to. Maybe 3-4 posts per month

10:08 AWizzArd: Maybe you could set up a static link that will always stay valid and has an overview about everything you found out?

10:08 gnuvince: AWizzArd: if I have enough material, I could probably do that, Wordpress allows "static" pages.

10:09 chessguy_work: gnuvince looks like a great blog

10:09 don't see an RSS link though

10:11 gnuvince: chessguy_work: if you use Firefox, you should see an orange RSS icon in your address bar

10:11 Otherwise: http://gnuvince.wordpress.com/feed/

10:12 chessguy_work: ah, nice. added

10:12 i was using chrome :)

10:12 gnuvince: OK

10:13 If you have comments (positive or negatives), corrections, suggestions, don't hesitate to post them.

11:30 dnolen: curious, why would in some case using aset-int slow down a tight loop over using aset?

11:31 durka42: is it an array of primitives?

11:31 dnolen: yes

11:32 Chouser: are you sure? :-)

11:32 dnolen: pretty sure

11:33 durka42: or are you giving aset-int Integers

11:33 Chouser: also, are you setting the value to an Integer or a primitive int?

11:33 dnolen: on comp.lang.lisp some time ago, there was a performance metric on the speed of array-primes in Clojure vs. SBCL.

11:33 here let me paste and you all can see.

11:36 lisppaste8: dnolen pasted "array-primes" at http://paste.lisp.org/display/80027

11:37 dnolen: this has been tweaked a little, (hopefully I didn't mess it up) from what I saw on the mailing list.

11:38 is it possible to get for loop performance over java primitive arrays in Clojure, or is something best done in Java?

11:38 that's really what I think the question is here.

11:38 Chouser: you should be able to get there.

11:38 dnolen: Chouser: that's what I thought

11:38 but I've tried a lot of things and haven't been able to figure it out.

11:38 Chouser: and loop/recur with primitives is the way to get there.

11:39 dnolen: yes

11:39 that what's being used here

11:39 Chouser: ok, outer-index is a non-primitive

11:39 which means inner-index is non-primitive

11:40 which means the * operations will have to box/unbox (I think), etc.

11:40 perhaps try (loop [outer-index (int 2)] ...) instead of the #^Integer hint?

11:40 dnolen: it said I can't type hint a local

11:41 with primitive initializer

11:42 Chouser: ,(loop [i (int 2)] (if (< i 10) (recur (unchecked-inc i)) i))

11:42 clojurebot: 10

11:42 lisppaste8: dnolen pasted "aset vs. aset-in" at http://paste.lisp.org/display/80028

11:43 dnolen: here's the example of aset-int being slower than aset

11:43 aset-int takes about 1.2s while aset takes ~120ms

11:44 stuhood: ~def aset-int

11:45 stuartsierra1: For these situations, it might be useful to have a "disassemble" function that shows the generated bytecode.

11:46 dnolen: stuartsierra: true.

11:47 ,(loop [#^Integer i (int 2)] (if (< i 10) (recur (unchecked-inc i)) i))

11:47 clojurebot: java.lang.UnsupportedOperationException: Can't type hint a local with a primitive initializer

11:47 lisppaste8: rhickey annotated #80027 "faster array-primes" at http://paste.lisp.org/display/80027#1

11:49 hiredman: so unchecked-inc -> inc

11:50 rhickey: less is more, avoid unchecked if you can

11:50 durka42: (neg? (unchecked-subtract (int aidx) (int limit))) seems to be much baster than (< (int aidx) (int limit))

11:50 rhickey: coercing at point of use is always a mistake, coerce at point of binding

11:51 i.e. let/loop

11:51 Chouser: is that why aset-inc in his second example is slower than aset?

11:53 rhickey: a trick, if you fn takes something you want to be considered primitive, re-let it: (defn integers [limit] (let [limit (int limit) ...

11:53 Chouser: I guess with a hinted array, aset is resolving a direct method-call anyway. Perhaps there's simply nothing faster than that.

11:53 rhickey: Chouser: yes, hinted array + aset is fastest, aset-int is not a fast thing at all

11:53 stuhood: Chouser: beat me to it... the array is already type hinted

11:54 stuartsierra: Does aset compile to a method call or to a bytecode array operation?

11:54 stuhood: method call: Array.setBlah

11:55 rhickey: stuartsierra: with all hints in place, the static method it resolves to is optimized by HotSpot into single array instructions, but I never have to emit them

11:55 stuartsierra: ok, cool

11:56 rhickey: stuhood: no, aset can do much better than Array.setBlah

11:56 stuhood: rhickey: after hotspot has compiled it? the implementation of aset just looks like it calls Arrays.set

11:57 rhickey: stuartsierra: that's one reason why disassembly won't show full story, but you can see what hotspot does using some flags I think

11:57 stuartsierra: ok. I was about to ask if there was a way to see what Hotspot is doing.

11:57 Chouser: so aset-<type> is for convience to avoid reflection, not performance when you're willing to type hint for primitives.

11:57 dnolen: wow

11:57 this is great

11:57 cgrand1: stuhood: look at the :inline meta

11:58 dnolen: so array-prime minus all the aset-int cruft when from taking forever to taking 900ms

11:58 rhickey: stuhood: aset has an inline definition

11:58 dnolen: so filter is eager correct?

11:58 not lazy.

11:58 rhickey: to RT.aset, which is overloaded for specific arrays

11:58 kotarak: dnolen: filter is lazy

11:58 stuhood: ahhh

11:59 dnolen: OK so maybe not 900ms :)

12:03 rhickey: I wrote about optimization tips here: http://groups.google.com/group/clojure/browse_frm/thread/61f236e830d98cb3/9cc8e1572b793c7e?lnk=gst&q=optimization#9cc8e1572b793c7e

12:03 no one replied

12:03 Chouser: heh

12:05 stuartsierra: those might be good tips to add to clojure.org

12:05 dnolen: yes

12:06 stuhood: cgrand1: regarding the inline definitions: when does it have to fall back to the clojure implementation?

12:06 dnolen: Also perhaps a clarification about what aset-* does? its seems easy to get confused.

12:09 * Chouser writes instance_member_foo+=1; in a .cpp file, and cringes.

12:10 chessguy_work: a witch!!!

12:11 cgrand: stuhood: when the arity is not supported by the inline definition (here for aset, only calls to aset with 3 arguments get inlined).

12:12 hiredman: clojurebot: optimizing?

12:12 clojurebot: excusez-moi

12:12 hiredman: clojurebot: optimizing is http://groups.google.com/group/clojure/browse_frm/thread/61f236e830d98cb3/9cc8e1572b793c7e?lnk=gst&q=optimization&pli=1

12:12 clojurebot: Ik begrijp

12:13 chessguy_work: clojurebot, ptimizing?

12:13 clojurebot: optimizing?

12:13 clojurebot: optimizing is http://groups.google.com/group/clojure/browse_frm/thread/61f236e830d98cb3/9cc8e1572b793c7e?lnk=gst&q=optimization&pli=1

12:14 rhickey: http://clojure.org/java_interop#optimization

12:14 Chouser: stuhood: also when getting the function as a value, like if you're passing it to 'map'

12:15 hiredman: clojurebot: forget optimizing

12:15 clojurebot: I forgot optimizing

12:15 hiredman: clojurebot: optimizing is http://clojure.org/java_interop#optimization

12:15 clojurebot: Roger.

12:17 stuhood: Chouser,cgrand: gotcha, thanks.

12:30 cads: hey, does clojure have a way to exhaustively search an infinite sequence?

12:31 hiredman: how would you do that?

12:31 if it is an ordered infinite sequence I imagine you chould do something with take-while

12:32 but otherwise you would just search forever

12:43 danlarkin: replaca: ping

12:48 replaca: danlarkin: pong

12:48 danlarkin: I got your github message, tried to run your clojure-json branch but I get an error on line 60 of json.clj

12:49 Unable to resolve symbol: write in this context

12:50 replaca: danlarkin: oops, a use but - I think I have uncommited code. One sec

12:50 *but => bug

12:52 danlarkin: sorry. Try now

12:54 danlarkin: I have too many git & svn projs going at once! All with alternate repositories and such. Gets confusing :-(.

12:54 danlarkin: replaca: agreed

12:55 replaca: have you run the tests? I get a stackoverflow error when it tries the big "pass1" test

12:56 replaca: danlarkin: no, I just ran it over the contrib API Index. That's just meant as a quick "concept" idea rather than finished code anyway

13:02 danlarkin: replaca: currently it's an awful lot slower than the master branch

13:02 500ms versus 10ms

13:02 microbenchmark, admittedly

13:03 but the proof of concept is sound

13:03 replaca: danlarkin: yeah, pretty printing has to work harder cause it's all conditional

13:04 danlarkin: but there's also lots of work that can be done to speed it up (I've just begun on that).

13:04 danlarkin: what about only running it through the pretty printer if the :indent option is passed

13:04 replaca: (by conditional I mean it will keep things on the same line when it can)

13:04 danlarkin: or some equivalent flag

13:05 replaca: as I've thought about it more, I think it makes sense to have a separate pretty printing encoder in contrib

13:06 so you'd have json.{read,write,pretty} or something like that

13:06 danlarkin: something like (contrib.prettify (contrib.json.write foo))?

13:06 replaca: cause it's a big switch

13:07 danlarkin: no, that doesn't work cause pretty printing works on s-exps, not strings

13:07 so it can't happen on the output

13:07 danlarkin: :-/

13:08 replaca: rather, it's thinking about the data structure as it's constructing the output to decide where

13:08 line breaks and indents go

13:08 danlarkin: so you're trying to pass the indenting that the pretty printer gives you on through the encoder function?

13:08 replaca: no, the pretty printer *is* the encoder function

13:09 danlarkin: is it not possible to make the pretty printer deal with strings? or is that just too much of a different job

13:09 replaca: basically it's a recursive dispatch mechanism

13:09 danlarkin: oh, right

13:09 replaca: completely different job & then you need a parser

13:10 the pretty printer (like lots of lisp stuff) operates on structure

13:10 but dispatch means you can get any kind of structure out

13:10 danlarkin: mmmhmm

13:11 replaca: The big advantage is that it's easy for it to be very smart about when and where to put line breaks

13:11 tbb: hi all, i have a problem i hope someone can help me with. i'm writing some sort of algorithmic animation tool. i define some algorithms that change the visuals over time. i'd also like to add some algorithms together in another algorithm. whenever these algorithms are called, i want it to show in the logs, but.. i want to know whether the lowlevel algorithm calls belong to the highlevel call or whether they are separate calls. i defined the followin

13:11 (def *action-id* nil)

13:11 (defn action-id []

13:11 (if (nil? *action-id*)

13:11 (gensym "action-")

13:11 *action-id*))

13:11 (defn action-id-test []

13:11 replaca: so it doesn't put a whole bunch of unnecessary line breaks in

13:11 tbb: (println (action-id))

13:11 (loop [counter 0]

13:11 (binding [*action-id* (action-id)]

13:11 (println (action-id))

13:11 (println counter)

13:11 (if (> counter 5)

13:11 nil

13:12 (recur (inc counter))))))

13:12 oops

13:12 danlarkin: tbb: please do not spam the channel with code, that's incredibly rude

13:12 tbb: my problem is: the binding gets cached somehow

13:12 i'm sorry

13:12 danlarkin: replaca: brb

13:12 replaca: tbb: you can use lisppaste

13:12 tbb: i thought it would show up nicer

13:12 replaca: danlarkin: gotta run to the office

13:12 lisppaste8: url?

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

13:12 danlarkin: replaca: we'll talk later, then

13:13 replaca: ok, sounds good. I'll fix that bug somewhere along the way

13:13 tbb: past number 80033, the problem is the binding gets cached

13:14 the weird thing is that it is cached in the repl, but not c-x c-e in the file

13:14 lisppaste8: tbb pasted "cached-binding" at http://paste.lisp.org/display/80034

13:15 tbb: sorry for the spamming, i like this lisppaste :)

13:16 replaca: tbb: what do you mean by "cached?"

13:17 tbb: replaca: when i evaluate *action-id* in the repl it has the value of the gensym, which should be rebound to nil (right?)

13:20 without the recursion it works properly

13:22 lisppaste8: hiredman annotated #80034 "output at repl" at http://paste.lisp.org/display/80034#1

13:23 hiredman: I dunno why you would put the binding in the loop like that anyway

13:23 lisppaste8: tbb pasted "first-run-second-run" at http://paste.lisp.org/display/80036

13:23 hiredman: I would definetly put it outside the loop

13:25 tbb: hiredman: this is just a test to see if the bindings worked, i'll be using this in different algorithms, compounded algorithms should all log with the same id

13:25 i'll make an example

13:25 replaca: hiredman: well, if he wants a different binding for each recursion step (I assume this is a simplified example)

13:25 *fdr => for

13:25 hiredman: tbb: the problem is the extra println at the top of the function

13:25 it is making you think something is happen, which isn't

13:26 binding definetly works

13:26 but keep in mind binding is not assignment

13:26 tbb: hiredman: what do you get if you evaluate *action-id* in the repl now?

13:26 replaca: tbb: but afterwards, what does the repl think the value of *action-id* is?

13:27 hiredman: tbb think the binding is "sticky" all the way back to the repl

13:27 tbb: right?

13:27 tbb: replaca: it thinks it's "action-id-###", it doesn't return to nil

13:27 yes

13:27 this is the output of two consequent runs: lisppaste8: tbb pasted "first-run-second-run" at http://paste.lisp.org/display/80036

13:27 replaca: tbb: that seems wrong to me, too

13:28 hiredman: tbb: you should lookup gensym

13:28 ~def gensym

13:28 replaca: hiredman: I don't think tbb is talking about the gensym

13:29 hiredman: the fact that it has two differnt vals is OK

13:29 tbb: i'll make a clearer example

13:29 replaca: tbb: when you use lisppaste, just keep annotating the same paste rather than creating new ones

13:29 tbb: ok

13:30 lisppaste8: tbb annotated #80036 "clear-example" at http://paste.lisp.org/display/80036#1

13:30 replaca: means I can type ^r inmy browser :-)

13:30 tbb: haha

13:31 somehow, the recursion makes it sticky

13:32 replaca: tbb: I agree that *action-id* should be nil after that, but maybe there's something I don't understand about binding here

13:32 tbb: Maybe a group post would shed more light on this

13:32 tbb: replaca: i'm coding an example of how i intend to use it

13:33 i'll do that

13:33 replaca: tbb: I've got to run, but I'm also interested in the answer here cause I would think that the result you're getting is impossible. But clearly, we're both wrong :-)

13:34 tbb: haha, ok, i'll post it to the group

13:34 thanks for your time :)

13:34 replaca: tb: no prob

13:35 hiredman: hmmm

13:36 it looks like the bindings are not being removed

13:36 tbb: what i've found out is they are removed if there aren't any recursive bindings, and it only happens in the repl

13:36 lisppaste8: hiredman annotated #80034 "set!" at http://paste.lisp.org/display/80034#2

13:37 tbb: hiredman: yes, that's what i get too

13:39 lisppaste8: hiredman annotated #80034 "close the binding before recur" at http://paste.lisp.org/display/80034#3

13:40 hiredman: that gives what I assume is the expected behaviour

13:43 tbb: hiredman: the intended behavior is that *action-id* is bound to a gensym and stays bound to it all the way down the function calls, it should only be bound at the toplevel

13:43 so the every time i call action-id-test the gensym should be the same for all the print outs, but the next time i call it they should be different than before

13:44 hiredman: ah

13:44 hmm

13:47 lisppaste8: hiredman annotated #80034 "binding outside the loop" at http://paste.lisp.org/display/80034#4

13:48 tbb: hiredman: it seems like loop is the culprit indeed

13:48 hiredman: yeah

13:48 tbb: although in this way i can't test the recursiveness i'm after

13:49 i made a new example that shows the intended use

13:49 cp2: hello folks

13:50 lisppaste8: tbb annotated #80034 "intended" at http://paste.lisp.org/display/80034#5

13:50 tbb: hi cp2

13:51 hiredman: that one works just fine

13:51 hiredman: tbb: I don't see anything that precludes the use of binding outside the loop

13:52 it is troubling none the less

13:52 tbb: hiredman: i used it inside the loop to simulate functions calls that all rebind *action-id*, like in the new annotation

13:52 hiredman: you are sending something to the group?

13:53 tbb: it seems to work for what i wanted to use it for, but i'd like to know why we get this behavior so i'll post something

13:54 hiredman: ugh

13:54 writing guis is such a drag (everywhere) I wish someone would do something about that

13:55 slashus2: Make a DSL for GUI programming?

13:55 technomancy: stop using GUIs? =)

13:55 dnolen___: hiredman: I'd say Cocoa + Interface Builder is damn good. sad so few GUI programming systems have learned from it.

13:55 hiredman: technomancy: Word

13:56 dnolen___: Interface Builder was originally a Lisp program.

13:58 chrizel: There should be a functional way of making GUIs... :-/

13:58 hiredman: there are

13:59 ~google functional reactive programing

13:59 clojurebot: First, out of 46000 results is:

13:59 Functional reactive programming - Wikipedia, the free encyclopedia

13:59 http://en.wikipedia.org/wiki/Functional_reactive_programming

14:03 dnolen___: http://www.cs.virginia.edu/~robins/papers/Signal_Constellation_Design_Tool_A_Case_Study_in_User_Interface_Synthesis.pdf

14:03 history of original Interface Builder as Lisp program running on Macintosh

14:03 rfgpfeiffer: is there a continuation-based web framework for Clojure?

14:04 hiredman: nope

14:04 dnolen___: rfgpfeiffer: I'm still working on it

14:04 but not a whole framework

14:04 just middleware

14:04 then you can use whatever webframework you want.

14:04 stuartsierra: The JVM cannot support continuations natively.

14:04 dnolen___: you don't need to support full continuations for building webapps tho.

14:04 just delimited continuations, this what Seaside and Weblocks use.

14:04 stuartsierra: yes

14:05 Right, you can simulate continuations up to a point.

14:05 rhickey: stuartsierra: sorry I can't make it tomorrow - conflict w/school band concert!

14:05 dnolen___: stuartsierra: yeah, you only need to capture use interactions, not the whole state of the web stack.

14:05 user interactions.

14:06 rfgpfeiffer: http://github.com/nex3/arc/blob/b3d2199f52fc0ef96ae78656e5baff0b18cb6cf3/srv.arc only uses closures

14:06 stuartsierra: rhickey: that's ok. We're still sketchy on the venue anyway.

14:06 rhickey: stuartsierra: I wonder what the attendance might be for a NYC Clojure meetup group

14:07 hiredman: rhickey: did you see tbb's issue with binding and recur?

14:07 danlarkin: re: NYC meetup: on the right day I would go

14:08 stuartsierra: rhickey: I've wondered the same thing

14:23 tbb: hiredman: i just posted it to the group :)

14:26 hiredman: tbb: is this your first post?

14:26 tbb: yes

14:27 hiredman: ok, so it will sit in the moderation queue until rhickey gives it the go ahead

14:27 tbb: ah, i see

14:28 well, i'm not in a hurry :)

14:28 thanks for your time man

14:40 stuartsierra: and I'm back

14:50 mattrepl: wb

14:51 rhickey: stuartsierra: any thoughts on a meeting place?

14:57 stuartsierra: rhickey: Hmm. Columbia's too expensive, unless I can a group will sponsor it.

14:58 Let me think about it. Got to prepare for LispNYC tomorrow and an exam on Wednesday.

14:58 rhickey: stuartsierra: I guess that's why lispnyc meets in churches and bars :)

14:58 stuartsierra: rhickey: exactly.

15:01 smauel: hey guys so when is the 'programming clojure' book coming out?

15:02 cp2: how about a clojure meet in dc

15:02 rhickey: cp2: http://groups.google.com/group/clojure-study-dc

15:02 cp2: oh neat

15:03 smauel: anyone know?

15:03 stuartsierra: smauel: soon :)

15:04 You can get the PDF now.

15:04 smauel: ya but it's delayed isn't it?

15:04 it was meant to be out on the 28th april

15:04 stuartsierra: yes, it was delayed for the lazy sequence branch of Clojure, completed now

15:05 Chouser: yeah, someone changed the language.

15:05 cp2: those bastards =p

15:05 sdf: d

15:05 smauel`: sorry i dc

15:16 replaca: stuartsierra, rhickey: Can you do what we do here in SF? Find a friendly company with a big conference room.

15:17 rhickey: replaca: maybe, stuartsierra said he'd think on it

15:18 grzm: I think I'm misunderstanding the use of (ns com.example.foo (:use (com.example [bar :as bar])))

15:18 replaca: I mean, Lisp is a religion, but actually going to church seems a bit much :-)

15:18 stuartsierra: heh

15:19 rhickey: I've given a few talks at that church - it's very bizarre

15:19 grzm: I was thinking that I would need to refer to all of the com.example.bar objects using bar/some-bar-obj, but it seems like some-bar-obj works just fine by itself.

15:19 hiredman: grzm: replace :user with :require

15:19 er

15:19 :user

15:19 :use

15:19 blah

15:19 Chouser: or add :only []

15:20 grzm: hiredman: thanks for confirming

15:20 Chouser: I actually want the shortened namespace scoping as I have objects with the same names in different namespaces, so if I'm understanding correctly, I'd still get collisions with :only

15:21 rhickey: What's up with Scandinavia? Is there a big Clojure base there? I've been invited to speak at 3 separate conferences in Denmark, Norway and Sweden

15:21 * rhickey checks Clojure map...

15:21 stuartsierra: Maybe it's all those mobile phone folk.

15:22 Ask them when I can get a Lisphone.

15:22 Chouser: grzm: by default, 'use' will bring all the names into your new namespace. but if you say :only, then it will bring in just the ones you specify

15:23 grzm: so :only [] will bring in none -- just like 'require' does by default.

15:23 rhickey: stuartsierra: as soon as we get Clojure compiling to ObjectiveC

15:23 grzm: Chouser: thanks for confirming

15:23 stuartsierra: ObjectiveC, really? Oh, the iPhone, right.

15:23 grzm: oh, I see: you meant explicitly an empty array

15:23 Chouser: grzm: yes

15:23 empty vector

15:24 grzm: Chouser: vector :) cheers

15:24 cp2: rhickey: er.. really?

15:25 oh i see, didnt notice what stuartsierra said

15:25 rhickey: stuartsierra: on android already

15:25 Chouser: refcount instead of garbage collection (for ObjectiveC)?

15:26 rhickey: Chouser: that is the problem, even though Objc 2 has GC, iPhone doesn't?

15:26 dnolen: ObjC has garbage collection now, just not on phone. Probably a matter of time tho. There is a usable Lisp for iPhone Dev, Nu, but it's not nearly as nice as Clojure.

15:26 cemerick: is it realistic to think that clojure will eventually have more (full-featured) backends beyond the jvm and clr? Getting to the point where 90% is self-hosting obviously simplifies things, but that last 10% (concurrency primitives, memory model, etc) get *really* tricky on other signficantly-different platforms (objc, llvm, etc?)

15:26 Chouser: rhickey: so someone said.

15:26 cp2: how is clojure on clr doing anyway?

15:27 Chouser: cemerick: but looking at contrib, for example, may demonstrate how little that 10% is required for some large set of apps.

15:27 rhickey: cemerick: I'm not sure any would be 'full-featured' other than jvm/clr, but those are two huge targets. Still plenty of utility in partially-featured JS/ActionScript/ObjC, IMO

15:27 stuartsierra: agreed

15:28 dnolen: btw, if a Clojure NYC user group happens, I host a small study group in Brooklyn that would definitely be interested in coming.

15:29 stuartsierra: It will happen. How does mid-June sound?

15:29 dnolen: great

15:29 rhickey: Chouser: I got sidetracked a bit with this modularity stuff (it's a big deal for Netbeans/OSGi et al), because it looks like I can deliver some benefit pre-clojure-on-clojure. Then I'm onto c-i-c

15:30 replaca: rhickey: have you thought about Blackberry at all? I know it's mostly J2ME which I remember being an issue for Clojure. I have a good friend who's an evangelist there and could help us make that happen if it made sense.

15:30 rhickey: stuartsierra: sounds good, just as long as post-JavaOne

15:30 stuartsierra: ok

15:30 Chouser: rhickey: ok. I've been sidetracked by a new job and lack of non-work computer to do any side projects.

15:31 I haven't touched c-i-c in weeks, probably not since ILC

15:31 rhickey: replaca: I'm not going to go crazy trying to fit Clojure on very small profile Java, but plans include splitting out ASM and compiler stuff for smaller footprint, as well as options to drop docstrings etc

15:32 Chouser: I have thought about it a lot, mostly making a huge list of things it needs to address :(

15:33 Chouser: nice

15:33 rhickey: I think I need to do instance/make whatever in Java prior to c-i-c so we have it when defining c-i-c

15:33 hiredman: j2me is horrible

15:33 (btw)

15:33 smauel`: is clojure as fast as scala?

15:33 replaca: rhickey: makes sense. I think they're moving towards a biger footprint (to compete with iphone). Are there particular things we would need from them for it to make sense?

15:34 rhickey: replaca: the closer it is to j2se the better, more memory is always good too

15:36 hiredman: j2me is java 2, which is jdk 1.4 which is pre-Collections

15:36 dnolen: smauel: probably depends on what you are doing, both compile to bytecode so perf is probably comparable.

15:36 hiredman: wiat

15:36 rhickey: Chouser: I also had ideas about HIP (host-in-parens), basically a completely transparent non-abstracted DSL for generating host code, but homoiconic and thus allowing for macros. I don't like what gen-class is growing towards

15:36 hiredman: I lie

15:36 replaca: rhickey: are there any specific things along that continuum that I should probe for? I can do some reconnaissance and report back.

15:37 hiredman: jdk 1.4 has Collections

15:37 stuartsierra: host-in-parens sounds awesome

15:38 rhickey: stuartsierra: yeah the idea is that clojure in clojure would be 90% clojure, 10% host in parens, and host-in-parens would reduce pressure to cram every host feature into some Clojure feature

15:38 Chouser: huh

15:38 stuartsierra: So, in theory, you could emit x86 assembly if you wanted to?

15:39 Chouser: once you had written HIP-for-x86-assembly

15:39 stuartsierra: right

15:39 rhickey: by the time we add all access specifiers, package qualifiers, annotations etc into gen-class, I'd rather write Java

15:40 stuartsierra: yeah, that makes sense

15:40 rhickey: erm, I don't think assembly is going to be a viable host. We're still talking simple-object-based hosts

15:40 stuartsierra: fair enough

15:41 That still leaves a lot of options. JVM, CLR, Parrot, ...?

15:41 Chouser: did anyone see my little JNA bit? Makes C look more dynamic that I would have guessed.

15:41 than

15:41 dnolen: rhickey: this would grealy simplify getting Clojure subset to run ObjC? ... that would be sweet.

15:41 duncanm: Chouser: link?

15:41 Chouser: http://github.com/Chouser/clojure-jna/tree/master

15:42 cp2: Chouser: yeah, jna is pretty nice

15:42 oh, clojure jna

15:42 havent seen that ye

15:42 t.

15:42 rhickey: dnolen: I don't know enough about ObjC to say definitively. I'd love to target the iPhone, but don't know if lack of GC is prohibitive. Everything else has GC

15:42 cp2: looks good

15:42 Chouser: It's hardly anything but it's fun. With no other in-clojure setup or declarations: (jna-invoke Integer c/printf "My number: %d\n" 5)

15:43 rhickey: ah, printf

15:43 been a while

15:43 Chouser: right, because that's what you really want from libc

15:43 :-)

15:43 cp2: heh

15:43 I guess it's the number of bytes printed or

15:43 something? Anyway, feel free to ignore it just like all C programs do.

15:43 i chuckled

15:44 Chouser: I'm hoping this will be the solution to my dbus-java pain.

15:44 Chousuke: I didn't even realise printf had a return value

15:44 sohail: Chouser, that is effing hardcore man :-)

15:44 Chousuke: I'm sure I've read the manual page more than once.

15:44 cp2: yeah i didnt know that either

15:44 learn something new everyday =)

15:45 oh, jna-fn is nice

15:45 Chouser: yeah, I think many C programmers would be startled by: int i = printf(...)

15:46 sohail: I thought printf returns int... why is that startling?

15:47 danlarkin: ah university programming, where they made us check the return value of printf

15:48 cp2: seriously? uck

15:48 if (!printf(....)) printf("error printing\n");

15:48 oh wait...

15:48 danlarkin: yeah it was all if(printf("foo") > 0) style

15:49 Chouser: if printf didn't segfault, that sounds like success to me

15:49 rhickey: there you go

15:49 danlarkin: not so much with printf, but with sprintf it's useful

15:49 Chouser: That's the other thing you realize using jna, esp. with strings. One little misstep and down goes the JVM.

15:50 cp2: well, jna automagically converts java String to c style strings

15:50 so shouldnt be too problematic

15:50 Chouser: (c-printf "My number: %s\n" 5)

15:50 *boom*

15:50 hiredman: ouch

15:51 rhickey: Chouser: that was my problem with jFli (embedding JVM in CL), one interop problem and the JVM goes down, taking CL with it or at least rendering the JVM non-restartable

15:51 cp2: oh right Chouser

15:51 stuartsierra: wew

15:51 Chouser: rhickey: you had to do JNI stuff to get the two to talk?

15:51 stuartsierra: wow

15:51 rhickey: Chouser: big time JNI

15:51 cp2: yeah

15:52 rhickey: not fun

15:52 cp2: jni is disgusting =p

15:52 rhickey: but it was a one-time thing, once jFli was working you could new up and call Java objects as if they were CLOS objects

15:52 Chouser: jna is about as pretty as one could hope for.

15:53 rhickey: well, no offense, but I'm glad you gave up on it.

15:53 rhickey: That's the biggest relief with Clojure, the host/implementation lang and Clojure share GC/memory model/ type system etc. interop is perilous

15:54 Chouser: me too :)

15:54 drewr: rhickey: How reluctant were you at first to create a new lisp dialect? Was it a last resort?

15:55 rhickey: OTOH, it works - Nick Levine polished up jFli a bit subsequently and its perfectly useable

15:57 drewr: when I first learned CL after a dozen years of C++ I thought, "WT heck have I been doing with my life!? I want to eventually program like this (Lisp)". Only with Clojure does that now seem possible.

15:58 dnolen: :)

15:58 stuartsierra: "Clojure: Lisp for people who need to get s*** done."

15:58 rhickey: exactly

15:58 drewr: rhickey: I mean, was creating a separate lisp ever a definite "no" in your mind, an end you eventually had to compromise with?

15:58 clojurebot: rhickey is a T-1000 sent from the future

15:59 rhickey: though I'd prefer an expletive-free slogan :)

15:59 dnolen: at my study group the other day we were talking about the insanity of C++ const, and how you can avoid that alltogether if everything is immutable by default.

15:59 hiredman: ~optimizing

15:59 clojurebot: optimizing is http://clojure.org/java_interop#optimization

15:59 drewr: I'm guessing the answer is yes since you tried everything else first, but I didn't know how reluctant you were.

16:00 * Raynes huggles hiredman

16:00 rhickey: drewr: creating a new language is a crazy thing to do. The only reason I did that, rather than keep pursuing interop or move to ABCL/Kawa was I had some new ideas about mixing Lisp and FP

16:00 stuartsierra: rhickey: Yeah, might not sit too well for the corporate folks. But the college kids will like it.

16:01 technomancy: clojurebot: optimazating is http://wondermark.com/481/

16:01 clojurebot: Alles klar

16:03 rhickey: stuartsierra: after the "Ruby: Perform Like a Pr0n Star" slides scandal, I think Clojure should stay on the high road

16:03 drewr: lol

16:03 technomancy: there could be ladies present

16:03 Chouser: or gentlemen

16:04 technomancy: that too. =)

16:04 stuartsierra: Well, if you insist. :)

16:04 * rhickey keeps appreciating how nice the Clojure community is compared to c.l.l.

16:05 stuartsierra: "Clojure: Lisp without Weenies."

16:08 Raynes: "Clojure: Lisp of the Rings."

16:08 sohail: I thought pr0n stars only fake performance by doing the same scenes over and over to make it look longer

16:09 dmiles: btw: clojure on IKVM is pretty cool

16:09 stuartsierra: Yes, but we call it recursion.

16:09 dmiles: haha

16:09 sohail: ruby doesn't support tail recursion!

16:09 ok I'm done

16:10 dmiles: As far as introp with ABCL.Net.Dll its going to take more work.. almost better maybe if i have the interop in Java first

16:10 sohail: tail call optimization, now I'm done

16:11 rhickey: uh oh, time to switch to Axum: http://msdn.microsoft.com/en-us/devlabs/dd795202.aspx

16:11 says MS

16:12 Chouser: "builds upon the architecture of the Web"!?

16:12 * Chouser panics

16:12 * rhickey never recovered from DCOM

16:12 Raynes: Axum looks infinitely boring.

16:12 technomancy: "Should I Use Axum? Yes!" <= well, I guess that settles it then.

16:12 ataggart: lol

16:13 the hivemind has spoken

16:13 hiredman: I opened the programmer's guide, saw the visual studio "create a new project" stuff, and ran away

16:14 Chouser: hiredman: I just did the same thing.

16:14 technomancy: hiredman: maybe if you installed the Silverlight plugin you could be wowed by the video.

16:14 Chouser: The Basics ... screenshot ... close pdf viewer.

16:14 hiredman: technomancy: possibly

16:14 Chouser: But then again, I'm probably being closed-minded.

16:16 It's so much easier to dismiss a new language than to expend the effort to find out if it has anything worth learning about.

16:16 Chousuke: it kind of looks like it's C# with new keywords and syntactic sugar

16:17 hiredman: Chouser: exactly

16:18 Chousuke: pity the lesser languages.. if you want syntactic sugar all you can do is invent a new language ;(

16:18 * Raynes doesn't feel like installing Mono.

16:19 technomancy: Raynes: does it say it works on Mono? IronRuby doesn't.

16:19 Raynes: technomancy: No, I just don't feel like installing Mono. For any of those Microsoft languages.

16:22 edgar_: hello

16:23 i got clojure

16:23 but when i try to run it, i got an error

16:23 Chouser: edgar_: you downloaded the 1.0.0 zip file?

16:23 edgar_: i'm going to publish the error in pastebin.com

16:23 for you can see it

16:23 Chouser yes

16:23 <Chouser>

16:24 hiredman: ...

16:24 Chouser: hiredman: you spilled some dots

16:24 Raynes: ...

16:24 edgar_: http://pastebin.com/d446275a2

16:25 hiredman: edgar_: replace clojure.lang.Repl with clojure.main

16:25 edgar_: there is the pastebin link where is the error i got

16:25 ok let me see

16:25 stuhood: or run `java -jar clojure.jar`

16:25 hiredman: that too

16:25 edgar_: well i got a similar error

16:27 okok, now it runs with java -jar clojure.jar

16:28 i got other problem with the clojure netbeans plugin

16:28 i installed but it wont create a clojure project

16:28 it seems that is in development

16:29 and also i have netbeans 6.7 beta, so maybe isn't compatible

16:30 replaca: the axum guys lost me at "start Visual Studio...."

16:31 chrizel: is there an apply for methods? like (apply method-name object args)?

16:31 replaca: I see hiredman had the same reaction

16:31 Chouser: chrizel: the method takes varargs?

16:31 hiredman: edgar_: I do not believe there are too many netbeans users here, maybe Raynes can help?

16:32 Chouser: chrizel: or you just want to unpack a fixed number of args from a seq?

16:32 Raynes: I certainly can. NetBeans 6.7 is currently not supported.

16:32 You'll have to use 6.5 for now.

16:32 edgar_: so you are saying that netbeans isn't used by many users?

16:32 chrizel: Chouser, a fixed number of args i get from an vector - ok, then i could just unpack them before...

16:33 Chouser: chrizel: yeah, you can either use a macro, or just (.foo obj (v 0) (v 1) (v 2))

16:33 hiredman: edgar_: as far as this this channel goes the only one I know of off the top of my head is Raynes

16:33 Raynes: edgar_: Most people just use Emacs. The NetBean's plugin is pretty good, I switched to Eclipse simply because I use it more. Both plugins will improve in the future. They are quite new.

16:33 hiredman: I dunno about the community at large

16:34 edgar_: ok

16:34 Raynes: Well, /they work/. That's all I can promise. ;)

16:34 * hiredman makes a note of Raynes' switch

16:34 chrizel: Chouser, thx

16:34 edgar_: and so...most of the people prefer emacs over vim?

16:35 cads: hiredman: I think we can search certain classes of compact uncountable spaces in finite time. http://www.cs.bham.ac.uk/~mhe/papers/exhaustive.pdf

16:35 stuhood: Chouser, chrizel: this might be a usecase for 'memfn': (apply (memfn method-name) obj args)

16:35 hiredman: I use vim

16:36 stuhood: oh, no, nvm.

16:36 edgar_: maybe in the future we see other kind of plugin for vim

16:36 hiredman: ~vimclojure

16:36 clojurebot: vimclojure is state-of-the-art

16:37 hiredman: wow, that was not so useful

16:37 ~google vimclojure

16:37 clojurebot: First, out of 131 results is:

16:37 Kotka : Projects : Clojure : VimClojure

16:37 http://kotka.de/projects/clojure/vimclojure.html

16:37 chrizel: stuhood, oh thanks, i'll try

16:38 hiredman: edgar_: vimclojure is pretty nice, I have some issues with it's more advanced features, but most vimers find it acceptable

16:38 edgar_: ok

16:38 stuhood: chrizel: that code won't work directly, but i think it is a start... still trying to figure it out

16:38 hiredman: ~VIM

16:38 clojurebot: excusez-moi

16:38 hiredman: ~vim

16:38 clojurebot: Gesundheit!

16:39 hiredman: hmm

16:39 kotarak: Even without the advanced features <C-n> eg. should get you quite far.

16:39 The advanced features need introspection of Clojure. That implies certain constraints on the way the source looks like.

16:39 hiredman: I honestly never remember the shortcuts, so I just live with identing and highlighting

16:40 kotarak: hiredman: me too :) I'm getting used to <C-n> and <C-x><C-o> only slowly.

16:40 hiredman: huh

16:40 tab seems to do the same thing as <C-n> for me

16:40 I wonder's whose .vimrc I picked that up from

16:41 kotarak: hiredman: maybe the supertab plugin?

16:41 cads: hiredman, I don't think I can understand the topology and computability theory behind it, but the guy wrote a haskell monad that lets you define and search infinite yet exhaustible sets

16:42 hiredman: ah

16:42 well those are not sequences :P

16:42 ?

16:43 cads: yeah, sequences have an order topology that makes them inexhaustible I guess :)

16:43 hiredman: I imagine that would use specific knowledge in the domain of sets

16:44 cads: I'm going to see if can write the cantor set search function in clojure

16:44 I have to say the haskell version looks spiffy: http://math.andrej.com/2008/11/21/a-haskell-monad-for-infinite-search-in-finite-time/

16:44 stuhood: chrizel: it looks like memfn requires you to name all the arguments you'll be passing, but if that works for you, it will generate a function that you can apply to: (apply (memfn split sep) ["blah" "a"])

16:44 cads: apparently, a few of the functions can be generated for free just from their type specification

16:47 hiredman: ,^#'+

16:47 clojurebot: {:ns #<Namespace clojure.core>, :name +, :file "clojure/core.clj", :line 569, :arglists ([] [x] [x y] [x y & more]), :inline-arities #{2}, :inline #<core$fn__3327 clojure.core$fn__3327@189fe1e>, :doc "Returns the sum of nums. (+) returns 0."}

16:48 * technomancy would really love it if *file* returned a full path

16:49 chrizel: stuhood, i did it with let and destructuring, but good to know about memfn, could be useful sometime

16:50 stuhood: chrizel: yea... memfn just expands into a (let) wrapped in a (fn)

16:54 kotarak: technomancy: it should return a full path for a file read with load-file, no?

16:55 technomancy: kotarak: maybe... I haven't used load-file in months

16:55 kotarak: me neither...

16:55 technomancy: it's not much good if it doesn't return consistent results

16:55 hiredman: technomancy: well java sort of ignores the filesystem outside of jars files and the classpath

16:59 technomancy: quite a shame

17:00 there's no problem with binding vars outside the current namespace, right?

17:01 Chouser: using 'binding'? should just work.

17:02 hiredman: it makes sense if you think of the jvm as vm

17:02 as a

17:04 it is some what analogous to how I have heard old ur-unix hackers talk about the unix vm

17:17 technomancy: I can't def in clojurebot, can I?

17:18 hiredman: nope

17:18 technomancy: oh bugger. a lazy seq inside a binding will get realized after it exits the binding.

17:18 gah!

17:18 hiredman: yep

17:19 stuhood: unless you use (doall)

18:23 AWizzArd: Did anyone else also get this invitation email for a "facevibe" project?

18:25 is that some modern kind of spam email?

18:26 hiredman: sounds like spam

18:27 ataggart: ~optimizing

18:27 clojurebot: optimizing is http://clojure.org/java_interop#optimization

18:29 AWizzArd: someone got my email address from the google groups and told me he wants to start a new project and is looking for others to join it

18:29 But the interesting part is that he says hello to me with my real name, he talks about Clojure and Compojure

18:29 but the mail very much looks like spam

18:29 hiredman: it might not be spam spam

18:30 it might just be some random guy out to change the world and show everyone how wrong they are

18:30 AWizzArd: and the website he linked to looks empty to me

18:30 technomancy: well a smart way to get stuff by spam filters is to grab keywords from publicly available mailing lists in an effort to look legitimate

18:31 AWizzArd: technomancy: yes, maybe a bot with some human input

18:31 I don't want to post the link here, but maybe someone can check if the page is empty?

18:31 technomancy: AWizzArd: adblock?

18:31 AWizzArd: hiredman: you want to take a look? :)

18:31 technomancy: you could curl it

18:32 AWizzArd: technomancy: I turned that on yes, but I expect that if someone invites me to a project, there will be something visible

18:32 hiredman: AWizzArd: my curiosity is piqued

18:53 AWizzArd: wb chessguy

18:53 chessguy: why thanky

18:53 AWizzArd: maybe you can give hiredman an api, so he can make Clojurebot play chess using your engine? :p

18:54 chessguy: hmm

18:55 Raynes: "honestly? i would rather date a girl who uses heroin than a girl who uses emacs"

18:56 hiredman: clojurebot: e4 is <reply>I resign

18:56 clojurebot: Alles klar

18:56 hiredman: clojurebot: pawn to e4!

18:56 clojurebot: I resign

18:56 hiredman: there, it plays chess

18:57 AWizzArd: now it can even play chess!

19:01 dysinger: heh

19:01 Raynes das funny

19:01 Raynes: dysinger: BONUS from #Haskell twittered that a moment ago.

19:02 dysinger: I would rather lick the bathroom clean than use VIM

19:28 dnolen: technomancy: how far is the clojure httpclient along, are you planning on using this with couchdb?

19:29 technomancy: dnolen: it's pretty usable at this point.

19:29 I've used it with couch; it seems to be pretty straightforward.

19:29 dnolen: nice!

19:31 technomancy: dnolen: it could be more performant if it used keepalive connections

19:31 I think that's the only significant thing left, unless others can think of any further enhancements.

19:31 dnolen: is keepalive difficult?

19:31 technomancy: not sure. =)

19:32 dnolen: :)

19:35 unlink1: Is there a more elegant way of expressing (concat (when x (list x)) coll) ?

19:37 cmvkk: to remove false values from a collection, you mean?

19:37 er, wait

19:38 you want to add x to the beginning but only if it isn't false

19:41 unlink1: I guess something like (defmacro cons-when [x xs] (let [tmp# x] (concat (when tmp# (list tmp#)) xs)))

19:42 I mean, (defmacro cons-when [x xs] `(let [tmp# ~x] (concat (when tmp# (list tmp#)) ~xs))

19:42 clojurebot: x is y

19:42 cmvkk: yeah. although for the record, concat isn't exactly cons.

19:42 unlink1: no, but I'm logically consing.

19:46 It could be implemented with cons. (defmacro cons-when [x xs] `(let [first# ~x rest# ~xs] (if first# (cons first# rest#) rest#)))

19:46 cmvkk: it's probably more efficient that way.

19:47 unlink1: Well whatever the implementation, I'm sure I'm not the first person to have the idea.

19:48 cmvkk: if you didn't care until the end, you could always just cons everything and then do (filter identity coll) afterwards.

19:49 probably not faster but maybe shorter

19:56 unlink1: Is this a correct/idiomatic implementation? (defmacro cons-when [x xs] `(let [first# ~x rest# ~xs] (if first# (cons first# rest#) rest#)))

21:55 chessguy: sure got quiet in here

22:51 eyeris: How can I instantiate an array of Java objects from Clojure?

22:53 I want to use the Gtk java bindings, but the ListStore class requires a DataColumn[].

22:54 Ahh, nevermind, I see (to-array coll) on the java_interop page.

22:54 danlarkin: eyeris: there's a few ways to create arrays, make-array being another

23:09 jmaness: does anyone know if there is an easy way to partition a collection based on a function?

23:10 Chouser: is the collection in order -- split it once? or collect things from where-ever into two groups?

23:10 durka42: there is partition-by

23:11 jmaness: ah thanks

23:11 the collection isn't in order but partition-by in contrib looks like it will work

23:11 Chouser: good

Logging service provided by n01se.net