#clojure log - Mar 29 2009

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

0:33 dreish: 10^100 == 2^100 * 5^100. 2^100 is obviously divisible by 2^32. So (int (.pow 10M 100)) is 0.

1:36 slashus2: Does the writer function in duck_streams allow for appending?

1:38 When i wrote my with-out-file macro I used FileWriter so that I could use the append functionality.

1:38 The new with-out-writer doesn't seem to support appending.

3:19 Raynes: I think Clojure has ruined me. Everything I think about learning another language, something about Clojure makes me dread it. :|

3:21 cmvkk: that's funny because, thanks to clojure being written in it, i've been learning java for the first time.

3:21 clojure has brought me closer to 'bad' languages.

3:21 Raynes: Why would you learn a language just because another language is written in it. :|

3:22 cmvkk: for clojure's sake, it's a boon to know java. for one thing, I can read the clojure source better which will make me better with clojure.

3:23 but also, it means i can implement part of a clojure library in java if i want, extend clojure from java, etc.

3:23 clojurebot: it is too

3:24 slashus2: clojurebot: indeed

3:24 clojurebot: It's greek to me.

3:24 cmvkk: i'm currently thinking about writing a small 2D game engine in java, but in such a way that it's easy to extend from clojure.

3:24 Raynes: I want to learn Scala or Java.

3:25 But I'm worried if I learn Java, I'll become corrupted.

3:25 cmvkk: worried that you'll see everything in an object-oriented light, and start to add needless OO code to your clojure programs?

3:26 slashus2: Raynes: It just feels more rigid. Using a good IDE like netbeans helps.

3:26 cmvkk: i personally think that knowing more languages can only make you a better programmer.

3:27 Raynes: I'm worried that I'll forget how great functional programming is. I'm worried that learning Clojure before learning an OO language will cause me to program horribly in Java.

3:27 slashus2: Righting things in the oo paradigm is sort of like a game. How can I model this problem into a complex, object oriented scheme?

3:27 Writing rather

3:27 need to go to sleep.

3:27 cmvkk: it's uh, really hard to not program OO in java. rather than code horribly in java, you'll just end up being frustrated.

3:28 you'll want to program in a functional style, but then it turns out that you can't.

6:11 maacl: I get "java.lang.RuntimeException: You need to use "Import Library" to add processing.core.PGraphicsJava2D to your sketch." when I try to run the clj-processing example, even if I and PGraphicsJava2D to the imports ((:import (processing.core PApplet PGraphicsJava2D)) - any ideas anyone ?

6:18 Lau_of_DK: Top of the morning gents

6:18 hiredman: the very top indeed

6:18 maacl: Lau_of_DK: hey

6:22 Lau_of_DK: have you used clj-processing ?

6:22 Lau_of_DK: No sir

6:37 AWizzArd: What is clj-processing good for?

6:50 Lau_of_DK: Anybody here found some interesting ways to couple servlets and ajax ?

7:00 Im thinking ala Symbolic Web

7:08 maacl: Lau_of_DK: can't say that I have

7:54 antifuchs: oh wow, clj-processing. neat!

7:59 maacl: antifuchs: yeah, except I can't get the examples to work

8:02 antifuchs: how so? not behaving properly or are you getting errors?

8:02 maacl: antifuchs: I get "java.lang.RuntimeException: You need to use "Import Library" to add processing.core.PGraphicsJava2D to your sketch." when I try to run the clj-processing example, even if I and PGraphicsJava2D to the imports ((:import (processing.core PApplet PGraphicsJava2D))

8:04 antifuchs: hmm, it's a couple months old, maybe either processing changed?

8:04 s/either//

8:08 maacl: antifuchs: can you get it to work ?

8:08 antifuchs: haven't tried yet... I promised myself I would not hack on stuff today (:

8:08 tomorrow, though

8:09 maacl: antifuchs: if you figure it out I would love to hear from you

8:09 antifuchs: sure thing

8:10 AWizzArd: maacl: when you are in a repl and do (import '(processing.core PGraphicsJava2D)) and then type PGraphisJava2D, what does happen?

8:11 If that beast was imported correctly then PGraphisJava2D should eval to the class processing.core.PGraphisJava2D

8:12 maacl: AWizzArd: hang on

8:15 AWizzArd: yeah it does eval to PGraphicsJava2D

8:19 AWizzArd: ok, that sounds good, it means that the import did work

8:20 maacl: AWizzArd: yeah but I can't figure out what to do to fix it

8:26 AWizzArd: is Processing some kind of graphics program?

8:27 maacl: Aw

8:27 AWizzArd: yeah, it is a data visualization tool

8:28 AWizzArd: ok

8:31 noidi: is it possible to use System/loadLibrary in clojure to load dynamic libraries?

8:32 i tried to port a simple "JNI hello world" from java to clojure but the loadLibrary doesn't seem to be working

8:33 i guess it has something to do with clojure using multiple classloaders, whatever they are :P

9:33 hjlee: ,(clojure.contrib.math/exact-integer-sqrt 1000000000000)

9:33 clojurebot: java.lang.ClassNotFoundException: clojure.contrib.math

11:16 mozinator: For those who might be interrested, I managed to make music with clojure + jmusic: http://mozinator.eu/?p=16

11:17 cmvkk: mozinator: very cool. i'm working on a similar project: http://github.com/cmvkk/lumenc/tree/master

11:17 mozinator: cmvkk, cool !

11:17 cmvkk, going to check it ou

11:17 t

11:18 duck1123: too bad I'm not a musician

11:19 years ago I learn the piece of music I was supposed to be practicing by programming hypercard to play it when i clicked a button

11:21 AWizzArd: mozinator: does jmusic talk to the hardware midi, or does it support very high quality software instruments?

11:23 mozinator: AWizzArd, don't know really, I just bumped into it via http://www.fatvat.co.uk/2009/02/jmusic-and-clojure.html and thought it was cool to let it make music live, instead of writing it to a midi file first

11:25 AWizzArd: yes, sounds good

11:27 mozinator: the thing I would like to accomplish is to make music on the fly

11:27 a little bit like this: http://www.infoq.com/presentations/archaeopteryx-bowkett

11:27 AWizzArd: sounds also interesting for me.. maybe I could combine this with my GP engine

11:28 mozinator: AWizzArd, GP engine ?

11:28 AWizzArd: Genetic Programming

11:29 mozinator: AWizzArd, sounds like a cool idea, go for it :)

11:29 I got to go, visiters

11:29 AWizzArd: l8rs

13:29 MikeSeth: AM HOOKED!

15:03 johanm: I have a question regarding swank-clojure, if anyone is up for it: if I eval a (ns ...) expression with C-M-x, my *slime-repl clojure* does not switch to that namespace. I can switch to it at the repl (and the imports have been picked up, etc.), but consequent evals from my source file is evaluated for the default "user" namespace (meaning I can't use my imports). Am I doing it wrong?

15:08 dysinger: how do I get auto-indentation in the command line repl like I can for emacs? Is there any .inputrc trickery to be had?

15:46 AWizzArd: johanm: if you eval a (ns ..) in a code file, then in that file you will be in that namespace from that moment on. All functions that you write into that same file and that you eval there, will become available in the repl under that namespace.

15:59 johanm: AWizzArd: yeah, but when I eval the (ns ...) i emacs the slime repl does not change to the specified namespace (as indicated by the prompt), like it does when you're running clojure-mode without slime, for example (I'm using slime, swank-clojure and clojure-mode from cvs/git)

16:04 Lau_of_DK: This is border-line off topic, but since Im driving with compojure, I figured you'll cut me some slack: I have an menu which dynamically expands when you hover your mouse on it, problem is, it pushes the entire rest of the page down when expanding - how do I avoid this?

16:09 got it, z-index + absolute positioning

16:09 thanks for nothing guys - whats keeping everyone so busy?

16:10 * chessguy just got here...

16:10 chessguy: and i know nothing about clojure anyway. that's why i'm here :)

16:11 Lau_of_DK: Welcome to :)

16:16 chessguy: welcome to smile? is that what clojure is all about?

16:18 astor: I've been away from clojure for a few months, and after updating to the latest lazy-seq stuff, I'm faced with the following issue. (def *foo* (some-lazy-func)) gives java.lang.ClassCastException: clojure.lang.LazySeq cannot be cast to clojure.lang.IFn

16:19 Lau_of_DK: try wrapping your lazy-func in (seq) or (cons ...)

16:19 chessguy, "Welcome to" was a sentense in itself, the smile was my warm welcome

16:19 astor: (def *foo* (seq (some-lazy-func)) gives the same problem

16:19 Lau_of_DK: Clojure is about functional concurrent lisping

16:19 astor, go to the pastebin

16:19 chessguy: is there a bot in here that interprets snippets?

16:20 cmvkk: ,(+ 2 3)

16:20 clojurebot: 5

16:20 chessguy: nice

16:20 Lau_of_DK: ,(doc cons)

16:20 clojurebot: "([x seq]); Returns a new seq where x is the first element and seq is the rest."

16:21 chessguy: ,(list 1 2 3)

16:21 clojurebot: (1 2 3)

16:21 chessguy: ,(car (list 1 2 3))

16:21 clojurebot: java.lang.Exception: Unable to resolve symbol: car in this context

16:21 Lau_of_DK: car.... :)

16:21 chessguy: just checking :)

16:21 Lau_of_DK: You got in here from last century ?

16:21 chessguy: haha

16:21 cmvkk: you know, i thought i would miss car and cdr.

16:21 chessguy: been watching SICP :)

16:22 Lau_of_DK: I dont mis car and cdr, but I sometimes need cardrradrrdadrrr

16:22 chessguy: ,(first (1 2 3))

16:22 clojurebot: java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn

16:22 Lau_of_DK: clojurebot: SICP ?

16:22 clojurebot: No entiendo

16:22 Lau_of_DK: clojurebot: SICP ?

16:22 clojurebot: Titim gan �ir� ort.

16:22 Lau_of_DK: Argh

16:22 qwert666: is pattern matching available in clojure ? like in scala or haskell

16:22 Lau_of_DK: There was a page with the SICP code ported to Clojure

16:22 chessguy: ,(first '(1 2 3))

16:22 clojurebot: 1

16:22 chessguy: ah

16:22 cmvkk: qwert666, not quite

16:22 chessguy: so without the quote it was trying to apply 1 to the arguments 2 and 3?

16:23 cmvkk: mostly (i guess?) because there aren't types to match against

16:23 hiredman: clojurebot: sicp?

16:23 clojurebot: sicp is http://web.mit.edu/alexmv/6.001/sicp.pdf

16:23 hiredman: clojurebot: sicp?

16:23 clojurebot: sicp is http://www.codepoetics.com/wiki/index.php?title=Topics:SICP_in_other_languages:Clojure:Chapter_1

16:23 qwert666: cmvkk: so there is a chance that it will be implemented in the future ?

16:24 cmvkk: there is arity overloading, but i don't think rhickey likes the pattern matching aspect

16:24 so probably not?

16:24 there's destructuring too, which is kind of like that

16:24 Lau_of_DK: Guys - how do I center a div-tag which is positioned absolutely ?

16:24 chessguy: uh...wouldn't that be better to ask in #css or #html or something?

16:24 cmvkk: position it absolutely in the center?

16:25 Lau_of_DK: I need something like 50%x100px

16:25 cmvkk: yes that is too complicated

16:25 chessguy: ,(* (+ 2 (* 4 6)) (+ 3 5 7))

16:25 clojurebot: 390

16:26 hiredman: (* 4 6)

16:26 clojurebot: *suffusion of yellow*

16:26 chessguy: huh?

16:26 cmvkk: math operations returning colors

16:27 that's a little too cutting edge for me

16:27 hiredman: http://www.thateden.co.uk/dirk/

16:27 astor: How do I rewrite this idiom which I use everywhere in my code using lazy-seq? http://clojure.pastebin.com/m5e0facc7

16:28 slashus2: lol

16:28 Lau_of_DK: astor, replace lazy-cons with cons I think

16:28 Doesnt look like anything out of the ordinary

16:29 astor: more like http://clojure.pastebin.com/m7354eb77.. forgot the lazy-cons recursion in the first example.

16:29 lazy-seq does not allow recur

16:30 cmvkk: your best bet is to put a lazy-seq, then use loop inside of the lazy seq

16:30 hiredman: uh

16:30 cmvkk: or something

16:30 astor: so I need defn, then fn, then lazy-seq, then loop, then recur+cons?

16:30 hiredman: I don't think that will work

16:30 astor: that's mighty complex.

16:31 hiredman: hmmm

16:31 you don't need the fn

16:31 cmvkk: oh yeah.

16:32 (loop [[[f & r] s] s] ...) instead of the let and fn

16:32 hiredman: using lazy-seq typially looks like (defn f [x] (lazy-seq (cons (first x) (f (rest x)))))

16:33 this lazy-seq looks like it just returns a laz-seq of even numbers is that correct?

16:33 astor: so I'd probably want something like (defn f [[f & r] x] (lazy-seq (cons f (loop ... (recur..) (f r)))))

16:34 cmvkk: not quite.

16:34 hiredman: (filter even? (iterate inc 0))

16:34 cmvkk: (defn f [s] (lazy-seq (loop [[[f & r] s] s] (when f ...))))

16:34 hiredman: will get you a lazy-seq of even numbers

16:34 cmvkk: or rather my-lazy-func instead of f there

16:34 then use cons instead of lazy-cons. but yeah, hiredman's right, just use filter.

16:35 hiredman: ,(take 10 (filter even? (iterate inc 0)))

16:35 clojurebot: (0 2 4 6 8 10 12 14 16 18)

16:35 hiredman: ~def filter

16:36 cmvkk: it's not quite that simple though, there's some weird destructuring going on in the input there

16:36 clojurebot: it is too

16:37 SethTisue: clojurebot is getting sassy

16:37 astor: my example is simplified, in real-life f takes several parameters which makes filter inadequate.

16:37 * hiredman disbelieves

16:38 cmvkk: http://clojure.pastebin.com/d321a3117 astor

16:38 astor: sometimes I use reduce, but that's ugly because the initial condition is physically separate in the code.

16:39 cmvkk: thanks

16:39 slashus2: cmvkk: step isn't defined in that code.

16:40 cmvkk: it wasn't in the example code either...i don't think.

16:40 hiredman: given the similar structure of filter and your code I fard it hard to believe that you cannot just use filter

16:40 AWizzArd: OT: anybody here who speaks russian? I have a very easy question :)

16:40 clojurebot: filter is not map

16:40 hiredman: clojurebot: thanks!

16:40 clojurebot: Gabh mo leithsc�al?

16:41 hiredman: ~translate to ru one ping, one ping only

16:41 clojurebot: ???? ????, ???? ?????? ????

16:42 chessguy: i'm thinking the symbolic differentiation pattern-matching thing from the video version of SICP would be a nice first project

16:43 hiredman: chessguy: using zippers

16:43 chessguy: oooh

16:43 is there a zipper module already?

16:43 hiredman: yes

16:43 clojure.zip

16:43 chessguy: though...i don't know that a zipper is really necessary for that one

16:44 recursion should be fine

16:44 hiredman: correct

16:44 but zippers are cool

16:44 cmvkk: i don't know what zippers are...am i missing out on the next big thing?

16:44 hiredman: http://clojure.org/other_libraries

16:44 chessguy: cmvkk: zippers aren't really new

16:44 cmvkk: heh

16:44 chessguy: http://en.wikipedia.org/wiki/Zipper_(data_structure)

16:44 hiredman: ,(require '[clojure.zip :as zip])

16:44 clojurebot: nil

16:45 chessguy: reading the huet paper is a good start

16:45 cmvkk: oh i've heard of this

16:45 chessguy: though i seem to remember the code in the paper being in haskell, or close to it

16:46 astor: hiredman: typically you have something like (defn foo [x] (let [state {} step (fn [state [[f & r] x] (when f (if (complex-expression f) (recur (update-state state) r) (lazy-cons f (step r)))))] (step x))

16:46 hiredman: ,(zip/seq-zip '(1 ? 3) zip/down zip/right (zip/replace 2) zip/root)

16:46 clojurebot: java.lang.IllegalArgumentException: Wrong number of args passed to: zip$replace

16:46 astor: there is probably a syntax error in there :-). the point is that there is additional state that is needed to figure out whether to recurse or not.

16:46 hiredman: ,(-> '(1 ? 3) zip/seq-zip zip/down zip/right (zip/replace 2) zip/root)

16:46 clojurebot: (1 2 3)

16:46 cmvkk: yes in fact, you can't use filter for that scenario.

16:46 clojurebot: filter is not map

16:47 chessguy: astor: are you saying a zipper is needed?

16:47 cmvkk: uh-oh, we're merging two conversations

16:47 chessguy: oh, whoops

16:47 referential opqueness for the loss

16:48 hiredman: ,(pl inc $ inc $ inc $ 0)

16:48 clojurebot: 3

16:48 cmvkk: i was going to say, this is where something like 'lazy-loop' would come in handy, but you couldn't do it with that kind of structure either.

16:48 the goal is to be able to recur a structure either with or without giving the next element.

16:49 hiredman: ,(pl (?map (replicate 3 range $ 3) call � (?map inc)))

16:49 clojurebot: ((1 2 3) (1 2 3) (1 2 3))

16:49 chessguy: ,(replicate 3 range $ 3)

16:49 clojurebot: java.lang.Exception: Unable to resolve symbol: $ in this context

16:50 hiredman: pl is a macro that uses zippers

16:50 chessguy: ah

16:50 hiredman: ,(macroexpand '(pl range $ 3))

16:50 clojurebot: (do (range 3))

16:51 hiredman: and it only exists in clojurebot

16:53 Lau_of_DK: I got the absolute positioning down :)

16:53 Man - The more I work with jQuery, the more I realize how powerful a clojure-wrap could be

16:53 chessguy: ,(do (range 3))

16:53 clojurebot: (0 1 2)

16:53 slashus2: hiredman: What does pl mean?

16:53 chessguy: clojure-wrap?

16:53 clojurebot: clojure is like life: you make trade-offs

16:53 Lau_of_DK: So I'll make the most full-featured wrapper imaginable, and keep it all to myself

16:54 That'll teach you guys to ignore my questions :)

16:54 chessguy: what is do?

16:54 hiredman: slashus2: pointless

16:54 Lau_of_DK: do is a utility for gnome, which helps you reach your apps faster

16:55 chessguy: ,slap Lau_of_DK

16:55 clojurebot: java.lang.Exception: Unable to resolve symbol: slap in this context

16:55 chessguy: bah

16:55 Lau_of_DK: haha

16:55 hiredman, thats bad PR right there

16:55 hiredman: ,(doc do)

16:55 clojurebot: java.lang.Exception: Unable to resolve var: do in this context

16:55 hiredman: bah

16:55 do does things

16:55 Lau_of_DK: ,(loop [] (recur))

16:55 hiredman: ,(do 1 (+ 1 2))

16:55 Lau_of_DK: ,(loop [] (recur))

16:55 ,(loop [] (recur))

16:55 ,(loop [] (recur))

16:55 ,(loop [] (recur))

16:55 clojurebot: Execution Timed Out

16:55 3

16:55 Lau_of_DK: Muhaha :)

16:55 clojurebot: Execution Timed Out

16:55 hiredman: Lau_of_DK: I will make clojurebot ignore you

16:55 clojurebot: Execution Timed Out

16:56 chessguy: ,(do 2 (+ 1 2))

16:56 Lau_of_DK: Fine - its your bot

16:56 clojurebot: Execution Timed Out

16:56 hiredman: I'm just saying, chillax

16:56 clojurebot: Execution Timed Out

16:56 3

16:56 hiredman: do evals the forms and returns the last one

16:56 chessguy: oh

16:56 ,(do (+ 1 2) 2)

16:56 clojurebot: 2

16:57 hiredman: ,(do (println 1) 2)

16:57 clojurebot: 2

16:57 chessguy: so it's intended for side effects

16:57 clojurebot: 1

16:57 it is too

16:57 hiredman: erm

16:57 not always

16:57 it is useful in macros

16:58 because macros can only return one form

16:58 so you wrap a bunch of forms in a do

16:58 like I do with pl

16:58 chessguy: interesting

17:01 slashus2: Do zippers make it easy to write tree data structures? (e.g. red-black, b-tree)

17:02 chessguy: they're more for traversing such structures

17:03 qwert666: have any of you seen any proj. in GSoC with Clojure ?

17:03 GoogleSummerofCode *

17:03 slashus2: It seems like it would work with modifying a tree structure too.

17:09 hiredman: someone should do a soc on the function interface and the compiler

17:09 as in, propagating type information

17:22 chessguy: so if i want to start playing with some basic existing lisp code, is the defn vs define/lambda stuff going to be the only real difference?

17:22 (at first)

17:22 duncanm: chessguy: there are other syntactic differences

17:22 chessguy: ones that i'll run into immediately?

17:22 duncanm: chessguy: when you refer to DEFINE, are you talking about Scheme?

17:22 antifuchs: also, things like not being allowed to modify local variables after they were bound

17:22 chessguy: yes

17:22 hiredman: clojure doesn't have cons cells

17:22 no car and cdr

17:22 duncanm: so substitute that with first and rest

17:22 chessguy: oh right, it's first and rest, right?

17:22 yeah

17:22 ,(rest '(1 2 3 4))

17:22 duncanm: chessguy: the LET syntax is different

17:22 clojurebot: (2 3 4)

17:22 chessguy: ,(rest (rest '(1 2 3 4))

17:22 clojurebot: EOF while reading

17:22 hiredman: but, if you are watching SICP, they uses cons cells for stuff like rational numbers

17:22 antifuchs: also, the cond syntax. and reader differences. check out the lisp differences page on the wiki (:

17:22 hiredman: of course clojure has rational numbers built in

17:22 chessguy: ,(rest (rest '(1 2 3 4)))

17:22 clojurebot: (3 4)

17:22 duncanm: hiredman: so does scheme

17:22 chessguy: hiredman: but using built-in code is no fun :)

17:23 hiredman: so you would use a struct for rational numbers in clojure

17:23 chessguy: a struct?

17:23 hiredman: ,(doc defstruct)

17:23 clojurebot: "([name & keys]); Same as (def name (create-struct keys...))"

17:23 hiredman: it is a kind of map

17:23 chessguy: you couldn't just use a list of 2 elements?

17:23 hiredman: optimized for making a small number of keys

17:23 Chousuke: uh, why would you use a struct?

17:24 hiredman: chessguy: you could

17:24 if you where going to go the positional route I would use a vector

17:24 Chousuke: I wonder what the class name was though

17:24 hiredman: instead of a list

17:24 Chousuke: ,(Ratio. 1 2)

17:24 clojurebot: java.lang.IllegalArgumentException: Unable to resolve classname: Ratio

17:24 Chousuke: (class 1/2)

17:24 hiredman: Chousuke: yes yes, the native rationals was covered

17:24 Chousuke: ,(class 1/2)

17:24 clojurebot: clojure.lang.Ratio

17:25 hiredman: but, if you where making your own rationals

17:25 duncanm: i think the name is rationalize

17:25 ,(rationalize 0.5)

17:25 clojurebot: 1/2

17:25 duncanm: ,1/2

17:25 clojurebot: 1/2

17:25 duncanm: you don't need an explicit constructor

17:25 chessguy: ,(defn test ((defn numer first) (defn denom [x] (first (rest x)) (denom '(1 2)))

17:25 clojurebot: EOF while reading

17:25 chessguy: ,(defn test ((defn numer first) (defn denom [x] (first (rest x)) (denom '(1 2))))

17:25 clojurebot: EOF while reading

17:25 hiredman: ,(struct (create-struct :denom :nom) 1 2)

17:25 clojurebot: {:denom 1, :nom 2}

17:25 chessguy: ah the fun of balancing parens

17:26 Chousuke: chessguy: def and defn won't work with clojurebot

17:26 duncanm: chessguy: use a real editor

17:26 hiredman: chessguy: I will stop you there

17:26 no defs in clojurebot

17:26 chessguy: oh

17:26 duncanm: hiredman: just use LET! ;-)

17:26 chessguy: well poo

17:26 Chousuke: and instead of rest you want to use second anyway

17:27 hiredman: and use a struct

17:27 :P

17:27 chessguy: ,(second '(1 2 3))

17:27 clojurebot: 2

17:27 duncanm: (rest '(1 2)) -> '(2); (second '(1 2)) -> 2

17:27 a common mistake

17:27 hiredman: USE A STRUCT

17:27 Chousuke: (let [numer first denom second] (denom [1 2]))

17:27 hiredman: why, though?

17:27 hiredman: a struct as clearly labeled parts

17:27 chessguy: duncanm: i was doing (first (rest x)), not (rest x)

17:27 hiredman: instead of just a list of numbers

17:28 duncanm: then that's the same as CADR, which is SECOND

17:28 chessguy: duncanm: yes, but it's not wrong

17:29 hiredman: so when you see (8 7) is that a rational? {:denominator 8 :nominator 7} is pretty clear

17:29 Chousuke: I wonder why this is being discussed as native support for rationals exists :P

17:29 chessguy: hiredman: i understand that. i'm trying to grok list syntax right now

17:29 chillax :)

17:30 Chousuke: you wouldn't use lists for rationals anyway. you'd use vectors.

17:30 hiredman: Chousuke: because in the SICP videos they make their rationals

17:30 Chousuke: lists are overrated.


17:30 geez

17:30 hiredman: 14:22 hiredman : if you where going to go the positional route I would use a vector

17:31 duncanm: la la la

17:38 chessguy: well, i'm glad we got that settled

17:43 hiredman: ,(alter-meta! *ns* assoc :killroy-was-here (Date.))

17:43 clojurebot: {:killroy-was-here #<Date Sun Mar 29 14:41:43 PDT 2009>, :a 1}

17:43 cmvkk: ^*ns*

17:43 ,^*ns*

17:43 clojurebot: {:killroy-was-here #<Date Sun Mar 29 14:41:43 PDT 2009>, :a 1}

17:44 antifuchs: haha

17:44 cmvkk: ,(alter-meta! + assoc :foo 2)

17:44 clojurebot: java.lang.ClassCastException: clojure.core$_PLUS___3313 cannot be cast to clojure.lang.IReference

17:44 cmvkk: ,(alter-meta! #'+ assoc :foo 2)

17:44 clojurebot: {:foo 2, :ns #<Namespace clojure.core>, :name +, :file "core.clj", :line 569, :arglists ([] [x] [x y] [x y & more]), :inline-arities #{2}, :inline #<core$fn__3310 clojure.core$fn__3310@ac0f75>, :doc "Returns the sum of nums. (+) returns 0."}

17:45 chessguy: i'm beginning to think that clojure might be the language that finally lures me away from haskell

17:45 cmvkk: wait does doc operate off of the meta

17:45 Chousuke: yes

17:45 hiredman: "hey man, I left you message in +'s metadata"

17:45 cmvkk: ,(alter-meta! #'+ assoc :doc "Subtracts two numbers. Just kidding.")

17:45 clojurebot: {:foo 2, :ns #<Namespace clojure.core>, :name +, :file "core.clj", :line 569, :arglists ([] [x] [x y] [x y & more]), :inline-arities #{2}, :inline #<core$fn__3310 clojure.core$fn__3310@ac0f75>, :doc "Subtracts two numbers. Just kidding."}

17:45 cmvkk: ,(doc +)

17:45 clojurebot: "([] [x] [x y] [x y & more]); Subtracts two numbers. Just kidding."

17:45 Chousuke: :)

17:45 cmvkk: excellent.

17:45 chessguy: haha

17:46 ,(+)

17:46 clojurebot: 0

17:46 chessguy: ,(+ 3)

17:46 clojurebot: 3

17:46 chessguy: cute

17:46 i like that syntax

17:46 AWizzArd: chessguy: in the end you could write your own reader and get any syntax you like

17:46 hiredman: huh

17:47 never noticed :inline and :inline-arities

17:47 slashus2: Are there any good examples of using zippers to create a tree structure?

17:47 chessguy: so i can do (defn foo [x] (...)) and then also do (defn foo [x y] (...)) ?

17:47 slashus2: they're not used to create trees

17:47 hiredman: no

17:47 chessguy: slashus2: they're used to define them

17:47 err

17:47 traverse them

17:48 hiredman: you do (defn foo ([x] ...) ([x y] ...))

17:48 chessguy: oh ok

17:48 slashus2: chessguy: It has the ability to create new nodes and edit them.

17:48 cmvkk: man whenever you write ellipses it shows up as random gibberish in my terminal

17:48 hiredman: cmvkk: because I use a unicode ellipse

17:49 cmvkk: yep. do you have a button assigned to it or something

17:49 Chousuke: cmvkk: set up your client to use UTF-8 :)

17:49 cmvkk: my client is aterm :/

17:49 hiredman: irssi turns ... into ...

17:49 Chousuke: well aterm ought to work.

17:49 hiredman: bah

17:49 "..."

17:49 Chousuke: nah.

17:49 slashus2: It has insert-child, make-node, etc. I don't see any reason why it could not be used for that purpose.

17:49 Chousuke: mine shows it just fine

17:49 cmvkk: aterm isn't unicode compatable. or so it seems...i'm running irssi on screen on aterm, and i get the weird gibberish

17:49 clojurebot: it is too

17:50 hiredman: I use terminator (tiling temrinal thing) screen and irssi

17:50 cmvkk: each of those things has it's own unicode settings

17:50 Chousuke: cmvkk: do you have your locale set to UTF-8

17:50 cmvkk: ............maybe

17:51 LANG=en_US.UTF-8 does that count

17:52 hiredman: http://jerakeen.org/blog/2005/06/screen-irssi-utf8/

17:53 slashus2: chessguy: Huet's paper states that changes, insertion, and deletion are valid operations.

17:54 hiredman: ...

17:54 ?


17:55 cmvkk: nope. hmm.

17:55 i restarted with screen -U and put /set term_charset utf-8

17:55 oh well!

17:55 chessguy: ok, so why does this blow the stack? (defn foo ([] 0) ([x & rest] (+ x (foo rest))))

17:55 hiredman: what do they show up as? squares?

17:55 cmvkk: a with a mark above it, dotted square, broken pipe

17:56 hiredman: you will never get to ([] 0)

17:56 chessguy: why? rest can't match against an empty list?

17:56 hiredman: you most likely want (apply foo rest)

17:56 [] is not an empty list

17:56 cmvkk: chessguy that's not an empty list, it's no arguments

17:56 hiredman: it is no args

17:56 chessguy: err, whoops

17:57 hiredman: ,(doc apply)

17:57 clojurebot: "([f args* argseq]); Applies fn f to the argument list formed by prepending args to argseq."

17:57 chessguy: what's that * notation?

17:57 hiredman: * is just used there to mean more then one thing

17:57 cmvkk: it means like 'zero or more'

17:57 hiredman: it isn't language syntax

17:57 cmvkk: it's a kleene star!

17:58 chessguy: ok, typical regex-ish notation

17:58 hiredman: ,(apply + 1 2 '(3 4 5))

17:58 clojurebot: 15

17:58 chessguy: yeah, this seems to work:

17:58 (defn foo ([] 0) ([x & rest] (+ x (apply foo rest))))

17:59 hiredman: ,(apply + '())

17:59 clojurebot: 0

17:59 chessguy: ,(+)

17:59 clojurebot: 0

17:59 chessguy: :)

17:59 AWizzArd: chessguy: while it works it would probably not be code that gets used in production

17:59 clojurebot: it is too

17:59 AWizzArd: ,(*)

17:59 clojurebot: 1

17:59 chessguy: AWizzArd: uh, this is the first code i've written in clojure. i don't expect it to get used in production :)

17:59 hiredman: clojurebot: botsnack

17:59 clojurebot: thanks; that was delicious. (nom nom nom)

18:00 chessguy: so helpful for you to point that out though

18:00 i was really concerned

18:00 AWizzArd: (defn foo [numbers] (apply + numbers)) could do the trick

18:00 chessguy: AWizzArd: so would (defn foo (+))

18:01 that's hardly the point

18:01 AWizzArd: No, that would not work

18:01 even (def foo +) would not be the same thing

18:02 cmvkk: ,(let [foo +] (foo 2 3))

18:02 clojurebot: 5

18:02 AWizzArd: ,(let [foo +] (foo '(2 3))

18:02 clojurebot: EOF while reading

18:02 AWizzArd: ,(let [foo +] (foo '(2 3)))

18:02 clojurebot: java.lang.ClassCastException

18:03 AWizzArd: ,(apply + '(2 3))

18:03 clojurebot: 5

18:03 chessguy: interesting

18:03 cmvkk: ,(let [foo #(apply + %)] (foo '(2 3)))

18:03 clojurebot: 5

18:03 chessguy: not sure i get why (defn bar +) doesn't work

18:04 cmvkk: (def bar +) would just make bar work like +.

18:04 chessguy: oh right, def

18:04 that's what i meant

18:06 wouldn't bar then represent the same function that + represents?

18:06 cmvkk: yes.

18:06 chessguy: cool :)

18:07 i did learn something from SICP

18:07 AWizzArd: And apply is one of those funny functions that one can not write on the same level on which one is writing the rest of the program. Although antifuchs made a nice macro that can fake apply for most practical cases ;)

18:09 chessguy: hm. so you can't evaluate clojure in clojure?

18:09 AWizzArd: you can

18:09 chessguy: hm

18:09 cmvkk: i'm not sure what you mean, though. apply isn't a special form; it's written in clojure.

18:10 astor: Thinking about the problem I mentioned earlier, a macro - (loop-seq sequence bindings &body) could be imagined which will go through a sequence and where bindings is used to keep state and where the exit of the loop is a (cons...). It seem that this macro is very hard to implement since there is not way to add extra arguments to (recur..).

18:10 chessguy: anyway, enough brain-bending for tonight. i'm off to hang out with some friends. thanks ya'all!

18:10 cmvkk: on second glance, apply is written with java after all.

18:10 AWizzArd: cmvkk: yes right.. but look at it's definition

18:10 yup

18:11 just write your own apply without making use of apply itself

18:12 cmvkk: (defmacro myapply [f args] `(~f ~@args))

18:12 :)

18:13 AWizzArd: yes, that works for a subset of cases where one can use apply

18:15 a small subset

18:15 dnolen: ,(apply apply [+ [1 2 3]])

18:15 clojurebot: 6

18:16 cmvkk: my version does that too?

18:17 AWizzArd: yes

18:17 but try for example:

18:17 ,(range 2 4)

18:17 clojurebot: (2 3)

18:17 AWizzArd: ,(apply + (range 2 4))

18:17 clojurebot: 5

18:17 duncanm: ,(range 1 3)

18:17 clojurebot: (1 2)

18:17 duncanm: heh

18:17 hiredman: cmvkk: I surprised you haven't paste your lazy-loop yet

18:17 cmvkk: touche!

18:18 hiredman I did a long time ago

18:18 1 1 0

18:18 http://paste.lisp.org/display/77400

18:19 it captures a variable though

18:19 clojurebot: it is too

18:19 * hiredman giggles

18:19 AWizzArd: hiredman: you gave him too much botsnacks

18:19 too many

18:19 Chousuke: :P

18:22 cmvkk: astor: look at my paste above

18:22 didn't notice that you were looking for something like that

18:22 clojurebot: for is not used often enough.

18:22 cmvkk: ideally you'd want a structure that you can either recur OR give, so that you can 'skip' iterations.

18:23 this is something that streams would be able to do i think?

18:23 hiredman: I think you can do it with seqs

18:23 you just return a call instead of a cons

18:23 cmvkk: in theory

18:24 right, but then you have to start worrying about blowing the stack if you skip too many times.

18:24 you can't use recur, since that won't work through a lazy-seq.

18:24 actually, you can't just call either. becuase then you have a lazy-seq returning another lazy-seq.

18:24 which isn't quite right...

18:25 actually, the way to do it would be to expand a loop right inside the lazy-seq, that just binds the same arguments as the function as a whole.

18:25 then you can use recur normally, and if all you do is return a cons right away, it just ignores the loop entirely.

18:30 lisppaste8: cmvkk annotated #77400 "fixed lazy-loop" at http://paste.lisp.org/display/77400#1

18:45 astor: cmvkk: inspired by lazy-loop, I wrote a very simple lazy-seq-fn

18:45 Chousuke: what does that do?

18:45 lisppaste8: astor annotated #77400 "lazy-seq-fn" at http://paste.lisp.org/display/77400#2

18:47 astor annotated #77400 "untitled" at http://paste.lisp.org/display/77400#3

18:48 astor: an fn where I can use either recur or cons based on whether I want to filter or not.

18:50 adding support for destructuring in bindings requires "slightly" more work :-)

18:50 Chousuke: (doc destructure)

18:50 clojurebot: excusez-moi

18:50 Chousuke: hm

18:50 cmvkk: my fixed lazy-loop does that, though.

18:50 Chousuke: anyway, there's a function that destructures a binding form

18:50 cmvkk: you can 'recur' or 'give' based on whether you want to skip or not, and it supports destructuring the same way regular loop does.

18:51 Chousuke: ,(destructure '[x 1 y 2])

18:51 clojurebot: [x 1 y 2]

18:51 Chousuke: eh

18:51 I'm silly sometimes

18:51 ,(destructure '[[x y] [1 2]])

18:51 clojurebot: [vec__4374 [1 2] x (clojure.core/nth vec__4374 0 nil) y (clojure.core/nth vec__4374 1 nil)]

18:53 durka42: oh, that's how it works

18:53 cool

18:53 cmvkk: ,(doc destructure)

18:53 clojurebot: "([bindings]); "

18:53 astor: cmvkk: the (vector % %) doesn't work with destructuring.

18:53 Chousuke: it's undocumented :)

18:53 cmvkk: astor... hmm, you might be right.

18:54 HMM.

18:54 astor: cmvkk: lazy-seq-fn does not have the capture problems. I think it captures the essence of your idea.

18:55 cmvkk: yep, it's pretty much the same thing.

18:55 now i'm just wondering how to fix destructuring on both of them.

18:56 Chousuke: actually, since loop supports destructuring, wouldn't calling that with something like [x [y z]] end up like (loop [x x [y z] [y z]] that is completely valid? :/

18:57 cmvkk: the problem is when you get [[x & y :as z] [x & y :as z]] where clearly the second is not a valid initial form.

18:57 Chousuke: ah, true.

18:58 * astor needs sleep

18:58 cmvkk: aha, i know how to do it.

18:59 for the function's arglist, you just use gensyms. then for the loop, you use the actual destructed args, and the gensyms as the inits.

18:59 astor: cmvkk: nice

19:02 lisppaste8: cmvkk annotated #77400 "double fixed lazy-loop" at http://paste.lisp.org/display/77400#4

19:36 hiredman: http://boinkor.net/archives/2009/03/clojure_and_art_of_illusion_bf.html <-- awesome

19:36 qwert666: hmm i`m using the fibonacci code from http://clojure.org/atoms and with a large numbers i`m getting StackOverflowError do u know any "tricks" to omit the stack problem... ?

19:36 cmvkk: even with the memoization?

19:37 hiredman: it depends what is blowing the stack, and how large your numbers are

19:38 cmvkk: ah yeah, it would.

19:38 qwert666: hiredman: fib >500

19:38 cmvkk: because if you start it out, it still has to call back and memoize every single previous number.

19:38 Puzzler: yeah, that implementation would blow the stack.

19:39 hiredman: I have no idea how big that number is

19:39 cmvkk: hiredman, it doesn't matter how big the result is.

19:39 clojurebot: it is too

19:39 qwert666: hmm so the implementation sux for big numbers :(

19:40 Puzzler: Some other versions of Scheme / Lisp don't really have a stack that's limited by anything but overall memory, but in Clojure, you've got to be careful, because it's running on Java.

19:40 cmvkk: yeah, even if you memoize that's a really bad way to write a fibonacci algorithm.

19:40 i think this sort of recurring is likely to blow the stack no matter what language you use.

19:42 qwert666: mhm ok thx u`r probably right

19:42 dnolen: Puzzler: that's not completely true, Scheme & Lisp have TCO, you can still blow the stack.

19:42 Scheme & CL I meant.

19:43 hiredman: from what I hear not all CL impls have tco

19:43 Puzzler: I don't know the implementation details, but I've used PLT Scheme enough to say that function calls are not implemented using a limited stack that can "blow". Eventually, you'll run out of overall memory on your machine, but far after mainstream languages would blow a stack.

19:43 dnolen: hiredman: you are correct.

19:44 Puzzler: It's as if everything is heap allocated (don't know if that's really how it's implemented, though).

19:44 dnolen: Puzzler: they will blow if the recursion calls are not in the tail posiitin.

19:44 cmvkk: Puzzler, are you sure you aren't thinking of tail recursion?

19:44 yeah.

19:45 Puzzler: I'm sure. Yes, I know the memory will eventually run out. I'm just saying it is not as limited as languages which have a very small amount of memory set aside for stack.

19:45 You can do non-recursive things involving many thousands of levels deep, and it won't bat an eye.

19:45 dnolen: in Clojure you can do pretty much the same thing with trampolines or recur

19:45 Puzzler: you can set the stack memsize to the jvm instanc.e

19:45 Puzzler: I meant "non tail-recursive"

19:46 dnolen: Puzzler: that's because functions calls are in the tail position.

19:46 cmvkk: dnolen, that wouldn't be "non tail-recursive" though.

19:46 Puzzler: To put it in perspective, in Clojure, you have to be very careful about writing non tail-recursive traversals of really long lists (like simple implementation of map).

19:47 In PLT Scheme, if the list can fit in your memory, you'll have no problem with the accumulated function calls fitting in memory too. So basically, you can write your function in the naive way, without worrying about stack.

19:48 That's cause in most languages the stack is only a small percentage of overall memory.

19:48 dnolen: cmvkk: the TCO, is tail call optimization, recursion is one case as far I understand the issue.

19:48 cmvkk: but i think his point is that PLT scheme won't blow the stack, even if you don't take advantage of TCO.

19:49 you can have recursion without having TCO.

19:50 Puzzler: Right cmvkk, you'll eventually run out of memory, but after you've used all 3GB of RAM on your machine (not likely to happen), rather than after 3000 function calls deep, or some other arbitrary number.

19:51 cmvkk: although that might be the case, i don't think it makes it okay to write naive recursive algorithms

19:51 you're right though: "At the same time, recursion does not lead to particularly bad performance in Scheme, and there is no such thing as stack overflow;"

19:51 from the PLT docs

19:52 Puzzler: Consider something like this: (defn map [f s] (if (empty? s) () (cons (f (first s)) (map f (rest s))))

19:53 In PLT Scheme, you don't have to worry about stack overflow. But you do in Clojure.

19:53 An easy fix in Clojure is to wrap this in a lazy-seq.

19:53 cmvkk: it's still a bad idea to do that, though.

19:53 Puzzler: Why?

19:53 cmvkk: in fact, that's how map is defined in clojure...

19:53 because TCO is more efficient in general

19:53 qwert666: so if i`m geting it right... the TCO secure in some way the jvm from blowing the stack off... ?

19:53 Puzzler: But for other kinds of traversals, it's not such an easy fix.

19:54 cmvkk: and because using O(n) space is pointless if you can do it in constant space.

19:54 "Similarly, in Scheme, it is often important to make sure that tail recursion is used to avoid O(n) space consumption when the computation is easily performed in constant space."

19:54 also from the PLT docs.

19:55 Puzzler: You're going to use up O(n) space anyway to build the final list. Taking up the same amount of space, temporarily, with "stack"-like allocations, doesn't change anything.

19:55 cmvkk: I suppose that's true...except for the extra function call stuff, I guess.

19:56 Puzzler: You can't easily make map tail-recursive without reversing the list, and reversing it again at the end (or using laziness which adds its own overhead).

19:57 Amazingly, if you compare a tail-recursive and non-tail-recursive version of factorial in PLT Scheme, the non-tail-recursive one is faster.

19:57 cmvkk: Yeah, the docs seem to suggest that that's the case.

19:57 dnolen: hey I just tried factorial in DrScheme and I ran out of memory, (fact 10000000)

19:57 cmvkk: heh

19:57 i think that kind of input doesn't prove much...

19:58 Puzzler: My guess is that with that kind of input, the final answer is too big to fit in memory :) .

19:58 lisppaste8: dnolen pasted "scheme blow stack" at http://paste.lisp.org/display/77760

19:58 dnolen: i don't think that is true Puzzler

19:58 the problem here is that the call to fact is not in the tail position

19:59 the stack grows because of the *

19:59 cmvkk: yep. it's not *impossible* to blow the stack in PLT, but you have to run out of all memory.

19:59 to calculate that number, you need ten million stack frames...

20:00 Puzzler: Yes, what cmvkk said is exactly my point.

20:00 dnolen: the point is that code cannot be TCO'ed

20:00 the multiply needs the stack to grow to resolve all values.

20:00 Puzzler: I don't think 10 million stack frames is your limiting factor though. My guess is it's the manipulation of such enormous integers.

20:01 cmvkk: i wonder. try it again with + instead of *.

20:01 that won't come near running out of memory just because of the integer.

20:02 dnolen: it stills runs out of memory

20:02 http://funcall.blogspot.com/2009/03/not-lisp-again.html

20:02 this is not my own invention, example culled from here

20:02 it explains the TCO issue quite well.

20:02 cmvkk: in any case, factorial is a good example of a function that nobody should be defining like that, no matter how good your language handles recursion.

20:03 but i think we can agree on that point...

20:04 Puzzler: OK, I concede that PLT Scheme can't handle 10,000,000 function calls deep.

20:04 dnolen: true, enuf, but it should clearly what TCO means, you need to write you code so that TCO can kick in even in Lisp and Scheme.

20:04 cmvkk: dnolen, well, to be fair, probably nobody's going to calling factorial ten million.

20:05 factorial's just an example of a function that's it's really simple to write in tail position.

20:05 Puzzler: It still helps that you're not as limited as in most languages.

20:05 cmvkk: no, you're right. especially with functions that hare hard to make tail-recursive.

20:05 Puzzler: When I write recursion over lists or trees, I do worry about whether Clojure will be able to handle the depth.

20:06 I'm not used to worrying about that.

20:06 I'm working on code right now that can't really be trampolined or turned into TCO, but potentially has a fair amount of depth.

20:06 cmvkk: it's a problem when you do tree recursion. since trampolines only work on tail calls too...

20:07 Puzzler: I'd probably have to do something analogous to lazy-seq, storing a delay to the next node of the tree.

20:08 Fortunately, the stack limitation hasn't bitten me yet on this particular code, but it bothers me that it is fragile in this respect.

20:10 qwert666: i`m searching for some benchmarks results of clojure and other langs do you know any good source of info. ? i usually was using http://shootout.alioth.debian.org/ but no clojure code there :(

20:10 Puzzler: Hmmm, I wonder if there is a clever way to use futures to return immediately, like a delay, but continue building the tree immediately on a separate thread.

20:11 I haven't seen much benchmarking of Clojure.

20:11 I have been impressed with its speed overall.

20:12 I LOVE the persistent vectors.

20:16 qwert666: Puzzler: ye but i think it would beat few langs anyway :) and it would be nice to compare the speedup of clojure from a perspective of time

20:22 Puzzler: i think that the fib example from clojure is quite good

20:22 0.044ms for fib 35

20:30 dnolen: Puzzler: you are right about tree walking it does present a problem in Clojure, that's where tree-seq helps.

20:30 ,(doc tree-seq)

20:30 clojurebot kaput?

20:30 clojurebot: "([branch? children root]); Returns a lazy sequence of the nodes in a tree, via a depth-first walk. branch? must be a fn of one arg that returns true if passed a node that can have children (but may not). children must be a fn of one arg that returns a sequence of the children. Will only be called on nodes for which branch? returns true. Root is the root node of the tree."

20:42 Puzzler: I haven

20:42 I haven't played around much with tree-seq.

20:42 I think I need a convenient, lazy way to *construct* trees, however.

21:35 * Raynes needs to figure out how to use JPopupMenu

21:38 Raynes: I usually feed off of Clojure Swing examples but it seems virtually no one has used JPopupMenu within Google Space.

Logging service provided by n01se.net