#clojure log - Oct 14 2010

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

0:05 amalloy: kmc: hotspot's jit is pretty good, i think. but i'm not a performance expert by any means

0:12 rplevy: how far can one elaborate on something like this do you think? (defmacro with-turbo [turbo-on & body] `(let [~'map ~(if turbo-on `clojure.core/pmap `clojure.core/map)] ~@body))

0:12 it's kind of the opposite of the Macintosh turbo button ;)

0:13 amalloy: rplevy: not sure what you mean by elaborate

0:13 rplevy: say if you don't know whether your code will be running on a quad core machine or a netbook and you want to provide an option

0:14 amalloy: I mean, add more conditional stuff to take advantage of parallelism for free

0:14 amalloy: taking advantage of parallelism for free turns out to be a lot more difficult than it looks (cf kmc's efforts a few nights ago)

0:15 rplevy: amalloy: I'll take a look, sounds interesting

0:15 amalloy: rplevy: the main issue is that pmap needs to be given a smallish number of large tasks in order to be useful, because it spawns a thread for each task

0:15 (it doesn't run all the threads at once, but it does create a new thread for each task)

0:16 rplevy: amalloy: what day's log is kmc's experiment in?

0:16 amalloy: uhhhhh

0:16 sec

0:16 mon oct 11

0:17 on my computer, anyway, which is pacific time

0:17 :P

0:17 so in greenwich it's probably tuesday morning

0:18 rplevy: search for pmap to find it quickly within the log file

0:18 rplevy: amalloy: yeah, so of course there is no free lunch, but still useful on occasion to wrapp small things in something like this, using judgment for specific cases

0:19 amalloy: rplevy: yes, clojure certainly provides a good groundwork for writing sensible parallel tasks

0:22 chouser: map has defined different semantics when the function you give it has side effects. pmap doesn't, I think.

0:22 clojure's got a lot more tools around concurrency at this point than it does around parallelism

0:23 _rata__: hi

0:23 amalloy: chouser: you don't think it's defined as "totally arbitrary and don't rely on it"?

0:23 i mean, that's sorta the same as totally undefined, i guess

0:24 _rata__: records are persistent, right?

0:25 rplevy: chouser: interesting, it seems inevitable then for more high-level abstractions for parallelism to enter the language

0:27 amalloy: _rata__: yes, they are immutable, if that's what you mean

0:27 _rata__: amalloy, i mean, is it ok to use them with STM?

0:28 amalloy: _rata__: yes, because they are immutable. they implement java.util.map, which has a put() method, but if you actually call it they throw an exception

0:30 _rata__: i asked because of the optimization STM can do using persistent vectors/maps/lists

0:30 amalloy: what optimization is that?

0:30 _rata__: STM can do that optimization using any immutable data?

0:30 amalloy: (records implement IPersistentMap, so whatever they are it seems likely that STM can use them on records)

0:30 _rata__: not having to do copies

0:31 ok

0:31 *to make copies

0:31 thanks

0:31 I was unsure

0:31 amalloy: _rata__: i can't defrecord on clojurebot, but you can try (supers (class x)), where x is some defrecord'ed object

0:31 _rata__: ok

0:34 good night

0:47 LauJensen: Good morning all

0:50 amalloy: morning lau. up early today?

0:51 (note: i don't actually know what time it is where you are, but you're usually not around for two more hours or so)

0:52 LauJensen: amalloy: Yea I usually get here by 9AM but todays its 6:50AM now

0:54 notsonerdysunny: how can one create a soft-link in a cake-task?

0:55 LauJensen: soft link?

0:55 amalloy: as in the $ ln -s variety?

0:55 notsonerdysunny: LauJensen: yes soft link

0:55 LauJensen: amalloy: thats a symlink

0:55 KirinDave: Anyone here good with enlive?

0:55 notsonerdysunny: :) yes symlink

0:56 amalloy: LauJensen: i know, but it was likely to be what he meant

0:56 KirinDave: Having problems with nth-of-type.

0:56 LauJensen: (sh "ln" "-s" "src" "dest")

0:56 amalloy: i think you have to launch the shell; java doesn't have symlink feature

0:56 LauJensen: amalloy: yea you're just a lot smarter than me it seems :)

0:56 lancepantz: nah, you should use the ant task

0:56 amalloy: LauJensen: perhaps a lot dumber!

0:56 lancepantz: notsonerdysunny: http://ant.apache.org/manual/Tasks/symlink.html

0:56 so you would use cake's ant helper fn

0:57 LauJensen: lancepantz: any idea what that does on Windows?

0:58 amalloy: LauJensen: i wouldn't be surprised if it did what cygwin does

0:58 LauJensen: Which is?

0:58 notsonerdysunny: lancepantz: can you please give me the syntax for the cake's ant helper function to create a symlink

0:58 amalloy: which iirc is create a .lnk (windows shortcut file), with metadata attached to it that lets other cygwin processes treat it as a symlink

0:58 LauJensen: ah ok

0:58 notsonerdysunny: I think Windows 7 and vista support link

0:58 lancepantz: (ant Symlink {:link "foo" :resource "bar"})

0:59 notsonerdysunny: thanks lancepantz

0:59 lancepantz: LauJensen: there's a disclaimer at the end of the above link

1:00 amalloy: LauJensen: yeah, just checked my windows machine. ln -s creates a .lnk with some kind of special metadata

1:00 LauJensen: great.

1:01 amalloy: (on my 5-year-old XP system. sunny seems to think vista/7 are smarter)

1:11 notsonerdysunny: amalloy: I read about it some-where .. not very positive though

1:13 Bahman: Hi all!

1:14 LauJensen: Morning Bahman

1:14 Bahman: Hi there LauJensen!

1:21 chouser: NTFS has supported links forever, I think, but the rest of the OS and the applications all get very confused.

1:26 notsonerdysunny: chouser: so what is the command to create a symlink or hardlink in windows/NTFS then?

1:30 amalloy: chouser: this seems to be true. my ubuntu system can create a hardlink on the mounted ntfs drive that windows uses. whether or not windows can understand it i haven't tested

1:50 sandGorgon: is there any way for me to figure out what is the exact java command used by lein when I do "lein repl" in a project ? is there any verbose setting for example

1:52 LauJensen: sandGorgon: Well, there is an environment variable which you can set, to make it more verbose, it outputs the classpath at least. But I'd just run ps ax |grep java if I wanted to know

1:54 kmc: you could use strace

1:54 sandGorgon: kmc, how do I use strace for that ?

1:55 amalloy: sandGorgon: or jps and then look at /proc/xxxxx/cmdline

1:55 kmc: strace -f -e execve -s 99999999 lein repl

1:57 sandGorgon: kmc, wow.. thanks that was great.

1:57 LauJensen, thanks.. that worked as well ;)

1:59 LauJensen: np

2:05 sandGorgon: has anyone looked at the source code of cake ? it is kinda funky - for e.g. src/cake/tasks/jar.clj:53 why is "(ns cake)" a string, which is written into a file called build/jar/cake.clj when cake is invoked ?

2:09 notsonerdysunny: does the reader macro #' have a corresponding function

2:09 lancepantz: sandGorgon: yeah, so cake actually runs in two jvms

2:09 amalloy: ,(get-var 'clojure.core/first)

2:09 clojurebot: java.lang.Exception: Unable to resolve symbol: get-var in this context

2:09 lancepantz: once for your project, and one that processes cake commands

2:09 amalloy: ,(ns-resolve 'clojure.core 'first)

2:09 clojurebot: #'clojure.core/first

2:10 amalloy: notsonerdysunny: there's one that's more convenient than that, lemme go find it

2:10 lancepantz: then there is a ruby script that sits in front of those two, sending forms over the socket to get evaled in the jvms

2:10 LauJensen: ,(= (var test) #'test)

2:10 clojurebot: true

2:10 notsonerdysunny: ,(doc var)

2:10 clojurebot: notsonerdysunny: I don't understand.

2:10 notsonerdysunny: ->(doc var)

2:10 sexpbot: ⟹ "Special Form: Please see http://clojure.org/special_forms#var"

2:10 amalloy: ,(var-get 'clojure.core/first)

2:10 clojurebot: java.lang.ClassCastException: clojure.lang.Symbol cannot be cast to clojure.lang.Var

2:11 kmc: what does sexpbot do?

2:11 notsonerdysunny: ->(doc var-get)

2:11 sexpbot: java.lang.SecurityException: Code did not pass sandbox guidelines: (#'clojure.core/var-get)

2:11 LauJensen: ,(-> #'var meta :doc println)

2:11 clojurebot: java.lang.Exception: Unable to resolve var: var in this context

2:11 amalloy: roughly the same as clojurebot, with a different codebase

2:12 notsonerdysunny: var is a special form ..

2:12 so I guess we can't do #'var

2:12 sandGorgon: lancepantz, all right, but then why isnt there an inherent cake.clj in the project itself ? I dont think cake can be run from the commandline (using java commandline) because there is no cake.clj

2:12 notsonerdysunny: LauJensen: *

2:13 LauJensen: ,(-> #'loop meta :doc println)

2:13 clojurebot: Evaluates the exprs in a lexical context in which the symbols in the binding-forms are bound to their respective init-exprs or parts therein. Acts as a recur target.

2:13 LauJensen: -> (doc loop)

2:13 sexpbot: ⟹ "Special Form: Please see http://clojure.org/special_forms#loop"

2:13 amalloy: ,(find-var 'clojure.core/first)

2:13 clojurebot: #'clojure.core/first

2:13 LauJensen: notsonerdysunny: ^^

2:14 amalloy: notsonerdysunny: the functions you probably want are intern, find-var, and ns-resolve

2:15 notsonerdysunny: thanks amalloy and LauJensen

2:25 amalloy: ,(zipmap (map (juxt identity -) (range 4)))

2:25 clojurebot: java.lang.IllegalArgumentException: Wrong number of args (1) passed to: core$zipmap

2:25 amalloy: ,(apply zipmap (map (juxt identity -) (range 4)))

2:25 clojurebot: java.lang.IllegalArgumentException: Wrong number of args (4) passed to: core$zipmap

2:25 amalloy: blahhhh

2:26 ,(apply hash-map (map (juxt identity -) (range 4)))

2:26 clojurebot: {[0 0] [1 -1], [2 -2] [3 -3]}

2:27 LauJensen: amalloy: let me guess, you used to do a lot of perl ? :)

2:27 kmc: ,(doc juxt)

2:27 clojurebot: "([f] [f g] [f g h] [f g h & fs]); Alpha - name subject to change. Takes a set of functions and returns a fn that is the juxtaposition of those fns. The returned fn takes a variable number of args, and returns a vector containing the result of applying each fn to the args (left-to-right). ((juxt a b c) x) => [(a x) (b x) (c x)]"

2:27 amalloy: LauJensen: hah, not actually very much. why, am i trying to do something like perl?

2:27 kmc: cool function

2:28 amalloy: kmc: yes, it's one to keep in mind. it turns out to be useful in a lot of interesting ways

2:28 LauJensen: amalloy: I once did something like what you just did, ie. tweaking until something working came out. Someone rebuked me saying "You need to understand what you're doing, not just tweak until it works, thats perl development"

2:28 amalloy: ,(map (juxt inc dec) (range 5))

2:28 clojurebot: ([1 -1] [2 0] [3 1] [4 2] [5 3])

2:28 kmc: amalloy, yeah, i've used something similar in Haskell

2:29 amalloy: LauJensen: in perl, tweaking is your only option. clojure gives you the choice to understand what you're doing...or just keep pounding on the keyboard like i was doing

2:29 kmc: heh

2:29 LauJensen: amalloy: well, im just gla you're not in charge of marketing

2:29 kmc: them's fightin' words

2:29 amalloy: i always have trouble creating a hash-map out of a map

2:29 LauJensen: kmc: naah, all the fighting words are on my blog :)

2:29 amalloy: ,(apply hash-map (mapcat (juxt identity -) (range 4)))

2:29 clojurebot: {0 0, 1 -1, 2 -2, 3 -3}

2:30 amalloy: there we go

2:30 kmc, what time zone are you in, if you don't mind?

2:30 kmc: EDT

2:30 LauJensen: ,(map (juxt (comp inc rand-int) +) (range 10))

2:30 kmc: GMT-4

2:30 clojurebot: ([1 0] [1 1] [1 2] [1 3] [1 4] [5 5] [2 6] [5 7] [7 8] [8 9])

2:31 kmc: comp is function composition?

2:31 amalloy: yes

2:31 LauJensen: yes

2:31 amalloy: blurgh. i used to stay up that late, but now that i have a job i can't stay up past like 1 without killing myself (pacific time)

2:31 LauJensen: (comp f g) = (f (g x))

2:31 amalloy: you're getting older :)

2:31 amalloy: LauJensen: not so. ((comp f g) x) = (f (g x))

2:32 LauJensen: tsk

2:32 amalloy: LauJensen: and yeah, getting older, but mostly getting up earlier

2:33 (or at least that's what i tell myself)

2:34 LauJensen: I really would like to know what they eat, the guys who run on 4 hours of sleep every night, that must be great

2:34 kmc: ,((comp inc *) 5 4)

2:34 clojurebot: 21

2:35 kmc: sweet

2:35 amalloy: LauJensen: future years of their lives

2:36 bobo_: and efficency of the ours they are awake

2:37 they probably get less done in more time

2:37 LauJensen: bobo_: Tell that to Obama, Denmarks former Primeminister and Dana White, who all seem to get a lot done

2:37 amalloy: i get about six hours a night, and ten hours once a week when i realize i'm exhausted :P

2:38 kmc: ((comp + *) 5 4)

2:38 ,((comp + *) 5 4)

2:38 clojurebot: 20

2:38 LauJensen: amalloy: yea I used to do that, if was just 5 and 10

2:38 kmc: ,((comp (partial + 1) *) 5 4)

2:38 clojurebot: 21

2:38 amalloy: ,((juxt + *) 5 4)

2:38 clojurebot: [9 20]

2:44 notsonerdysunny: can anybody help me figure out why #(-> % second :name) goes through fine while #(-> % second (fn [x] (:name x))) does not .. both seem identical to me...

2:45 amalloy: ,(macroexpand '(-> % (fn [x] (:name x))))

2:45 clojurebot: (fn* % ([x] (:name x)))

2:45 amalloy: ,(macroexpand '(-> % ((fn [x] (:name x)))))

2:45 clojurebot: ((fn [x] (:name x)) %)

2:45 amalloy: notsonerdysunny: you want the second of these

2:47 (though what you *actually* want is (comp :name second))

2:47 notsonerdysunny: amalloy: aha .. I think I see what is happening .. thanks .. :)

2:48 yea you are right comp is a better way of doing it

2:48 amalloy: ,((comp :name second) [{:name 10} {:name 15}])

2:48 clojurebot: 15

2:51 LauJensen: ,15

2:51 clojurebot: 15

2:51 LauJensen: much easier

2:51 amalloy: LauJensen: you're right. i don't know why i bother writing any programs; i should just figure things out by hand and then write the answer in a clj file

2:51 notsonerdysunny: LauJensen: :)

2:51 amalloy: ,(identical? 15 15)

2:51 clojurebot: true

2:52 LauJensen: ,(identical? 130 130)

2:52 clojurebot: false

2:52 amalloy: that's the result i would have expected

2:52 why did i get true?

2:52 kmc: haha

2:52 interning of small integers?

2:52 ,(doc identical?)

2:52 LauJensen: amalloy: The first 128 integers are hardcoded in the jvm

2:52 clojurebot: "([x y]); Tests if 2 arguments are the same object"

2:52 amalloy: ,(identical? -5 -5)

2:52 clojurebot: true

2:53 kmc: ,(let [x 130] (identical? x x))

2:53 clojurebot: true

2:53 amalloy: LauJensen: the first 256 :P

2:53 kmc: the first 127 and the last 128

2:53 LauJensen: sure

2:53 punks

2:53 :)

2:53 amalloy: kmc: that adds up to 255. you have to include 0 in one of the two sets

2:54 LauJensen: ,(true? (Boolean. "true"))

2:54 clojurebot: false

2:54 kmc: that constructs a Java Boolean from the string "true"?

2:54 is there a better way to write #(identical? % %) ?

2:54 LauJensen: ,(Boolean. "true")

2:54 clojurebot: true

2:54 kmc: ,(Boolean.)

2:54 clojurebot: java.lang.IllegalArgumentException: No matching ctor found for class java.lang.Boolean

2:54 amalloy: kmc: identical?

2:54 oh

2:54 kmc: ,(new Boolean)

2:54 clojurebot: java.lang.IllegalArgumentException: No matching ctor found for class java.lang.Boolean

2:55 kmc: ,(new Boolean "true")

2:55 clojurebot: true

2:55 kmc: in general, is there a better way to write #(f % %)

2:55 lypanov: ,(new Boolean TRUE)

2:55 clojurebot: java.lang.Exception: Unable to resolve symbol: TRUE in this context

2:55 LauJensen: (new Boolean "true") == (Boolean. "true")

2:55 * lypanov forgot it

2:55 LauJensen: lypanov: You're thinking of Boolean/TRUE

2:55 lypanov: ah, thats the one. forgot the syntax.

2:55 kmc: ,Boolean/TRUE

2:55 clojurebot: true

2:55 kmc: and that's a static field of the Boolean Java class?

2:55 ,(Integer. 3)

2:55 clojurebot: 3

2:55 * lypanov hasn't got to the java interop part of JoC yet :P

2:56 amalloy: kmc: i'm not sure, about (f x x). there must be an easy way

2:56 LauJensen: ,(set (range 32))

2:56 clojurebot: #{0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31}

2:56 LauJensen: ,(set (range 33))

2:56 clojurebot: #{0 32 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31}

2:56 kmc: heh

2:56 lypanov: cute

2:56 kmc: ,(class 5)

2:56 clojurebot: java.lang.Integer

2:56 kmc: ,(class 5000000000000000000000000)

2:56 clojurebot: java.lang.ExceptionInInitializerError

2:57 amalloy: !

2:57 kmc: ;P

2:57 lypanov: huh

2:57 LauJensen: This is almost better than PHP :)

2:57 amalloy: oh

2:57 kmc: ,(Bignum. 500000 500000)

2:57 clojurebot: java.lang.IllegalArgumentException: Unable to resolve classname: Bignum

2:57 kmc: ,(java.lang/Bignum. 500000 500000)

2:57 clojurebot: java.lang.ClassNotFoundException: java.lang

2:57 kmc: hrm

2:57 LauJensen: kmc: in 1.3 you can to (class 5000000000000000000N)

2:57 amalloy: ,(class 500000000000000000L)

2:57 clojurebot: Invalid number: 500000000000000000L

2:57 amalloy: ,(class 500000000000000000M)

2:57 clojurebot: java.math.BigDecimal

2:58 kmc: cool

2:58 LauJensen: ,(class (bigint 5000000000000000000000000))

2:58 clojurebot: java.lang.ExceptionInInitializerError

2:58 LauJensen: eh?

2:58 ,(clojure-version)

2:58 clojurebot: "1.2.0-master-SNAPSHOT"

2:58 LauJensen: -> (class (bigint 5000000000000000000000000))

2:58 amalloy: ,(doc bigint)

2:58 sexpbot: java.lang.Exception: EvalReader not allowed when *read-eval* is false.

2:58 clojurebot: "([x]); Coerce to BigInteger"

2:58 LauJensen: ,*read-eval*

2:58 clojurebot: false

2:58 amalloy: LauJensen: (bigint) doesn't get called until 50000000000000 is evaluated, and it's an illegal integer literal

2:59 LauJensen: anyway, I should really do some work

2:59 amalloy: ,100N

2:59 lypanov: hehe

2:59 clojurebot: Invalid number: 100N

2:59 LauJensen: amalloy: works in the repl here though

2:59 amalloy: hm

2:59 LauJensen: same clojure version

3:00 kryft: Does this just destructure the value of the function neighbors? ([size yx] (neighbors [[-1 0] [1 0] [0 -1] [0 1]] size yx))

3:00 (Looking at listing 5.1 in JoC)

3:01 amalloy: kryft: no, that code is doing no destructuring

3:01 it is treating the vector [size yx] as a function, and calling it with the result of (neighbors ...)

3:01 when vectors are called as functions, they treat their argument as an index

3:02 ,([\a '- "qqq"] 1)

3:02 clojurebot: -

3:02 Chousuke: that looks more like a variadic function definition for the [size yx] parameter vector

3:02 taken out of context :P

3:02 amalloy: however, if there's a (fn) lurking around near the code that you didn't show us...

3:03 (and i agree with Chousuke, it looks like it is)

3:06 kryft: amalloy: http://pastebin.com/YTPJ8iUq (Listing 5.1 in Joy of Clojure)

3:06 amalloy: kryft: Chousuke is correct

3:06 Chousuke: yeah. it calls the 3-arg version of neighbor from the 2-arg version

3:06 amalloy: it's saying that neighbors can take 2 or 3 arguments. the 2-argument version calls the 3-arg version

3:06 Chousuke: the first arg is just a vector of vectors.

3:07 kryft: Ah, ok, I don't think that was covered in the book yet. :)

3:08 I forgot about that syntax for indexing vectors even though I just read about it. :P

3:10 amalloy: kryft: see 2.3.2

3:10 discussing variadic args

3:14 tomoj: anyone using octobot in clojure yet?

3:22 amalloy: ah, kryft, he does mention using vectors as functions in chapter 5, but it's hidden so well i had to reread the whole damn chapter to find it

3:22 it's in 5.2.2

3:30 bartj: ,([1 2 3] 0)

3:30 clojurebot: 1

3:33 tomoj: ztellman is my hero

3:33 amalloy: ,([1 2 3] -1)

3:33 clojurebot: java.lang.IndexOutOfBoundsException

3:33 amalloy: :(

3:33 LauJensen: tomoj: why?

3:35 tomoj: http://github.com/ztellman/gloss

3:35 not to mention aleph

3:36 zkim: and penumbra

3:38 LauJensen: Yea he's a cool and crafty guy, no doubt

3:42 kmc: cool

3:42 embedded gpgpu programming for clojure

3:42 i like that a lot

3:42 LauJensen: kmc: Yea he's done 2 amazing ports of my blogposts to Penumbra

3:43 First Brians Brain, when in optimized Clojure it does a 160x160 board in 1.6ms, Zach kept it at 1.6ms per iteration, but on a 2000x2000 board. My Fluid sim ran about 35 fps (I think) on a 80x80 board, Zach had it on 55 fps on a 800x600 board.

3:43 kmc: nice

3:43 i love GPU programming

3:43 need to get back into it

3:44 i was doing fractal video feedback loops at 4096 x 4096 x 60fps, in 2007, without particularly optimizing my code

3:44 there's just so much power there

3:44 that card is probably in every midrange machine now

3:44 LauJensen: I read that the largest supercomputer in 1998 had the same power as a 500$ graphics card today

3:44 kmc: hehe

3:45 hiredman: thats a hell of a screensaver

3:45 kmc: well, i'd bet that supercomputer had more ability to do *different* things at once

3:45 LauJensen: no

3:45 it would only solve solitaire puzzles

3:45 kmc: haha

3:45 LauJensen: j/k ofc :)

3:46 kmc: http://en.wikipedia.org/wiki/Semi_Automatic_Ground_Environment ← the largest computer, ever

4:37 jjido: no clojurebot today

4:37 LauJensen: jjido: ?

4:38 jjido: ,true

4:38 LauJensen: clojurebot: where are you ?

4:38 -> true

4:38 sexpbot: ⟹ true

4:38 LauJensen: Well, there are alternatives

4:46 jjido: -> (:foo nil)

4:46 sexpbot: ⟹ nil

4:52 jjido: killall -s java | wc -l --> 6

4:52 killall java

4:52 how many stray processes do I have?

4:57 Is there a string representation of Clojure objects which is resilient to structural loops (with an atom)?

5:01 notsonerdysunny: thanks raek

5:01 that actually highlights the use of atom

5:01 :)

5:02 raek: sorry for being offensive about the def thing... I should have mentioned what "the right way" was, rather than just saying "you're doing it wrong"

5:04 bmh: dear #clojure -- I love clojure so much. The Java interop makes me so happy

5:04 jjido: -> (take 10 (.toString first))

5:04 sexpbot: java.lang.SecurityException: Tried to call: toString on clojure.core$first@137e670 which is not allowed.

5:06 notsonerdysunny: raek: no problem ... being critical is what makes this fun.. :)

5:06 esj: bmh: absolutely, playing with libraries like JFreeChart from a repl makes me uncommonly happy

5:07 bmh: esj: I found a C++ library that did the things I wanted it to do, but bugger, it's written in C++. I found a Java library that did some of the things I want to do, so bam. I can use the Java bits to port the C++ code I need!

5:07 (sorry if that was incoherent)

5:07 esj: bmh: not at all

5:07 raek: notsonerdysunny: actually, thing the counter example would be a good example to have on clojuredocs. it very clearly shows how the function is applied to the data structure

5:09 jjido: -> (take 10 (str first))

5:09 sexpbot: ⟹ (\c \l \o \j \u \r \e \. \c \o)

5:10 jjido: but I guess that won't prevent a stack overflow.

5:12 raek: jjido: what are you trying to do? :)

5:13 jjido: raek: I want to find out what I did wrong (error), so I want to print out objects. But that goes in infinite loop because of an atom.

5:14 raek: jjido: does the data structure in the atom have a reference to the atom itself?

5:14 jjido: yes

5:15 raek: then it might be a good thing to wrap the printing code in a (binding [*print-level* 10] ...)

5:16 when an atom is printed/stringified, it will turn its contents into a string first

5:16 at the repl, you can also do a (set! *print-level* 10)

5:16 jjido: is that the depth or the string length?

5:17 raek: form depth

5:17 there is a *print-length* too

5:20 notsonerdysunny: can somebody help me with an example for apply-macro from clojure.contrib.apply-macro

5:24 (defmacro hello [x]

5:24 `(sayhello ~x))

5:24 (macroexpand-1 (apply-macro hello '(10)))

5:25 http://gist.github.com/625927 is my example .. but I keep getting a stack overflow ..

5:34 jjido: raek: ok, I inadvertently shared an atom :(

5:52 I see no effect of using the *print-length* binding. *print-level* works great though.

6:20 raek: ,(binding [*print-length* 3] (println ["one" "two" "three" "four"]))

6:20 clojurebot: [one two three ...]

6:21 raek: it inly restricts the number of element printed from collections

6:21 ,(binding [*print-level* 3] (println ["one" ["two" ["three" ["four"]]]]))

6:21 clojurebot: [one [two [three #]]]

6:23 raek: *print-length* is useful when dealing with infinite or very long sequences and *print-level* when dealing with circular structures or deep trees

6:26 jjido: raek: thanks

6:34 rfgpfeiffer: how can i give a function a fixed time to return or kill it?

6:36 raek: rfgpfeiffer: I know that clj-sandbox (http://github.com/Licenser/clj-sandbox) does something like that

6:37 http://github.com/Licenser/clj-sandbox/blob/master/src/net/licenser/sandbox.clj#L35

6:38 LauJensen: rfgpfeiffer: http://gist.github.com/626002

6:38 rfgpfeiffer: thanks

6:38 LauJensen: np

6:41 raek: ,(class (future 1))

6:41 clojurebot: clojure.core$future_call$reify__5492

6:43 raek: hrm, what happens with the running code if a timeout occurs?

6:43 LauJensen: it gets barged

7:56 tobiasraeder: anyone ever done anything with wings and clojure?

8:06 carkh: wew that wing thing is ugly

8:09 LauJensen: carkh: ?

8:11 carkh: i was reacting to tobiasraeder's query

8:11 bmh: I'm trying to use penumbra and the universe is exploding on me when I run 'lein test'

8:13 hurumph, looks like a case of a broken test

8:16 LauJensen: carkh: Yea, just wondering what you were looking at

8:16 ie. link

8:17 carkh: http://wingsframework.org/wingset/WingSet/

8:17 LauJensen: bmh: just start a project vm and run the examples

8:17 bmh: LauJensen: I just spotted it on the bug tracker

8:17 thanks

8:23 kumarshantanu: I have a question on Java interop

8:23 ,(. "Hello" :toLowerCase) ; this works

8:23 clojurebot: "hello"

8:24 kumarshantanu: ,(. "Hello" :substring 3 4) ; but this doesn't

8:24 clojurebot: java.lang.IllegalArgumentException: Malformed member expression

8:24 kumarshantanu: can anyone help me understand this?

8:24 carkh: ,(. "hello" substring 3 4)

8:24 clojurebot: "l"

8:25 carkh: don't know why using a keyword should work on the first example

8:25 you're supposed to use simple symbols

8:25 kumarshantanu: carkh: I want to be able to compose the method name at runtime (I don't know them in advance)

8:25 LauJensen: kumarshantanu: The first example shouldnt work, thats just a result of how keywords are implemented

8:25 carkh: kumarshantanu: what's your use case ?

8:26 kumarshantanu: LauJensen: I see

8:26 carkh: I have a bunch of setter methods to be called, so want to create a helper function to call them

8:26 but I don't know them in advance

8:27 carkh: you might have to use reflection

8:27 there is a helper function somewhere in clojure (java side)

8:27 clojrue.lang.Reflector has it i think

8:28 kumarshantanu: example: (setter! some-obj {:method1 [m1-value1] :method2 [m2-value1 m2-value2]}) --> (doto some-obj ((.method1 m1-value1) (.method2 m2-value1 m2-value2))

8:28 carkh: (clojure.lang.Reflector/invokeInstanceMethod instance method-name-as-string array-of-args)

8:28 kumarshantanu: okay *looking*

8:29 carkh: note that args are an array, not a vector

8:29 http://github.com/richhickey/clojure/blob/master/src/jvm/clojure/lang/Reflector.java

8:31 kumarshantanu: carkh: there seems to be a c.c.reflect too -- http://richhickey.github.com/clojure-contrib/reflect-api.html

8:31 carkh: ahyes indeed !

8:32 * kumarshantanu thinks clojure.contrib should be aliased as c.c :-|

8:33 carkh: yes that would help tremendously

8:38 LauJensen: You guys should use emacs, fuzzy completions expands c.c to clojure.contrib

8:40 carkh: i do but fuzzy completion is not perfect for namespaces

8:40 maybe some setup problem

8:40 i walways end up with clojure.contrib.sql/<space>

8:43 kumarshantanu: ,(clojure.contrib.reflect/call-method java.lang.String :substring [] "hello" 3 4)

8:43 clojurebot: java.lang.ClassNotFoundException: clojure.contrib.reflect

8:45 kumarshantanu: I am still getting this error on my local REPL: java.lang.NoSuchMethodException: java.lang.String.substring()

8:46 carkh: the vector should have classes inside it

8:47 [java.lang.String java.lang.Integer java.lang.Integer] i guess

8:47 i think it's easier to use (clojure.lang.Reflector/invokeInstanceMethod instance method-name-as-string array-of-args)

8:48 jk_: are there any old-time common lispers here who resent the mixture of messy, stateful java into lisp? i've been really interested in the controversy and when most old-timers go with clojure, it seems like it's with a shrug like it's the lesser of 2 evils (using only java, for example)

8:48 probably a bad question in this forum :)

8:49 kumarshantanu: carkh: I am passing [Integer Integer] too, but the signature accepts primitives

8:49 not working....I guess that might be the reason

8:50 carkh: jk_: well common lisp is very imperative as well

8:51 kumarshantanu: really you should try c.l.reflector/invokeInstanceMethod, i had success using it

8:52 kumarshantanu: carkh: I will use Reflector, I was just wondering the clojure.contrib version may be better supported

8:52 carkh: kumarshantanu: clojure itself uses reflector so i guess it's here to stay =P

8:53 jk_: carkh: what about exceptions? does that seriously detract?

8:54 carkh: jk_: conditions sure are way better, but exceptions are good enough in most cases

8:54 and we have a library for condition-like behaviour

8:54 though i never used it

8:54 kumarshantanu: ,(clojure.lang.Reflector/invokeInstanceMethod "Hello World" "substring" (into-array [3 4]))

8:54 clojurebot: "l"

8:55 carkh: kumarshantanu: yay !

8:56 kumarshantanu: carkh: invokeInstanceMethod should be promoted to c.c (!)

8:56 jk_: carkh: ok, one last question... do you think seq is a big win over the predominance on cons cells? as a newcomer, that shift in focus looks like an advantage

8:56 carkh: yes i beleive so

8:57 most of the time you'll be working with vectors instead of lists

8:57 it's very handy to be able to use seq abstraction on these

8:57 and vector are _fast_

8:57 vectors*

8:58 jk_: thanks :)

8:58 carkh: also they grow at the end, so you can avoid most of this reverse non-sense

9:00 jk_: carkh: i was watching some online lectures where they are teaching with scheme and i was wondering if lispers thought something was lost or radically different with clojure because they always had such a strong link to the cons cell data structure before

9:00 carkh: well we still have cons cells

9:00 kinda

9:01 we have single linked lists anyways, for a cons cell we use a simple vector

9:01 but really i think it's a plus to have the right data structure for the right job

9:02 sure the jvm has its drawbacks, but it has many good features

9:03 and clojure is way above CL for functional purity (though not to the haskell level)

9:04 take CL's hash tables for instance

9:04 very imperative

9:05 we have fully immutable and persistent maps in clojure for that

9:11 pdk`: i recall some article once whining about clojure wasnt lisp all the way down and how evil this was cause it was on the jvm

9:11 though on the other hand

9:11 the same person who wrote that still thought his efforts to make a multi ghz lisp machine for today's world were remotely practical

9:11 carkh: there is strong opposition to clojure in the CL community

9:12 _fogus_: jk_: Common Lisp is not necessarily centered around the cons cell. It has a powerful sequence abstraction.

9:13 carkh: _fogus_: though the sequence abstraction doesn't go as far as in clojrue

9:13 _fogus_: carkh: I haven't noticed a very strong opposition at all.

9:13 jk_: pdk`: http://www.loper-os.org/?p=46 probably this guy :)

9:13 carkh: i guess it withered down with time, they're mostly ignoring clojure

9:13 pdk`: oh yeah i was just about to look for that jk

9:13 _fogus_: carkh: It's not as pervasive no. But the point is that the Common Lisp world does not revolve around the cons cell.

9:14 pdk`: but the tl;dr of it is it boiled down to whining from an ivory tower

9:14 carkh: _fogus_: anyways i can see their point, CL has been there for decades, clojure is but a blip on their radar

9:15 Bahman: Hi all!

9:16 jk_: pdk`: well i was reading through a lot of this blogs and i don't think it's really ivory tower whining. he's claiming that something truly valuable was lost when lisp machines went away because the same abstractions when all the way down giving crystal clarity to the whole structure (that's how i read it anyway, in a nutshell)

9:16 _fogus_: carkh: If you're a long-time Common Lisp programmer then you're probably happy with what you have. Plus, you've seen "other Lisps" come and go numerous times. ;-)

9:16 djpowell: where should i report a clojure-clr issue?

9:17 carkh: _fogus_: i never was fully happy with CL, the multi-processing issues (under windows) and the impertive nature of it were always a drawback

9:17 jk_: _fogus_: thanks for the input. i guess i was getting that feeling (re cons cell) from some of R.H.'s comments and from the SICP lectures i'm viewing

9:18 pdk`: are these lectures recent

9:18 _fogus_: jk_: Those SICP lectures are like 20 years old no?

9:18 jk_: pdk`: mid-80's i think

9:18 and it's scheme, not CL

9:20 _fogus_: That's not to say that cons cells are not used in CL, they are an incredibly robust structure. Only, that they are not used exclusively.

9:21 jk_: gotta go to work. thanks for the insightful comments, guys.

9:21 djpowell: ,(with-out-str (pprint {:a {:b "c"}}))

9:21 clojurebot: java.lang.Exception: Unable to resolve symbol: pprint in this context

9:21 djpowell: ,(with-out-str (clojure-version))

9:21 clojurebot: ""

9:21 djpowell: ,(clojure-version)

9:21 clojurebot: "1.2.0-master-SNAPSHOT"

9:22 carkh: ,(with-out-str (clojure.contrib.pprint/pprint {:a {:b "c"}}))

9:22 clojurebot: java.lang.RuntimeException: java.lang.RuntimeException: java.lang.RuntimeException: java.lang.ClassNotFoundException: clojure.contrib.pprint

9:22 carkh: =/

9:22 ,(require 'clojure.contrib.pprint)

9:22 clojurebot: java.io.FileNotFoundException: Could not locate clojure/contrib/pprint__init.class or clojure/contrib/pprint.clj on classpath:

9:22 djpowell: hmm, anyway pprint in clojure-clr totally mangles that expression

9:23 as: {:a "c"{:b }}

9:23 _fogus_: ,(with-out-str (clojure.pprint/pprint {:a {:b "c"}}))

9:23 clojurebot: "{:a {:b \"c\"}}\n"

9:26 carkh: ah i'm still with good old 1.1 =P

10:08 bmh: well this seems to be an energetic channel. Any penumbra users about, I'm trying to make sense of ztellman's marble vertex shader

10:22 cemerick: bmh: quiet just means work is getting done :-)

10:26 hircus: has anyone tried this snippet? http://gist.github.com/624638

10:26 I tried it with Clojure 1.2.0 on Linux x64 -- both JDK 1.6.0u22 from Sun and IcedTea from Fedora

10:27 and the Clojure REPL freezes at (defprotocol...) -- it returns nil but never prompts for the next command

10:36 _fogus_: hircus: Hrm. That'

10:36 s odd

10:37 hircus: Does it do that for every defprotocol ever?

10:39 cemerick: hircus: funky; works fine in both direct and ccw repls.

10:40 hircus: _fogus_:

10:41 _fogus_: I updated my comment in the gist. as it turns out it's just that the prompt is not printed after defprotocol. If I enter a simple expression (e.g. a number) then it's evaluated and the prompt is then printed

10:41 and it does not always happened -- I *sometimes* get the prompt back after defprotocol. odd eh

10:45 kryft: #(< -1 % size) <- Hmm, what does the % do?

10:46 MayDaniel_: ,(#(- 10 %) 15)

10:46 clojurebot: -5

10:47 kryft: MayDaniel_: Duh, of course :P

10:58 raek: kryft: #(< -1 % size) is the same as (fn [%] (< -1 % size))

11:00 kryft: raek: Yeah, thanks. :) I did remember that #() was literal syntax for anonymous functions, but for some reason I didn't remember (and couldn't figure out) that naturally % must be an argument for the function.

11:03 There are no stupid questions, but some days I manage to get pretty close!

11:05 bhenry: is there any utility that will tell you all the namespaces on the classpath in which a given function is called?

11:09 raek: bhenry: with emacs and swank-clojure, there is "C-c C-w c: List all callers of a given function"

11:10 bhenry: awesome!

11:12 raek i get error in process filter: Wrong type argument: char-or-string-p, nil

11:12 i'm leaving the argument as is after the command

11:15 _rata_: hi

11:16 dpritchett: does the newest vimclojure integrate with lein-nailgun?

11:17 I really want to like vimclojure but I haven't gotten used to classpaths... it's so nice to let leiningen deal with them for me.

11:19 _rata_: is there a function like tree-seq but for graphs? (i.e., the children function can give nodes already visited by the function)

11:21 jkkramer: _rata_: http://github.com/jkk/loom or clojure.contrib.graph

11:21 _rata_: clojure.contrib.graph doesn't have anything like that... I've already checked

11:22 jkkramer: lazy-walk does if you use ccg's graph structure

11:23 loom has loom.alg-generic/bf-traverse and others for general-purpose traversal

11:24 _rata_: to use a ccg's graph structure I'd need a function like the one I'm asking for

11:25 I have my own data structure and I want to walk over it

11:26 jkkramer: then loom would be a better fit. it's alpha though so the API isn't concrete

11:35 fliebel: Hey

11:35 jkkramer: _rata_: if you do end up using loom, i'm interested in any feedback

11:36 fliebel: chouser or _fogus_: You probably know this, but the index of Joy of Clojure(which I just bought) says 'firehos', missing the 'e'.

11:37 _rata_: jkkramer, I think my team wouldn't be happy to include another library dep, but I can see bf-traverse is self-contained, so I'd like to copy it right into my code... don't you mind?

11:39 dpritchett: firehoss

11:39 jkkramer: _rata_: sure, go for it. just pass along changes if you make any

11:40 _rata_: ok... I think that lazy-seq should go at the beginning of the step function

11:41 jkkramer: my reasoning for not is that the first node is always available in the queue

11:41 and subsequent nodes require some work to find

11:43 but i'm not an expert in the subtleties of lazy-seq

11:44 _rata_: I think it's preferable to have a complete lazy seq than a seq that's mixed

11:45 jkkramer: opinions from the #clojure sages? is the form (cons x (lazy-seq ...)) discouraged?

11:46 Chousuke: why would it be?

11:46 _rata_: also I've always seen (lazy-seq (cons x ...)) in the functions returning lazy seqs

11:46 Chousuke: well the latter is lazier

11:48 If you do (defn foo [] (cons 1 (lazy-seq (foo)))) and call it it realizes the first element immediately.

11:49 jkkramer: right. when you have the first element in-hand that's not bad, is it?

11:49 Chousuke: Well, the recommendation is to make sequences as lazy as possible

11:50 jkkramer: if you did (member:defn foo [] (lazy-seq (cons 1 (foo)))) and (foo) takes some time to process, the first element would take longer to return

11:50 KirinDave: Because of chunking, right? It's already going to do sequences in blocks.

11:50 jkkramer: oops, scratch "member:"...colloquey weirdness

11:51 Chousuke: KirinDave: Chunking doesn't really matter here.

11:51 KirinDave: Chousuke: Right, but realizing the first several elements probably doesn't offer efficiency gains unless they're terribly expensive.

11:52 jkkramer: in the case of a graph traversal, finding neighbors not yet visited could be a less-than-fast task

11:54 and you'd be doing work for a step one farther than the consumer asked for

11:55 _rata_: I don't think so

11:57 every function that returns a lazy-seq I've seen use the lazy-seq macro at the beginning of the function and they don't realize more elements than the ones asked for (except for chunking)

11:57 Chousuke: That's what we're saying

11:57 jkkramer: taking pre-traverse as an example: http://github.com/jkk/loom/blob/master/src/loom/alg_generic.clj#L30 if you request the one item, no work is done -- the start node is returned. if lazy-seq was moved before cons, it would find the neighbors of the starting node but still only return the starting node. right? i fully acknowledge i mgiht be misunderstanding lazy-seq

11:59 _rata_: what's the difference between pre-traverse and bf-traverse? just DFS vs BFS?

11:59 jkkramer: yes. pre-traverse is preorder

11:59 and bfs right now has more options for filtering neighbors, depth, etc

12:00 still messing with the API

12:00 _rata_: ok

12:00 why preorder = DFS?

12:01 it'd be more consistent to call it df-traverse

12:01 jkkramer: because dfs can be preorder or postorder

12:03 _rata_: ah ok

12:08 dpritchett: Does anyone know how to use the vimclojure/server jar on clojars? Meikel suggests there should be a `lein run` task to start it up but that doesn't seem to be the case.

12:08 (http://groups.google.com/group/vimclojure/browse_thread/thread/69abeea9f57cb73b)

12:11 _rata_: jkkramer, I've tried both versions of pre-traverse, your and the one with lazy-seq at the beginning, and the later is faster when I (take 1 ...)

12:12 jkkramer: _rata_: how are you benchmarking?

12:12 _rata_: nothing serious, just (time ...) a couple of times

12:13 maybe the graph I'm giving to the function is too small

12:14 I'm calling it like (take 1 (pre-traverse {:a [:b :c], :b [:c], :c []} :a))

12:21 jkkramer: (dotimes [_ 10] (time (doall (take 1 (pre-traverse {:a [:b :c], :b [:c], :c []} :a))))) is consistently faster for me with my version -- note the doall to realize the first element

12:23 also, (dotimes [_ 10] (time (doall (take 1 (pre-traverse #(do (Thread/sleep 100) ({:a [:b :c], :b [:c], :c []} %)) :a))))) demonstrates when the 'neighbors' function takes a long time to execute. with lazy-seq before cons, requesting the first element does the work for the second element

12:25 _rata_: ^

12:25 dpritchett: woo, i figured it out!

12:25 rhickey: -XX:MaxInlineSize=100 seems to help Clojure perf a good bit

12:25 interested in feedback from others if it helps you

12:25 dpritchett: add the vimclojure/server jar to lein's dev dependencies

12:26 then start the server with a quick alias including lein classpath

12:26 alias nailgun='java -cp "`lein classpath`" vimclojure.nailgun.NGServer'

12:27 _rata_: jkkramer, ok

12:28 but normally no one will ask for just the first element... they already have that element

12:29 jkkramer: _rata_: it applies to any node. with lazy-seq before cons, work is done for nodes subsequent to the one requested

12:30 _rata_: that's weird... it should be lazier, but it's the other way around then?

12:32 jkkramer: basically it's lazy for the nodes that require work to find

12:33 if there's a better way to do arbitrary-sized lazy graph traversal pre/post/bf, i'm very interested to know

12:35 lazy-walk from clojure.contrib.graph, which uses concat, dies on 100,000+ node graphs

12:35 _rata_: I've tried it and you're completely right... putting lazy-seq before cons realizes always one more than needed

14:00 fliebel: I'm reading Joy of Clojure, and in some of the examples some collections from java.util are used instead of clojure.lang. Why is this and what are the differences?

14:00 d0m_: fliebel: The goal is to be able to use both depending of when you need them

14:01 nishant: test message

14:02 fliebel: d0m_: I see… But what are the differences? Why might you prefer one over the other?

14:03 d0m_: Well suppose you need to call a method on an existing Java object, but what you have available right now is a clojure list

14:03 You can call directly the java method with the clojure list.. without conversion

14:04 nishant: hey everyone, I'm new to clojure, I've a question about java interop. I am trying to create an object of a java class using the (new Class args) form, but I get an InvocationTargetException, even after fully qualifying the name of the class, any ideas? I also verified that the constructor is visible using the show function available in repl-utils. Please help!

14:05 d0m_: fliebel: The list in clojure and in java are different implementations, even if they share some interfaces. So, if you're coding only in clojure, you can use only the clojure one if you like.. but then, if you have to use some java methods, it's nice to be able to convert java list to clojure list.

14:06 fliebel: Right :)

14:06 d0m_: so because of the interface they share, you can use java implementation of list in your high level function in clojure

14:06 that's awesome :)

14:07 hiredman: ping?

14:07 clojurebot: PONG!

14:10 raek: nishant: can you paste the full stack trace somewhere?

14:11 also, which class do you try to instanciate

14:11 nishant: @raek should I paste it here?

14:12 @raek it's a class that I wrote and I'm importing it through lein

14:12 raek: nishant: put it in gist.github.com and paste the link here

14:12 nishant: you can check whether clojure can find the class by just trying to evaluate the class name

14:12 ,java.util.ArrayList

14:12 clojurebot: java.util.ArrayList

14:13 nishant: yeah it can find the class

14:13 raek: ,java.util.Something

14:13 clojurebot: java.lang.ClassNotFoundException: java.util.Something

14:13 raek: great

14:13 nishant: okay here's the stack trace git://gist.github.com/626696.git

14:14 raek: ok, I tried http://gist.github.com/626696

14:14 (you pasted the git url)

14:14 nishant: oops

14:14 raek: hrm, looks like it can't figure out the constructor in some way

14:15 ,(java.util.ArrayList.)

14:15 clojurebot: #<ArrayList []>

14:15 raek: ,(java.util.ArrayList. "foo" "bar")

14:15 clojurebot: java.lang.IllegalArgumentException: No matching ctor found for class java.util.ArrayList

14:15 raek: hrm, but it's not that exception..

14:16 nishant: if you press 1 in the exception buffer (goes to the cause) what do you get?

14:16 my current theory is that the constructor throws an exception

14:16 nishant: I get No message [Thrown class.java.NullPointerException]

14:17 umm, let me try to see if I can use the constructor in Java

14:17 raek: nishant: does the class have multiple constructors that take the same number of arguments

14:17 ?

14:17 nishant: @raek yeah the same number, but different types

14:18 raek: what types?

14:19 nishant: well there are two that take 1 argument, one of them takes a string, and the other one takes a JSON object (it's a java JSON implementation)

14:19 _rata_: why can't I use ^ instead of (meta ...) in a place that meta has no problems? like in ^(:a b)

14:19 isn't ^ just a reader macro?

14:20 raek: _rata_: ^ as a shortcut for 'meta' is deprecated

14:20 it worked up to 1.1

14:20 _rata_: raek, really??

14:20 and what's ^ for now?

14:20 raek: in 1.2 ^ is the new #^

14:20 so, use the more verbose (meta ...) for getting the metadata

14:21 and since 1.2, you can use ^ to attach metadata and type hints

14:21 _rata_: mmmm... I don't get it yet

14:21 raek: ,(meta ^{:a 1} :foo)

14:21 clojurebot: Metadata can only be applied to IMetas

14:22 _rata_: is there no shortcut for (meta ...) then?

14:22 raek: _rata_: not anymore...

14:22 _rata_: :(

14:22 raek: attaching meta is probably much more common

14:22 nishant: @raek the ctor works from Java

14:23 raek: nishant: can you post the stack trace of the cause?

14:23 _rata_: than retrieving it?? how can that be? everytime you attach metadata there will be one or more times you get it

14:24 nishant: @raek http://gist.github.com/626720

14:25 raek: _rata_: a very common usage is type hints for the compiler

14:25 which only the compiler looks at

14:26 _rata_: anyway, ^ (or #^ in 1.1) only works for literals

14:26 if you have some data *in* your program that you want to attach metadata to, you must use with-meta

14:26 _rata_: mmmmm... so metadata isn't used that much.... that's a pity

14:27 yeah, I'm using with-meta

14:27 but the (meta ...) thing is annoying... with ^ the code would be much clearer

14:27 raek: when interfacing with clojure.core, you more often declare it than use it yes...

14:28 ,(meta (with-meta [1 2 3] {:a 1}))

14:28 clojurebot: {:a 1}

14:28 _rata_: the old shortcut could have been replaced by another one

14:30 and one that could be used everywhere, not just with literals

14:31 raek: meta is the "opposite" of with-meta

14:31 nishant: is com.complabs.Annotators.EntityAnnotator the class you try to make an instance of?

14:31 nishant: yeah

14:32 _rata_: so (:changed? (meta (:volume c))) could be written as (:changed? &(:volume c)) or something similar... the later is much more readable I think, no boilerplate

14:35 nishant: ping

14:35 KirinDave: Okay, something that's been bugging me...

14:36 Due ot profound mental deficiency, I don't know how to (require ...) a single namespace with an as without nesting. Is it possible?

14:36 I want to say (require '([clothesline.service :as service]))

14:36 Obviously that doesn't work.

14:36 and I know I could say (require '([clothesline [service :as service]]))

14:37 raek: nishant: is com.complabs.Annotators.EntityAnnotator the class you try to make an instance of?

14:37 nishant: @raek yes

14:37 raek: KirinDave: (require '[clothesline.service :as service])

14:38 KirinDave: raek: Oh weird.

14:38 raek: the extra parens introduce a "prefix list"

14:38 KirinDave: raek: I thought require just wanted seqs.

14:38 But I guess lists vs vectors actually matter?

14:38 raek: KirinDave: it is recommended to use vectors and lists as they are used at clojure.org/libs

14:39 other variants might work, but those are not documented

14:39 and could be an implementation detail

14:39 the general syntax is:

14:39 foo.a

14:39 [foo.a ... options ...]

14:40 foo.a foo.b foo.c --> (foo a b c)

14:40 or combinded:

14:40 KirinDave: raek: Thanks. I didn't realize the type was significant.

14:40 raek: [foo.a ..opts..] [foo.b ..opts..] [foo.c ..opts..] --> (foo [a ..opts..] [b ..opts..] [c ..opts..])

14:40 KirinDave: raek: (btw notice I was saying (require ...) not (:require ...)

14:41 raek: I write the way recommended by libs in ns statements because it looks good and some things parse it

14:41 But it felt strange to do it in an actual require statement. I should get over it.

14:41 raek: the only difference between require and :require in a ns, is that the former requires you to quote the form

14:41 (foo) is actually the degenerate case of the prefix list

14:41 meaning, require *nothing* with the prefix foo

14:42 how ever, a vector in that position simply means "no options"

14:42 nishant: raek: Yes I am trying to instantiate the EntityAnnotator class

14:43 raek: I think that is about the only case where vectors and lists are treated differently in the current implementation

14:43 nishant: what do you pass to the constructor?

14:43 jarpiain: nishant: do you use the internal class name com.complabs.Annotators$EntityAnnotator ?

14:43 raek: is there any docs for the clas online?

14:43 nishant: raek: a string

14:44 raek: no there are no docs

14:44 raek: what jarpiain said looks interesting

14:44 nishant: raek: the constructor I'm trying to invoke takes a string, I tried creating an object through java code using the same ctor, and it works

14:45 jarplain: no I haven't tried that

14:45 :jarplain I get a ClassNotFound when I try that

14:46 raek: I think I am out of ideas...

14:47 but maybe one could type hint the param

14:47 (fn [^String s] (com.complabs.Annotators$EntityAnnotator. s))

14:47 nishant: have you tried passing a literal string or something?

14:48 what value does the calling code pass?

14:50 nishant: I am getting a slightly different behavior when I pass a literal string (the string is supposed to be a file path)

14:50 raek: the same exception?

14:51 nishant: the same exception, but when I try to debug the cause I get a filenotfound exception

14:52 raek: nishant: can you double-check that the code you used previously used to generate the string doesn't give nil?

14:53 nishant: raek : I've hardcoded the string for testing

14:55 raek: so there is a difference whether the string is a literal or not?

14:56 if so, could you try it with the type hint code I wrote before?

14:57 nishant: raek: yeah let me try that

14:59 raek: the behavior is same for literals and variables

15:00 raek: and if the file whose path is in the string exists, you get NullPointerException, otherwise FileNotFoundException?

15:01 nishant: raek: yes, it's weird

15:01 raek: should the file contain some data in a specific format?

15:02 nishant: raek: the file contains a json formatted string

15:03 raek: I think clojure finds the correct contsructor, since you get a FileNotFoundException

15:04 it seems unlikely that it tries to open a file using a JSON object (or whatever the other type was)

15:05 nishant: yeah, I think it's calling the right ctor

15:05 LauJensen: /whois nishant

15:06 nishant: You're not the guy who used to write a ton of C# tutorials on codeproject are you?

15:06 nishant: LauJensen: no :)

15:06 LauJensen: ok :(

15:07 hiredman: ,(* 16 3)

15:07 clojurebot: 48

15:08 nishant: :raek I just noticed that there might be multiple jars which contain this class, you think that could result in this behavior?

15:09 raek: possibly

15:09 I don't know, but I guess that could be worth investigating

15:09 it can cause weird things, for sure

15:10 nishant: okay let me try that, thanks for your help!

15:18 raek: the jar was old :)

15:18 sorry for wasting your time

15:24 raek: nishant: no worries :)

15:25 nishant: thanks

15:49 _rata_: if I have a map from objects to their weights, how do I randomly choose one of those objects based on the given distribution? is make-distribution from clojure.contrib.probabilities.finite-distributions the best way?

15:56 why are there two math libs in clojure.contrib?

16:15 amalloy: _rata_: finite-distributions, as far as i can tell, defines a way to create pdfs, but not a way to select from them, so there must be some other lib that uses them

16:16 if you

16:16 re interested, http://rosettacode.org/wiki/Probabilistic_choice#Clojure is an implementation of what you're doing from scratch

16:17 _rata_: can't I use the monad that make-distribution returns directly? (I don't know anything about monads... any reference to understand them would be appreciated :) )

16:17 amalloy: i don't either :P

16:18 raek: _rata_: rhickey's ants.clj example contains the 'wrand' function, which seems to do something similat to what you are trying to obtain: http://raek.se/ants.clj

16:21 _rata_: raek, oh thanks. that's something very similar to what I'm looking for

16:22 "=" for refs is the same as "identical?"?

16:25 amalloy: ,(let [[a b :as c] (repeatedly (atom 0))] (map (juxt = identical?) c))

16:25 clojurebot: java.lang.RuntimeException: java.lang.ClassCastException: clojure.lang.Atom cannot be cast to clojure.lang.IFn

16:25 amalloy: ,(let [[a b :as c] (repeatedly #(atom 0))] (map (juxt = identical?) c))

16:25 clojurebot: java.lang.IllegalArgumentException: Wrong number of args (1) passed to: core$identical-QMARK-

16:25 amalloy: bleh

16:26 ,(let [[a b] (repeatedly #(atom 0))] ((juxt = identical?) a b))

16:26 clojurebot: [false false]

16:27 _rata_: ,(for [a (repeatedly 5 #(atom 0))] (map (juxt = identical?) a))

16:27 clojurebot: java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Atom

16:27 amalloy: _rata_: looks like yes

16:27 _rata_: ,(for [a (repeatedly 5 #(atom 0))] ((juxt = identical?) a))

16:27 clojurebot: java.lang.IllegalArgumentException: Wrong number of args (1) passed to: core$identical-QMARK-

16:28 amalloy: _rata_: you can't possibly do it with just a for. only one a is in scope at a time

16:28 _rata_: mmm ok

16:29 amalloy: but since 0 is identical to 0, and two refs to it are neither equal nor identical, it looks like equal and identical are the same for refs

16:29 _rata_: but anybody knows if that result is an implementation detail or I can relay on that behaviour?

16:30 raek: _rata_: for clojure types, = means value equality for immutables and indentity equality for mutable things (atoms/refs/agents/vars, etcs)

16:30 _rata_: ah ok :)

16:30 raek: ,(= [1 2 3] '(1 2 3))

16:30 clojurebot: true

16:30 _rata_: thank you amalloy and raek

16:40 ztellman: bmh: still have questions about penumbra?

16:41 BufferUnderpants: Hi

16:42 I'm trying to use the ZK web framework from within Clojure and I'm having trouble with a proxy class.

16:43 nishant: does repl-utils/source not work on functions I define in the user namespace?

16:44 BufferUnderpants: The method I'm invoking receives an instance of an instance of an interface, very much like Swing.

16:44 raek: nishant: no, but their definitions needs to be loaded through a require

16:44 or C-c C-k in emacs

16:45 if you load then in the repl or with C-x C-e or C-M-x file and line metadata is not stored for them

16:45 amalloy: oh neat, raek, i didn't realize source worked for C-c C-k. i just knew it didn't work if you put them into the repl so i never tried

16:47 nishant: raek:thanks

16:48 colinsteele: hey folks how do I turn a string into a java.io.Reader or a java.io.InputStream??

16:48 <---- java noob, pardon my cluelessness :)

16:50 lpetit: ,(java.io.StringReader. "a string")

16:50 clojurebot: #<StringReader java.io.StringReader@6d9e14>

16:50 lpetit: colinstee: ^^

16:50 colinsteele: ahhhh

16:50 voila, thanks

17:07 hsuh: hello folks... i wrote this (http://pastie.org/1221883) and thought it was too slow, what am i doing wrong ?

17:09 Chousuke: hsuh: 7ms per database connection & query doesn't sound too bad.

17:09 well, 8ms

17:10 hsuh: it opens a new connection to the database for every query, you hopefully won't be doing that in production code.

17:11 arkh: how do I :use namespaces from multiple files (of my own making)?

17:11 hsuh: Chousuke: not anymore... so what should i be doing ? (RTFM is a valid answer)

17:12 Chousuke: hsuh: I think you'll want to open a connection and use that for all your queries. (You'll have to read the docs to find out how, though)

17:13 raek: arkh: other than (ns my.ns.one (:use the-ns)) (ns my.ns.two (:use the-ns)) etc, for each file that wants to use it?

17:14 Chousuke: it's a good habit to avoid :use though

17:14 arete: hsuh: you'll want to use a connection pooling ds and the :ds option for clojure.contrib.sql

17:14 Chousuke: at least without :only

17:14 arete: http://jdbc.postgresql.org/documentation/publicapi/org/postgresql/ds/PGConnectionPoolDataSource.html

17:14 arkh: raek: how do namespaces work with the class path? i.e., how does clojure know where to find namespaces in the files I make / want to load

17:14 raek: (I interpreted your question as that you wanted to use "the-ns" from "my.ns.one" and "my.ns.to"

17:14 hsuh: arete: tks

17:15 raek: arkh: yes. (ns foo.bar.some-thing ...) corresponds to foo/bar/some_thing.clj

17:15 arkh: raek: cool - that's what I didn't know. Thank you

17:15 raek: where the foo/ directory should be in a directory on the class path (presumably src/)

17:15 arete: hsuh: actually there's an even better example here: http://en.wikibooks.org/wiki/Clojure_Programming/Examples/JDBC_Examples

17:15 dpritchett: how long has leiningen had the "lein classpath" task anyway?

17:15 raek: note that hyphens in namespace names correspond to underscores in file names

17:16 arkh: k

17:16 hsuh: arete: otoh the datasource - postgresql example there says "Note that this is not recommended for production. Use c3p0 or similar instead."

17:17 bmh: ztellman: missed you message an hour back. Can pixel shaders be written in java/clojure or am I tied into using C/C++?

17:17 ztellman: bmh: pixel shaders have to be written in GLSL, which is a C-99 derivative

17:18 arete: yeah dunno why it says that, perhaps there are/were issues with the connection pooling

17:18 ztellman: but there's a Clojure DSL that offers some of the same functionality

17:18 under the covers, it just translates into GLSL

17:18 bmh: ztellman: hrm. Do you know a good simplex noise/fBM implementation?

17:19 I'm playing around with some algorithmic terrain stuff and figured I could try generating everything in the pixel shader

17:19 ztellman: bmh: you were looking at the marble program, right?

17:19 that uses perlin nosie

17:19 bmh: ztellman: I saw. Perlin fBM. Perlin has dimensionality issues, though

17:19 hsuh: arete: there is also http://github.com/briancarper/postgres-pool

17:20 ztellman: bmh: well, it's generally difficult to use pre-existing GLSL code

17:21 perlin noise is pretty friendly to the hardware

17:21 I'm not sure about simplex noise, but it shouldn't be too hard to create your own version

17:22 bmh: ztellman: Have you read any of the papers analyzing Perlin? It actually has some terrible characteristics

17:23 ztellman: bmh: I haven't, but I'm really not an expert

17:23 bmh: For example, the hash function that Perlin used is highly correlated

17:24 If I was an expert I wouldn't be lurking on irc picking the brains of people more in the know than I ;-)

17:24 ztellman: ha, well I don't think the difference between terrains generated by perlin noise and simplex noise are all that obvious

17:25 but if you want to pursue another fractal generator and need any pointers on using Penumbra, I'm available

17:26 bmh: Thanks. Have you ever looked at turbulence? It works by perturbing you x,y,z coordinates with... wait for it... coherent noise

17:26 edoloughlin: Hi, I'm trying to remove nil values from a map (I'm new to Clojure). I'm using

17:26 (def record {:a 1 :b 2 :c nil})

17:26 (merge (for [[k v] record :when (not (nil? v))] {k v})

17:26 but this gives:

17:26 ({:a 1} {:b 2})

17:26 Whereas I would like:

17:26 ztellman: bmh: I haven't but that seems very GPU friendly

17:26 edoloughlin: {:a 1, :b 2}

17:27 bmh: edoloughlin: why don't you use remove

17:27 edoloughlin: Wow. Thanks. Will look it up!

17:27 bmh: (remove (fn [k v] (nil? v)) collection)

17:27 http://clojure.github.com/clojure/clojure.core-api.html#clojure.core/remove

17:27 edoloughlin: Thanks.

17:28 bmh: rich & co. did a great job of getting all the functional stuff right.

17:28 dpritchett: what's the latest in clojure on AppEngine hand-holding libs?

17:28 raek: ,(apply merge (for [[k v] {:a 1, :b 2, :c nil} :when (not (nil? v))] {k v}))

17:28 clojurebot: {:b 2, :a 1}

17:28 raek: (into {} (for [[k v] {:a 1, :b 2, :c nil} :when (not (nil? v))] [k v]))

17:29 dnolen: ,(into {} (remove (fn [[k v]] (nil? v)) {:a 1 :b 2 :c nil}))

17:29 clojurebot: {:a 1, :b 2}

17:29 bmh: ztellman: Is there any reading you could suggest for GPU programming? I'm a bioinformatician by trade, so graphics is a big, magical world to me

17:29 ztellman: bmh: I haven't found a good conceptual book yet

17:30 bmh: but the orange GLSL guide isn't all that bad as a reference

17:30 edoloughlin: Thanks everyone.

17:30 ordnungswidrig: is there something like zip for multiple seqs? [[1 2 3] [:a :b :c] ["!" "§" "$"]] -> [[1 :a "!"] [2 :b "§"] [3 :c "$"]]

17:31 raek: ,(map vector [1 2 3] [:a :b :c] ["!" "§" "$"])

17:31 clojurebot: ([1 :a "!"] [2 :b "§"] [3 :c "$"])

17:32 raek: map hase the useful property of "taking one thing from each seq"

17:32 bmh: raek: I had an interview earlier this week. I solved one of the problems they gave me with a few applications of map, filter, and reduce.

17:33 We spent the remainder of the interview discussing the finer points of roguelikes...

17:34 ordnungswidrig: ah, cool, I didn't know this one.

17:34 ,(doc map)

17:34 clojurebot: "([f coll] [f c1 c2] [f c1 c2 c3] [f c1 c2 c3 & colls]); Returns a lazy sequence consisting of the result of applying f to the set of first items of each coll, followed by applying f to the set of second items in each coll, until any one of the colls is exhausted. Any remaining items in other colls are ignored. Function f should accept number-of-colls arguments."

17:35 ordnungswidrig: ,(map vector [1 2] [:a :b :c])

17:35 clojurebot: ([1 :a] [2 :b])

17:36 hsuh: arete: 10x improvement with postgres-pool

17:37 ztellman: bmh: I'm heading out, but hit me up on the penumbra mailing list with any questions you have

17:38 bmh: ztellman: thanks. I'll subscribe.

17:39 arete: hsuh: sounds speedy

17:44 _rata_: has anybody problems with the debugger of swank-clojure and clojure 1.3?

17:45 lancepantz: so i was just playing around with tuning my jvm a little

17:45 i took 100m off of my Xmx, which dropped my virtual memory usage by 160m

17:46 anyone have any ideas where the extra 60 is coming from?

17:50 amalloy: lancepantz: what was your Xmx to begin with?

17:51 lancepantz: took it from 500 down to 400 in this case

17:52 amalloy: my guess, at any rate, would be some magic mumbo-jumbo to do with powers of two

17:52 _rata_: has anybody experienced problems with the debugger of swank-clojure and clojure 1.3?

17:58 nishant: does clojure have something like for-each?

17:58 bold question

17:59 AWizzArd: map, doseq, for

17:59 ,(map inc [10 20 30])

17:59 clojurebot: (11 21 31)

17:59 nishant: okay, I was looking for something that only side effects

17:59 AWizzArd: ,(doseq [n [10 20]] (println n))

17:59 clojurebot: 10 20

18:01 kmc: heh, clojurebot captures output?

18:05 nishant: thanks!

18:08 gfrlog: is there a faster way to create a map from a list of pairs aside from (apply hash-map (reduce concat pairs))?

18:08 dnolen: gfrlog: into is your friend

18:09 ,(into {} [[1 2] [3 4]])

18:09 clojurebot: {1 2, 3 4}

18:09 gfrlog: ,(into {} [[1 2] [3 4]])

18:09 clojurebot: {1 2, 3 4}

18:09 gfrlog: awesome, thanks

18:11 kmc: ,(doc into)

18:11 clojurebot: "([to from]); Returns a new coll consisting of to-coll with all of the items of from-coll conjoined."

18:11 kmc: ,(into [1 2] [3 4])

18:11 clojurebot: [1 2 3 4]

18:12 kmc: ,(conj [1 2] 3)

18:12 clojurebot: [1 2 3]

18:13 gfrlog: (into #{} {:a 2 :c 5})

18:13 ,(into #{} {:a 2 :c 5})

18:13 clojurebot: #{[:a 2] [:c 5]}

18:19 gfrlog: ,(defrecord Tom [jill tim])

18:19 clojurebot: DENIED

18:23 gfrlog: hmm. I do a (defrecord Graph [order edges]) in a certain namespace, (use) that namespace from the repl, but then Graph doesn't resolve

18:25 KirinDave: So

18:25 Chousuke: gfrlog: you need to import records

18:25 gfrlog: they become classes

18:25 gfrlog: oooh

18:26 very good

18:26 KirinDave: It's not possible to use the extend+merge technique to simulate inheritance with (reify ...), unless you want to use a macro and promise compile-time support. Right?

18:27 With (extend ...) you can merge two maps together

18:28 But extend requires a specific type to extend.

18:28 If you want anonymous types to fit a protocol, you have to have the entire proposition be static, right?

18:28 (unless, of course, you want to eval a form)

18:28 There's no way to provide default/inherited behavior to reified objects.

18:29 Chousuke: I suppose you could use reflection but it'd be fragile

18:30 KirinDave: Chousuke: I mean, a macro is easy enough to turn {:name (fn...) ...} into a '(name (fn...))

18:30 Chousuke: But...

18:30 That's purely static.

18:37 AWizzArd: How can I declare a deftype field as :unsynchronized-mutable and ^int at the same time?

18:43 _rata_: I don't get what make-distribution does

19:03 gfrlog: does (first #{2 3 4}) require the axiom of choice?

19:04 amalloy: AWizzArd: i think it looks something like this: (deftype a [^{:volatile-mutable true :tag int} h])

19:05 that creates for me an A class, with a 1-arg int constructor. i'm not sure if it's mutable since i don't do deftypes very often, but it seems like if the tag works the mutability probly does too

19:07 AWizzArd: I will try that, thanks for the idea

19:15 gfrlog: ,#{4 4 5}

19:15 clojurebot: Duplicate key: 4

19:19 jashmenn: hey, im wondering if someone can help me figure out a macro problem: https://gist.github.com/fdd8b7b902b1ab8170f7

19:20 i realize that macros don't evaluate their operands

19:20 but i'm wondering how i can evaluate them if i want to

19:21 gfrlog: jashmenn: I think you can only set them up to be evaluated

19:22 it looks like you're trying to call the function twice?

19:22 jashmenn: i want to use the var x as an argument to defining the output of the macro

19:22 jweiss: anyone know how to switch slime from clojure back to lisp? when i run slime it tries to load clojure

19:23 or better yet, be able run either one :)

19:23 technomancy: jweiss: getting rid of swank-clojure should help

19:23 gfrlog: jashmenn: could you make foo a function? maybe one that calls another macro?

19:24 technomancy: I don't use CL myself though, I could use some help making swank more Cl-frinedly

19:24 jweiss: technomancy: so once swank-clojure is installed, it assumes you're only using clojure as inferior-lisp?

19:24 dnolen: jashmeen: there are two hidden params handed to macros &env and &form

19:24 jweiss: i don't know CL much myself. i learned a bit briefly before finding clojure.

19:24 technomancy: jweiss: maybe? getting rid of swank-clojure.el is a good idea even if you don't use CL. it's just got some heinous hacks that were necessary when lein didn't exist, but don't make sense any more.

19:25 it just complicates things

19:25 jashmenn: dnolen: this sounds interesting. let me look that up

19:25 jweiss: technomancy: so it is not necessary to run lein swank, and then slime-connect?

19:25 it meaning swank-clojure.el

19:25 technomancy: correct

19:26 jweiss: excellent, that's most likely the problem then, i set up clojure dev here before lein came along (or maybe just before i discovered it)

19:27 technomancy: i have swank-clojure and clojure-mode elpa packages - do i need those?

19:28 technomancy: just clojure-mode and slime-repl

19:28 jashmenn: dnolen: okay, so i've got &env and it shows the LocalBinding. now im not exactly sure how to safely get the value of `g` out of it

19:29 dnolen: jashmenn: ah sorry you led you astray, &env is just so you can the surrounding context from w/in a macro

19:29 jashmenn: dnolen: ah okay

19:30 dnolen: jashmenn: the only way to get at the value of something is eval, but what exactly are you trying to do?

19:31 jashmenn: dnolen: i want to pass an argument into a macro and use the value of it (unquoted) to help build the sexp within the macro

19:33 but, like gfrlog was saying, i think i need to just set it up to be evaluated, not evaluate it early

19:35 gfrlog: jashmenn: can you use eval?

19:35 dnolen: jashmenn: curious as to the end goal, why do you need the actual value of a literal to influence the macro expansion?

19:36 jashmenn: sometimes it is indeed useful to eval in a macro, but usually unnecessary.

19:36 gfrlog: I've never done it

19:37 dnolen: I've only needed once, because I was using the contents of files on disk to generate code.

19:41 amalloy: jashmenn: why is the value being passed in a variable instead of a literal? (not just asking to tell you you're wrong; i think you can probably make this happen)

19:49 rplevy: using clojure contrib 1.1.0, I am trying out contrib.condition. it doesn't do quite what I would expect. it certainly responds to the raised condition as specified but the exception goes uncaught delivering the message in tomcat. what I need it to do and what I think the semantics of it is, is for handler-case to be like try and for handle to be like catch in the sense that I can do something with the result. Am I doing it wrong or was it jus

19:50 technomancy: rplevy: support for catching regular exceptions in handler-case just got committed last week IIRC

19:50 might be able to backport it to 1.1, but it might be tricky; easier to just upgrade to 1.3 =)

19:53 jashmenn: dnolen: well when i try to eval it says "can't eval a local"

19:53 dnolen: jashmenn: heh, yeah I forgot about that.

19:53 jashmenn: amalloy: right, if i pass in the value as a literal it works fine

19:53 but, obviously this is just extracted from a much larger macro

19:53 and `x` in this case "has to" be a variable

19:54 i don't mind passing it in as a literal in the `let` if you have advice on the best way to do that

19:55 amalloy: is this a macro embedded within another macro?

19:55 or called from another, whatever

19:55 jashmenn: amalloy: yes

19:55 amalloy: okay. usually you don't need to do that

19:56 write your inner macro as a *function*, not a macro

19:56 jashmenn: but what if i need both inner and outer to do list destructuring like ~@body ?

19:57 amalloy: eg (defn foo [x] `(prn ~x))

19:57 backtick is legal in functions too; the only special thing about macros is that their arguments aren't evaluated

19:57 jashmenn: i didnt think that was possible with just a plain defn but i guess im wrong

19:57 hmmm

19:58 ah ha

19:58 okay

19:58 thanks

19:58 amalloy: ,(let [x (fn [] `(prn 1))] (x))

19:58 clojurebot: (clojure.core/prn 1)

19:59 jashmenn: okay, this is very helpful. thanks amalloy (and everyone else)

19:59 amalloy: welcome jashmenn

19:59 this is a macro "trick" that is widely applicable: don't use macros :)

20:06 tomoj: haha

20:08 kmc: i see a few libraries for continuations in Clojure, implemented by performing a continuation-passing-style transform

20:08 but it seems to me that CPS is fatally limited without TCO

20:08 is this a problem for using continuations in Clojure, or do they manage to insert trampolines cleverly to get TCO?

20:11 tomoj: kmc: http://intensivesystems.net/tutorials/cont_m.html

20:12 does it look like that approach is limited by lack of TCO?

20:15 kmc: yes

20:15 most of those functions end in a tail call

20:15 in CPS you replace "return to parent, which does something else" with "tail-call a continuation"

20:15 this is going to use more stack, unless you have TCO

20:16 however i bet that some clever CPS macros for Clojure could replace calls with returns and use trampoline

20:16 which is what i was asking about

20:17 amalloy: You know we have trampoline, right?

20:18 kmc: yeah i mentioned it twice

20:18 amalloy: Haha, just checking that you didn't mean to implement it first

20:19 tomoj: would you just have to add a trampoline at every tail call site?

20:19 amalloy: On my mobile atm, apologies if I miss some context

20:20 kmc: tomoj, i'm not really sure

20:20 tomoj: I don't understand CPS yet :(

20:20 kmc: other languages implemented on systems without TCO sometimes wrap the whole program in one trampoline

20:20 and my understanding is that Clojure could have done this to get transparent TCO

20:20 but it would slow down everything

20:20 tomoj: ah, right

20:22 kmc: tomoj, in CPS every function takes an extra argument (the continuation) and, instead of returning, calls that

20:22 so (fn [x] (+ x 2)) becomes (fn [x k] (k (+ x 2)))

20:22 except that in a full CPS transform, we'd CPS-transform (+) too, and eliminate every non-tail call

20:23 (fn [x k] (+ x 2 k))

20:24 and (fn [x] (* (+ x 2) 3)) becomes (fn [x k] (+ x 2 #(* % 3 k))) or some such

20:27 and if you carry this to its conclusion, your big nested expressions get unfolded to a linear sequence of small steps

20:27 which is why CPS transform is useful as a stage in a compiler

20:28 and indeed is close to the SSA form used in lots of compilers for languages not traditionally called "functional"

20:29 tomoj: kmc: actually, doesn't the article there explain it?

20:29 search for "But why?"

20:29 kmc: yeah

20:29 that's kind of orthogonal to what i said above

20:30 tomoj: oh

20:30 kmc: that's answering why you as the programmer should care about CPS

20:30 what extra power it gives you

20:30 not why a compiler should use it internally, or mechanically how it's carried out

20:31 tomoj: well, doesn't that article show a way to do the trampolining to get around lack of TCO?

20:31 kmc: yeah i see it now

20:32 tomoj: by placing bounces you can control which parts of the chain avoid function call overhead at the expense of stack space, I guess?

20:32 kmc: yeah

20:33 and if you baked the bounce into your monadic bind, you'd have full TCO at the expense of slower function calls

20:34 tomoj: unrelatedly, have you seen aleph?

20:34 kmc: no

20:34 tomoj: http://github.com/ztellman/aleph/wiki

20:34 bells are going off in my head but I'm too stupid to tell whether it's a false alarm

20:35 kmc: ding

20:44 so how expensive are threads in Clojure?

20:45 are they 1:1 with Java threads or something more lightweight?

21:20 amalloy: i don't remember if it was tomoj or kmc who linked the intensivesystems monad tutorial, but thanks. so far i'm finding it a lot more understandable than the others i've looked at

21:21 anyway, have to run, but just wanted to mention that

21:30 gfrlog: does anyone else think that c.c.sql could use an ensure-connection macro?

21:30 lancepantz: cc.sql could use alot of things

21:31 gfrlog: ,(defn alot-of-things [& args])

21:31 clojurebot: DENIED

21:31 ninjudd: like a way to load huge datasets without bringing the whole thing into memory!!!

21:31 ;)

21:33 lancepantz: gfrlog: there is a clj-sql project that addresses alot of the shortcoming, but i don't actually use it

21:34 i usually end up calling the jdbc methods directly

21:36 gfrlog: lancepantz: clj-sql doesn't have it -- are you suggesting that project might be easier to contribute to than cc?

21:36 lancepantz: gfrlog: yep

23:57 yayitswei: any pointers for setting up log4j with clojure.contrib.logging? just want a simple way to append-to-file

Logging service provided by n01se.net