#clojure log - Jul 09 2009

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

1:43 sayyestolife: hm

1:44 I might have missed something; but wouldn't it be nice of the api doc had some concrete examples?

2:04 arbscht_: sayyestolife: have a look at http://clj-doc.s3.amazonaws.com/tmp/doc-1116/index.html

2:04 oops, I meant http://java.ociweb.com/mark/clojure/article.html

2:05 but yes, it would be nice if the api doc had examples :)

2:07 ah, this has progressed somewhat too: http://en.wikibooks.org/wiki/Clojure_Programming/Examples/API_Examples

2:09 sayyestolife: thanks

3:14 hmm in python and c++ (and in other languages aswell) you can specify a default value for function parameters; is there a way to do this in clojure too?

3:15 like "void func(int x=0) { return x; }"

3:16 hoeck: sayyestolife: sometimes I'm using arity overloading to specify default arguments

3:16 arbscht_: not in the params vector, but you can rebind with (let [x (or x 0) ..] ..) in the function body

3:16 hiredman: arity or hash destructuring

3:16 sayyestolife: hmm, no thanks then; that is too much work for something so simple :)

3:17 hiredman: *shrug*

3:18 ,((fn this ([a] (this a 1)) ([a b] (+ a b))) 3)

3:18 clojurebot: 4

3:19 Riecon: pretty much the same way they do it in java right?

3:22 hiredman: ,((fn [{:keys [a] :or {a 1}}] a) {:a 2})

3:22 clojurebot: 2

3:22 hiredman: ,((fn [{:keys [a] :or {a 1}}] a) {:b 2})

3:22 clojurebot: 1

3:23 hiredman: except people don't use much hash destructuring it seems

3:23 :(

3:44 Riecon: I donno, I'm a fan :)

3:44 although I use it in lets alot

5:46 sayyestolife: hm

5:47 If I want to pass an argument when I create a java class instance, how do I do that? I tried (new MyClass arg), but it didn't work

5:55 eh, found the error

5:55 how does one reload an opened file?

6:04 ehm

6:04 isn't is possible to add a directory on the classpath?

6:16 ceninan: sayyestolife: don't know if java supports dir in classpath, but either way a shell script could do it

6:18 Raynes: sayyestolife: java -cp <dir>/

6:20 eevar: someone able to help me speed up http://pastebin.com/d64ca3d98 ?

6:40 sayyestolife: anyone here used clojure-mode in emacs?

6:41 arbscht_: I use it

6:42 sayyestolife: How do I make it start automatically when editing .clj files?

6:44 eevar: (add-to-list 'load-path "/path/to/clojure-mode") (require 'clojure-mode) ;; in your .emacs should do?

6:45 sayyestolife: eevar I still have to do a M-x clojure-mode each time I open a new file

6:46 asbjxrn: (setq auto-mode-alist

6:46 (cons '("\\.clj$" . clojure-mode)

6:46 auto-mode-alist))

6:48 sayyestolife: nice, thanks

6:48 one more thing though; how do I make the connection between emacs and the clojure program?

6:48 (the interpreter)

6:49 asbjxrn: eevar: Add a type hint for the image var in the render-frame function.

6:49 eevar: you'll need swank-clojure and slime, if I understand your question correctly

6:49 asbjxrn: how? :)

6:50 ceninan: any reason why "(do (print "Enter something: ") (read-line))" waits for the input before printing?

6:50 sayyestolife: hmm okay, what I meant was that I'd like to be able to run the current buffer inside a clojure repl (and all that good stuff)

6:50 asbjxrn: I changed your paste.

6:50 (And paste.lisp.org is nicer, I think...)

6:50 (.setRGB #^BufferedImage image (int x) (int y) (int (+ current-time (* x y)))))))

6:50 eevar: okies, thanks

6:51 yay, way snappier :)

6:52 asbjxrn: I'm not familiar enough with the reflection warnings to understand why there was no reflection warning, though :-/

6:53 sayyestolife: I guess that I need to set the variable 'inferior-lisp-buffer' or something like that?

6:53 eevar: there was (for me) -- i just had no idea where to add the type hint

6:55 asbjxrn: ceninan: it's buffered. Try: (do (print "someting") (flush) (read-line))


6:56 sayyestolife: eevar I'm just trying to use the Clojure -> Eval region command (inside clojure-mode)

6:56 ceninan: asbjxrn: thanks :)

6:56 asbjxrn: sayyestolife: Yes, you need to set that. And then M-x run-lisp

6:59 eevar: sayyestolife: here's my ~/.emacs -- http://pastebin.com/m2e181d8d

6:59 could probably be better, but C-c C-c does eval a sexp once i've started slime

7:01 asbjxrn: slime is more complex, which is good and bad.

7:02 More features, and more trouble :)

7:16 Raynes: I use a very small subset of Slime's features.

8:32 Chouser: that's actually a pretty good tag line. "Slime: more features, more trouble"

8:36 asbjxrn: I think slime is great for Common Lisp (Well, I used Lispworks myself, but still) But clojure is not quite a perfect match.

8:42 rhickey: Chouser: :)

8:49 AWizzArd: Is there in contrib (or just somewhere) a text/repl based stepper?

8:50 I got jswat working, but it shows way too much variables, everything the jvm has on its stack. I can't see the Clojure data in the way I am thinking about it, but instead deeply hidden in some collections of collections of collections of ...

8:55 sddiew: what is the best way to assoc in nested vector? (similar to assoc-in for maps)

8:57 AWizzArd: update-in maybe?

8:57 sddiew: wait, it seems that assoc-in works for vectors as well! (but it's not documented)

8:58 rhickey: AWizzArd: IntelliJ has intelligent Java collection displays, which show e.g. maps as key-> val entries, show collection sizes etc, without showing the internals (by default) This all works for Clojure collections as well

8:58 ,(doc assoc-in)

8:58 clojurebot: "([m [k & ks] v]); Associates a value in a nested associative structure, where ks is a sequence of keys and v is the new value and returns a new nested structure. If any levels do not exist, hash-maps will be created."

8:59 rhickey: ,(associative? [1 2 3])

8:59 clojurebot: true

8:59 sddiew: ok :)

9:00 rhickey: sddiew: some of these things are doc'ed in terms of abstractions (as opposed to enumerating all supported types) specifically so they are still true when extended

9:01 sddiew: perfect, because of that "...hash-maps will be created." I thought it's maps-only

9:02 rhickey: sddiew: right, maps are hardwired as the default constructing type, there has to be one

9:02 sddiew: is there any other (even more concise) way to get value from nested vector? better than eg: (reduce get [[[[:x]]]] [0 0 0 0])

9:03 Chouser: hm, it could use (empty coll) instead.

9:03 sddiew: something like a reverse -> macro that would expand to (((some-vector id) id) id)

9:04 I know that I can use (-> some-vector (get id) (get id) ...) but...

9:07 sayyestolife: I'm using ClojureBox, and when I evaluate an expression (with C-x C-e) several times I get the error java.lang.reflect.InvocationTargetException

9:07 rhickey: Chouser: empty the root coll? the problem is the assoc of a new vector will only work for index == count

9:07 ,(doc get-in)

9:07 clojurebot: "([m ks]); returns the value in a nested associative structure, where ks is a sequence of keys"

9:08 sddiew: oh ;) perfect!

9:08 rhickey: ,(get-in [[[42]]] [0 0 0])

9:08 clojurebot: 42

9:08 sddiew: that's just great

9:10 rhickey: Chouser: begs the question as to whether index of -1 should mean "at end"

9:10 clojurebot: Who??

9:12 Chouser: rhickey: hm... well, that question has certainly come up before.

9:17 rhickey: it doesn't quite work for this, as ([0 1 2 3] -1) == ([0 1 2 3] 3), but what you want for blinds assoc-at-end is (assoc [0 1 2 3] -1 x) == (assoc [0 1 2 3] 4 x)

9:17 Chouser: I always found that natural and convenient in python and ruby

9:17 oh. hm.

9:18 rhickey: maybe we need conj-in?

9:18 Chouser: not interested in -0 ?

9:18 :-)

9:18 * rhickey tried -0

9:18 Chouser: oh, really? for this or something else?

9:18 sddiew: what would be equivalent to delete-in/remove-in for nested associative structures?

9:18 clojurebot: for is not a loop

9:19 rhickey: just tried typing it in, not a concept I desire (-0)

9:19 Chouser: oh

9:19 rhickey: ,(doc dissoc-in)

9:19 clojurebot: "clojure.contrib.core/dissoc-in;[[m [k & ks as keys]]]; Dissociates an entry from a nested associative structure returning a new nested structure. keys is a sequence of keys. Any empty maps that result will not be present in the new structure."

9:19 sddiew: wow! amazing :)

9:19 Chouser: yeah, I wouldn't have expected you to like the concept of -0

9:20 sddiew: that's why i couldn't find it (contrib), any chance that it would land in core soon?

9:21 rhickey: sddiew: which?

9:21 sddiew: dissoc-in

9:21 rhickey: that's in core

9:21 sddiew: i mean clojure.core (I know that it's in c.c.core)

9:22 sayyestolife: how can I recompile a file inside SLIME? (atm when I try to compile via C-c C-k it complains about stuff being declared/defined more than once)

9:22 rhickey: that should be moved

9:22 patch welcome

9:23 issue/patch

9:24 sddiew: hmm so I guess conj-in or similar is welcome as well

9:24 rhickey: conj-in has slightly murky semantics - is it assoc-in except for the last step?

9:25 sddiew: sould insert at the n+1 position (for vectors at least)

9:25 rhickey: conj will mean what it does (per collection type) the issue is the inner steps

9:26 Chouser: would it conj anytime an inner step exceeds the length of the vector at that step?

9:26 rhickey: would prefer not to think about vectors specifically

9:26 Chouser: so an error in those cases

9:26 sddiew: by the way, how to insert element in the middle of a vector? assoc and some subvec (n to the end) merged?

9:28 rhickey: Chouser: I'm trying to think about what conj-in means

9:28 I think it's maybe not a valid concept

9:28 sddiew: maybe just get-in and conj on the last element? (if it's a collection)

9:28 rhickey: ,(doc update-in)

9:28 clojurebot: "([m [k & ks] f & args]); 'Updates' a value in a nested associative structure, where ks is a sequence of keys and f is a function that will take the old value and any supplied args and return the new value, and returns a new nested structure. If any levels do not exist, hash-maps will be created."

9:29 rhickey: might be enough

9:29 Chouser: if it just conj's as the last step, then (conj-in v [0 0 0] :b) is just (update-in v [0 0] conj :b)

9:29 rhickey: heh

9:31 sddiew: so, speaking REST verbs: GET would be get-in, DELETE is dissoc-in PUT is assoc-in POST is update-in f?

9:31 asbjxrn: sddiew: (let [foo (range 20)] (concat (take 10 foo) ['insertedelement] (nthnext foo 10))) kind of works.

9:32 Uh, not a vector...

9:32 rhickey: sddiew: that's one way to think about it, I guess, but post really changes something and update-in doesn't

9:32 Chouser: so does that invalidate using (empty root-coll) for assoc-in and update-in?

9:32 sddiew: asbjxrn: yeah (vec ...) would do

9:33 Chouser: or just that it remains less useful on vectors because you have to know the length at steps where you'd want to conj

9:33 rhickey: Chouser: there really isn't any more reason to match the root coll than there is to hardwire a map, and maps are easier to create from scratch using assoc

9:34 Chouser: ok

9:34 rhickey: e.g. if the root is a vector of maps

9:34 Chouser: I don't know that I've ever used the new-collection feature of either fn

9:35 rhickey: I think the most common case is maps of maps of ...

9:36 Chouser: so I've been building up a set of functions for interacting with git and assembla and have most of what I need to automate various patch-wrangling tasks (still missing "attach to ticket")

9:36 but then this task of creating a new ticket when committing, all in one step, came up.

9:37 sayyestolife: Can any nice person here please try to tell me what is wrong the following code (it's pretty short): http://pastebin.com/d5aad3b91 ?

9:38 asbjxrn: Works fine for me.

9:38 sddiew: is there any simple way to extend clojure writer to put ',' between elements in a vector? what i'm trying to do is to emit valid JSON array from nested vector with strings, reading that in would be straightforward (commas omitted, null would be symbol bound to nil), is that a good idea?

9:38 Chouser: and I was disappointed to find that I was nowhere close to being able to do it with these functions. This case is just different enough that it misses all the apis I've created, and runs into java api areas where I'm weak. A couple hours of hacking at it and I only had the first of 5 or so steps working.

9:39 sayyestolife: asbjxrn okay, damn it :/, my biggest problem with clojure isn't the coding but to get an actual (usable) environment up and running :(

9:39 danlarkin: sddiew: there is a json library you can use in contrib

9:40 Chouser: so last night I spent a couple hours working on the same task as a bash script, and it's already nearly done. Plus it runs faster (because no jvm startup hit). This all makes me a bit sad.

9:40 sddiew: yes I know, but all i need is nested vector with strings, I guess 'read' would be much simpler here (and faster)

9:40 read-string actually (and catching eventual exceptions)

9:41 danlarkin: Chouser: yeah clojure doesn't fit every domain

9:41 nor will it ever, I guess

9:41 asbjxrn: Chouser: I'm a Unix admin. I know how you feel. Really want to use clojure for stuff, but ....

9:44 The one "scripting" niche I found for it was visualization of various stuff by using jfreechart.

9:46 sddiew: somebody (hmm, me?) should put online applet or java web startable waterfront or similar +clojure/clojure-contrib, would make clojure much more accessible for newbies

9:46 Chouser: I know it's popular to say "use the right tool for the job" and apply that to languages and domains, but I tend to believe that's more an idictment of existing languages than any kind of fundamental property of reality.

9:49 a general-purpose language should not be like a hammer or screwdriver, it should be like a stack of iron ingots and a forge.

9:49 mattrepl: with languages, sometimes being the right tool means having the right library

9:49 danlarkin: Chouser: to some extent, I suppose. But even if the JVM start time was a non factor, and even if clojure had easy access to idiomatic shell scripting libraries, writing a shell script would still be a better choice a lot of the time. Sure you can make a "dsl" for what you want to do, but sh is already the dsl

9:50 Chouser: danlarkin: but the sh dsl carries a whole lot of baggage with it. some good, and of course that's why it fit well in this case. but some very bad.

9:51 asbjxrn: But isn't that the whole point of the "right tool for the job" saying?

9:52 Chouser: why should I put up with bad baggage?

9:52 asbjxrn: Because you don't care.

9:52 Chouser: but I do!

9:53 this bash code I wrote has the most horrible string manipulation code blocks

9:53 asbjxrn: You shouldn't :)

9:53 danlarkin: Chouser: love it for what it is :)

9:53 mccraig: Chouser: 'cos all baggage is bad baggage

9:54 Chouser: I reject all your assertions!! :-) I want all the good features of all the languages in a single language, and nobody's yet proved to me that it's impossible.

9:54 asbjxrn: scripts very quickly become the wrong tool for the job. But for small jobs..

9:55 Chouser: asbjxrn: that's actually a key point. "small jobs" very frequently don't stay that way, and yet you find yourself saddled with whatever language choice was made initially.

9:55 pjstadig: the more general a language is the less useful

9:55 asbjxrn: Ah, but that just means the job changed...

9:56 mccraig: Chouser: i'm not saying it's impossible, just that languages are like species : constantly evolving and yet never perfectly adapted to an ever changing environment

9:56 pjstadig: if a language does everything, then it really does nothing, and you have to do a *lot* of work to turn those ingots into something useful

9:56 Chouser: hmph.

9:56 asbjxrn: ps -ef | awk '/styp\id proc/ {print "kill " $2}' | sh

9:56 is a "program"

9:57 danlarkin: in the oh-so-powerful sh dsl :)

9:58 asbjxrn: And when running this I don't care if awk doesn't do closures or referential transparency.

9:58 newbie: hey all, when i execute this for loop in repl i get nil printed as well besides the number (for [y (range 0 100)] (println y ) ) am i doing it wrong or is this the behaviour?

9:59 Chouser: ~for

9:59 clojurebot: for is not used enough

9:59 Chouser: wrong!

9:59 ~for

9:59 clojurebot: for is not a loop

9:59 Chouser: there you go

9:59 newbie: 'for' is not meant for side-effects. It's lazy.

10:00 pjstadig: ,(for [y (range 1 100)] (println y))

10:00 clojurebot: (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)

10:00 asbjxrn: ,(doc for)

10:00 clojurebot: "([seq-exprs body-expr]); List comprehension. Takes a vector of one or more binding-form/collection-expr pairs, each followed by zero or more modifiers, and yields a lazy sequence of evaluations of expr. Collections are iterated in a nested fashion, rightmost fastest, and nested coll-exprs can refer to bindings created in prior binding-forms. Supported modifiers are: :let [binding-form expr ...], :while test, :when test.

10:00 Chouser: newbie: so what's going on there is your 'for' is producing a lazy seq of whatever println returns (nil for each number)

10:01 ...but when the repl prints that seq of nils, it has to realize each value which cause the side-effect of println (actually printing the number) to happen at each step

10:02 newbie: so you have to decide if you actually want the side-effect (in which case use 'doseq') or if you want to produce a lazy-seq (use 'for' but get rid of the println)

10:02 mattrepl: newbie: (doseq [x (for [y (range 1 100)] y)] (println x))

10:02 Chouser: huh

10:04 newbie: what i am trying to do is iterate over x and y values ( coordinates ) i tried doseq but when i have for inside a for it only prints nil?

10:05 Chouser: ,(for [x (range 3), y (range 3)] [x y])

10:05 clojurebot: ([0 0] [0 1] [0 2] [1 0] [1 1] [1 2] [2 0] [2 1] [2 2])

10:07 sddiew_: so, string is not associative, is it a bug in get-in?

10:08 Chouser: ,(get-in ["abcde"] [0 3]) ; like this?

10:08 clojurebot: \d

10:09 sddiew_: ,(associative? "abcde")

10:09 clojurebot: false

10:09 newbie: one last question how can i call a function using these x y values?

10:09 sddiew_: sure it is ok for ordinary get

10:10 Chouser: ,(for [x (range 3), y (range 3)] (+ x y))

10:10 clojurebot: (0 1 2 1 2 3 2 3 4)

10:11 newbie: this maybe a stupid question but how can i call + on x y but not println?

10:12 Chouser: do you mean "why?" because + has no side-effects, but println does.

10:13 asbjxrn: newbie: You can still call println, but println will only return nil, the printing is a side-effect. So collecting the result of a println only gives you nil.

10:15 you could use println-str instead:

10:15 ,(for [x (range 3) y (range 3)] (println-str x y))

10:15 clojurebot: ("0 0\n" "0 1\n" "0 2\n" "1 0\n" "1 1\n" "1 2\n" "2 0\n" "2 1\n" "2 2\n")

10:15 Chousuke: newbie: for is not a looping construct, it's a list comprehension :)

10:15 newbie: ok now i get the nil is the return value of print and numbers are written inside print thats the reason i am seeing nil, am i right?

10:16 asbjxrn: right

10:17 newbie: coming from java i picked for because thats what i am used to but if you were to iterate a bunch of x y coordinated and do some calculation on them which looping construct would you use? is using for in this case a wrong thing to do?

10:18 mblinn: depends on what you're trying to do

10:18 there are a lot of higher level functions that help with that sort of thing

10:18 map, reduce, etc

10:18 so uh, what are you trying to do :-)

10:19 newbie: i will iterate each pixel on a panel and depending on the coordinates paint a dot on its location

10:20 Chousuke: then you need to use doseq or loop

10:22 newbie: thank you all.

10:24 asbjxrn: What is the reasoning for the [{a :a b :b :or {a 1 b 2}}] destructuring? Why isn't the "or hash" {:a 1 :b 2}?

10:25 Chousuke: asbjxrn: the a, b, are the names you bind to, and the :a, :b are the keys you use to look up the names.

10:26 in the :or hash, there's no need for the lookup keys, only the names to bind to.

10:26 asbjxrn: Right. But then I would have thought it would have been {a :a b :b :or [a 1 b 2]}

10:27 Chousuke: I guess it could be {:a 1 :b 2} too, as in, the default map to destructure.

10:29 asbjxrn: Right, that's the way I was thinking. Doesn't really matter since it's a special case anyway, but I found it a bit funny.

10:29 thickey_: isn't it {} instead of [] for lookup reasons when it uses the :or? i.e. it's looking up the value associated with a

10:29 Chousuke: but you could have something like [{a "foo" b 0 :or {a 2 b 3}}] which is a bit clearer that :or {"foo" 2 0 3}

10:31 asbjxrn: Right, that's a good point.

10:34 thickey_: Ah, maybe the local vars is built up by starting with the "or hash" and assoc'ing the rest of the keys/values? (No, I haven't read the source, and I suspect that local vars may not be stored in a hash like that...)

10:35 (BTW: What's the right name in this case? "vars" is obviously wrong as it has a special meaning.)

10:35 Chouser: locals

10:36 :-)

10:36 ,(macroexpand '(let [{a :a b :b :or {a 1 b 2}} nil]))

10:36 clojurebot: (let* [map__2197 nil a (clojure.core/get map__2197 :a 1) b (clojure.core/get map__2197 :b 2)])

10:37 sddiew_: ,(get-in [:a [:b]] [1 0]) ; works

10:37 clojurebot: :b

10:37 sddiew_: ,(dissoc-in [:a [:b]] [1 0]) ; fails, bug?

10:37 clojurebot: java.lang.Exception: Unable to resolve symbol: dissoc-in in this context

10:38 sddiew_: provided that dissoc-in was use-d

10:38 Chousuke: I don't think that's a bug

10:38 vectors don't support dissoc

10:38 asbjxrn: ,(macroexpand '(let [{a :a b :b :or {a 1}} {:b 2}]))

10:38 clojurebot: (let* [map__2207 {:b 2} a (clojure.core/get map__2207 :a 1) b (clojure.core/get map__2207 :b)])

10:39 sddiew_: I guess I should use update-in instead but... one level up?

10:41 it's a bit inconsistent with the rest of -in functions that work on associative structures

10:45 is there a better way to 'remove' item from a vector than concat+take/drop or concat+subvec?

10:45 Chouser: maybe (into (subvec ...) (subvec ...))

10:46 sddiew_: which would be fastest? :)

10:46 Chouser: I think the meaning of that is pretty clear, and using into,subvec like that is O(n) where n is the length of the second subvec

10:47 sddiew_: subvec is much faster than take/drop (that work on sequences so O(n)) but how about into vs concat etc.?

10:47 Chouser: if you want a vector in the end, you're not going to do better than O(n) as with the into

10:48 sddiew_: hmm, yes, I want vector, too bad that there is no dissoc for vectors :(

10:48 Chouser: the underlying data structure simply doesn't support that

10:49 sddiew_: hmm is it some kind of trie?

10:49 Chouser: indeed

10:50 sddiew_: ok I guess I have to live with that (much better and more performant for most other problems though)

10:58 rhickey: persistent finger trees would be a welcome contribution

10:59 Chousuke: hm, I vaguely remember seeing someone working on an improved persistent map data structure on github

10:59 I wonder what that was.

11:29 sayyestolife: hm

11:29 I can do a (require 'myfile) but a (require :reload 'myfile) fails due to (reflect.InvocationTargetException), any ideas?

11:34 drewr: I think I like defnm better than defn-memo

11:38 good work, btw :-)

11:42 Chouser: defn-memo too wordy?

11:46 drewr: for me, but I like brevity to the extreme

11:50 Chousuke: I'd go with defn-memoize :P

11:50 though memo is fine too

11:51 unnecessary abbreviation is the root of all evil.

11:51 drewr: it's actually unnecessary unabbreviation :-)

11:51 Chousuke: not to mention that defnm is unpronounceable.

11:52 sddiew_: clojure is not arc ;)

11:52 drewr: sddiew_: I *like* that aspect of arc...

11:52 Chousuke: seriously, though, I wish people didn't always abbreviate things so much

11:52 it just makes stuff unreadable.

11:52 drewr: it's the other way around for me

11:52 clojurebot: for is not a loop

11:53 Chousuke: defnm is so close to defn that it looks like a typo.

11:53 Chouser: I didn't use defn-memoize because memoize is a verb and ends up in the wrong place there

11:53 maybe def-memoize-fn :-P

11:53 drewr: Chousuke: defn- is too

11:54 sayyestolife: excuse the language but, holy shit it feels good when you make stuff work by yourself :)

11:54 Chousuke: drewr: yeah, but in that case there's a convention

11:54 drewr: - = private

11:54 sddiew_: hm, maybe the way to go is to create abbreviations, similar to call-with-current-continuation => call/cc

11:54 Chouser: I didn't use defmemo because I didn't want to lose the fn in there

11:54 drewr: Chousuke: I'm trying to shape future conventions :-)

11:54 clojurebot: drewr: the fn created by future (like all fns) doesn't close over dynamicly scoped stuff

11:54 Chouser: hah!

11:54 drewr: clojurebot: shut your hole

11:54 clojurebot: excusez-moi

11:54 Chousuke: clojurebot is chatty today :p

11:55 Chouser: I stuck the dash in there becase the nm together in defnmemo makes my eyes go buggy

11:55 all of which matters to me a bit less than the little race condition in my definition

11:56 drewr: you guys put way too much stock into what looks immediately "right"

11:56 what matters is what you type over and over again

11:57 (not that defn-memo) will be as popular as defn

11:57 sayyestolife: well, I've heard that you often write code once but look at it a thousand times

11:57 Chouser: but I think that's ok too because even if you're calling defn-memo to redef an existing var, if something calls it in the race state you just get the un-memoized new version, which shouldn't hurt anybody too much

11:57 drewr: that close paren should have been at the end

11:58 sayyestolife: I've never understood that argument; once you know what stuff means, it makes sense

11:58 Chousuke: drewr: I still don't like looking at alphabet soup

11:58 drewr: unmaintainability comes in when you make fns too big and don't modularize properly

11:59 Chousuke: drewr: having proper names for things helps with being able to discern them quicker amid other code.

11:59 Chouser: I'm glad it's defn not define-function

11:59 drewr: yes

11:59 Chouser: seeing that written out wouldn't help me one whit

12:00 drewr: "defnm" has a distinct flavor to it; I would get used to it

12:00 Chousuke: well, it's something you write very often.

12:00 Chouser: Chousuke: exactly

12:00 and read often

12:00 and it has a whole lot of character of its own

12:00 drewr: I will concede since I don't then to memoize very often

12:00 Chousuke: defn- is fine because it's basically defn

12:01 Chouser: memoizing a fn is not terribly common, and the word "memo" conveys a whole lot of meaning that "m" doesn't

12:01 drewr: I always do a double-take at defn-

12:01 Chousuke: defnm is also basically defn, but the m is not a convention for "memoize" so it fails

12:02 drewr: wow, s/then/tend/ up there

12:02 Chousuke: and the thing that it's easy to typo defn into defnm

12:02 and then you won't be able to tell whether that's intended or not.

12:02 Chouser: it's a bit unfortunate that (defn- foo ...) and (defn -foo ...) are both valid and mean very different things. ...not that I have any better alternatives to suggest. :-P

12:04 Chousuke: I'm just saying that if you do abbreviations that are not conventions, they must be *obvious* :)

12:04 m is not.

12:04 drewr: I screw code up no matter what; I prefer brevity so I can screw it up more quickly and be done

12:04 Chousuke: typing a couple fewer characters won't make you code faster.

12:04 drewr: Chousuke: fair point

12:05 Chousuke: no-one codes as fast as they type, anyway

12:05 drewr: the above point

12:05 Chousuke: if they do, something's wrong :)

12:05 drewr: I dunno, with clojure I can bust out a thought pretty quickly

12:05 sddiew_: how about defnemo ;)

12:06 drewr: defnoize

12:06 has a nice ring to it

12:06 defn01ze

12:06 sddiew_: :)

12:06 Chousuke: or for the british, defnoise

12:18 guille_: hi

12:18 what do you use for taking a look to javadocs from clojure-mode?

12:53 sayyestolife: I know that Clojure uses STM (I'm not very familiar with that), but I'm making a server and obviously I'd like to server a lot of people at the same time; should I still use java threads?

12:53 Chousuke: Threads and STM are not mutually exclusive :)

12:54 in fact, without threads the STM would be rather useless.

12:54 rhickey: has anyone tried the ensure branch?

12:54 cemerick: sayyestolife: STM allows you to write programs that have reliable semantics in a multithreaded environment.

12:54 sayyestolife: heh, so threads is the way to go in this case?

12:54 Chousuke: but instead of using threads explicitly you might be able to use agents, too

12:54 sayyestolife: agents you say, I better look that up, thanks :)

13:01 I might be stupid but I didn't really get http://clojure.org/agents, do any of you have some other resources regarding agents?

13:02 cemerick: rhickey: Since you're not on twitter, FYI: https://twitter.com/headius/status/2552807823

13:03 rhickey: cemerick: I'm on twitter, I just don't follow anyone or say much :)

13:03 very interesting though, thanks

13:05 must be nice to work at Sun and get the things you need :)

13:09 moving it into Java 6 greatly enhances the viability

13:29 drewr: sayyestolife: think of agents as refs that don't get updated immediately

13:30 and aren't transactional

13:30 sayyestolife: mkay, (another, unrelated question) is there an easy way to have a variable parameter list such as in python where you can retrieve all of the argumentsin a list?

13:31 drewr: yes, that's what [... & args] does when you see it

13:31 args is a seq of the remaining parameters

13:32 sayyestolife: oh I see

13:32 thanks

13:33 drewr: ,((fn [a b & c] c) :foo :bar :baz :quux)

13:33 clojurebot: (:baz :quux)

13:43 sayyestolife: I might be totally out there but; when I have a list of items I'd like to print, wouldn't a map do the job?

13:43 I tried with (map #(print (str %)) args) but it didn't print anything at all

13:44 cemerick: rhickey: the notion of it requiring a flag *and* an rt.jar addition is less than ideal.

13:47 ceninan: sayyestolife: why not use doseq?

13:47 ,(doseq [x [1 2]] (println x))

13:47 clojurebot: 1 2

13:48 sayyestolife: ah thanks

13:52 cemerick: sayyestolife: map is lazy, which is why nothing was printed. see doall

13:52 ,(doall (map println (range 5)))

13:52 clojurebot: (nil nil nil nil nil)

13:52 0 1 2 3 4

13:52 cemerick: but yes, doseq is more idiomatic

13:55 maacl: I have a recursive call like this inside a traceback-lcs function (traceback-lcs m s1 s2 (- i 1) (- j 1)) (nth s1 (- i 1)). The call generates the return value of the function. If s1 is a string i can just coerce the whole thing into a string and get a sensible return value that way, but the rest of the traceback-lcs function works on all ordered collections. How do I coerce this into returning a collection of the same class as s1?

14:03 Chousuke: maacl: hm, please clarify. instead of one call, you wrote two separate expressions :)

14:03 but maybe something like this

14:05 ,(let [f (fn [coll] (into (empty coll) [1 2 3 4]))] [(f {}) (f [])]

14:05 clojurebot: EOF while reading

14:05 Chousuke: oops

14:05 ,(let [f (fn [coll] (into (empty coll) [1 2 3 4]))] [(f {}) (f [])])

14:05 clojurebot: java.lang.IllegalArgumentException: Don't know how to create ISeq from: Integer

14:05 Chousuke: hm

14:05 maacl: sorry missed a paren at the end. when coercing to a string it looks like this: (str (traceback-lcs m s1 s2 (- i 1) (- j 1)) (nth s1 (- i 1)))

14:07 Chousuke: hm

14:10 now I'm more confused as to why my example gives that error.

14:11 :o

14:11 ,(empty {})

14:11 clojurebot: {}

14:11 Chousuke: ,(into (empty {}) [1 2 3 4])

14:12 clojurebot: java.lang.IllegalArgumentException: Don't know how to create ISeq from: Integer

14:12 Chousuke: no wonder. :P

14:12 ,(let [f (fn [coll] (into (empty coll) [[1 2] [3 4]]))] [(f {}) (f [])])

14:12 clojurebot: [{3 4, 1 2} [[1 2] [3 4]]]

14:13 Chousuke: anyway, into might do what you want.

14:14 though sadly, it doesn't work for strings

14:15 (doc show)

14:15 clojurebot: "clojure.contrib.repl-utils/show;[[x] [x selector]]; With one arg prints all static and instance members of x or (class x). Each member is listed with a number which can be given as 'selector' to return the member object -- the REPL will print more details for that member. The selector also may be a string or regex, in which case only members whose names match 'selector' as a case-insensitive regex will be printed. Finall

14:15 maacl: thanks - will give it some more thought

14:16 sddiew_: any reason why you use (into (empty {}) ...) and not simply (into {} ...) ?

14:16 Chousuke: sddiew_: well, the actual parameter might not be empty

14:16 ,(let [f (fn [coll] (into (empty coll) [[1 2] [3 4]]))] (f {1 2}))

14:16 clojurebot: {3 4, 1 2}

14:16 Chousuke: bad example, though :P

14:17 ,(let [f (fn [coll] (into coll [[1 2] [3 4]]))] (f {5 6})); if you remove the empty

14:17 clojurebot: {3 4, 1 2, 5 6}

14:17 sddiew_: actually what's the use of empty? and what is the difference between (empty {}) and eg. (identity {})?

14:17 Chousuke: nothing

14:18 ,(empty {1 2}); this case differs however

14:18 clojurebot: {}

14:18 sddiew_: ah ok, in case you want to make empty collection of some type of non-empty one

14:18 Chousuke: useful for polymorphism

14:18 sddiew_: sure sure, I guess I need some sleep ;)

14:46 sayyestolife: I have a function where I call print; this function gets called several times inside a loop, but it isn't until the last call in the loop that everything gets printed. How come?

14:47 kotarak: sayyestolife: try to call (flush) in the loop.

14:47 sayyestolife: mkay

14:48 that fixed it, thanks.

15:11 guille_: does exist a function to convert a symbol to a string?

15:11 kotarak: (doc name)

15:11 clojurebot: "([x]); Returns the name String of a symbol or keyword."

15:11 kotarak: (doc namespace)

15:11 clojurebot: "([x]); Returns the namespace String of a symbol or keyword, or nil if not present."

15:12 guille_: thanks

16:24 j-dot: anyone know what would have changed between 1.0 and now regarding the way Clojure is loaded?

16:24 I'm trying to write an Ant task in Clojure using gen-class and a simple build file works fine with 1.0, but not with HEAD

16:25 lisppaste8: j-dot pasted "Ant task written in Clojure" at http://paste.lisp.org/display/83318

16:25 j-dot: that paste is a stripped down task the exhibits the behavior

16:26 kotarak: Which is?

16:26 j-dot: with 1.0, "Ah-ha" is echoed as expected

16:27 with HEAD, I get the exception I'm annotating on that paste now

16:27 lisppaste8: j-dot annotated #83318 "Exception with HEAD" at http://paste.lisp.org/display/83318#1

16:28 j-dot: mainly, this: "java.lang.IllegalStateException: Var clojure.core/refer is unbound."

16:28 that gets thrown when clojure.zip goes to refer to clojure

16:30 lisppaste8: j-dot annotated #83318 "Example build file for testing the task" at http://paste.lisp.org/display/83318#2

16:31 kotarak: oerk... ugly... but sorry: no clue here.

16:31 j-dot: eh, no worries ... thanks anyway. Maybe I'll send it off to the list

16:33 Chouser: know how to use git bisect? :-)

16:34 j-dot: nope, but I don't expect I'll find a much better time to learn

16:38 Chousuke: it's pretty easy.

16:38 j-dot: ahh, git bisect looks very cool. Thanks, Chouser!

17:07 texodus: Is there any way to add java annotations to clojure proxy functions?

17:11 hiredman: nope

17:17 texodus: tragic

17:19 lisppaste8: guille_ pasted "Trying to emulate normal recursion (without success)" at http://paste.lisp.org/display/83321

17:19 guille_: would you take a look to the paste above about how would i change it to use recur? (from PAIP)

17:20 i've changed the function name by recur, but it seems that you can only call recur from the bottom

17:21 Chousuke: recur only works for tail recursion

17:21 opqdonut: yeh

17:21 Chousuke: if you don't have tail recursion, you can't get the optimisation anyway and need to use regular recursion :)

17:24 guille_: i see. thanks

17:24 Chousuke: but it does look like you could do that without recursion.

17:24 hmm

17:27 but before I go and do that, you should rename variable-p to "variable?".

17:28 guille_: is it not recommended to use -p for booleans?

17:29 hiredman: use ?

17:32 Chousuke: guille_: Clojure follows the Scheme convention that predicates end with ?

17:35 hmm, it looks like your pattern matching algorithm might need to be "truly" recursive after all.

17:36 kotarak: does a zipper help in this case?

17:40 guille_: it's supposed to match more than one word (up to the next word from the placeholder), so actually the "zipper" is the function itself

18:00 Chousuke: guille_: you want something like this? http://gist.github.com/144035

18:01 it's not iterative, but I don't think you can avoid keeping a stack in any case.

18:08 guille_: Chousuke: yes, concise code yours :)

18:08 Chousuke: github screwed up the indentation though

18:08 but the source is my emacs. it's using tabs again

18:08 for whatever reason.

18:08 * Chousuke grumbles

18:09 Chousuke: I'm sure I disabled tabs.

18:12 I even have "(setq indent-tabs-mode nil); Aquamacs is idiotic" at the top of my init.el but it seems to have no effect :-(

18:23 guille_: i switched two days ago from aquamacs to cocoa emacs (in macports "emacs-app-devel") because some problems in latex-mode and I don't regret it. Also sometimes aquamacs decided to close erc buffers when killing the contiguous...

18:27 Chousuke: I might do that too. Though does it have similar support for trickery with the alt key as aquamacs does?

18:28 I need alt-2 to output @ because I have a finnish keyboard layout and no altgr (this being a mac) :/

18:29 guille_: i use in .emacs: (setq mac-command-modifier 'meta) (setq mac-option-modifier nil) so you have meta in command and alt free

18:31 Chousuke: hmm.

19:23 grrrt: I would like to define an event "stream" as a lazy seq. The elements of the seq would be "change" events from, say, a ref (using add-watch to see changes) or a Swing widget (using a ChangeListener or ActionListener for instance). The seq would be blocking, i.e. if you iterate over it, it would wait until new events are available.

19:24 is that a dumb idea?

19:27 ceninan: funny, I had a similiar idea earlier today when playing around with DSLs

19:27 clojurebot: The most exciting phrase to hear in science, the one that heralds new discoveries, is not 'Eureka!' (I found it!) but 'That's funny ...' -- Asimov

19:28 Chousuke: Doesn't java provide a BlockingQueue or something?

19:28 ceninan: far too inexperienced to know if it's a good idea though :/

19:28 grrrt: Chousuke: it does. But I'd like to avoid writing java :)

19:28 unless it's the best way to do it ofcourse

19:29 Chousuke: grrrt: you'd be writing Clojure :p

19:29 just using a java library.

19:29 seqs are persistent, too. do you want to hold onto the events?

19:29 grrrt: hm

19:29 perhaps not...

19:29 Chousuke: though only persistent as long as you hold onto the head.

19:29 grrrt: ah that's good

19:29 I'm not sure yet, still experimenting...

19:30 I'm inspired by a paper about FrTime, about a FRP gui library in scheme

19:30 Chousuke: should others be able to "consume" the events?

19:31 or just see a list of them

19:31 in the latter case, a seq of events them could be useful.

19:31 grrrt: I was thinking, you could have a function that iterates over a seq, consuming events as they appear

19:32 Chousuke: if you consume them, then it's better to have a BlockingQueue I think

19:32 grrrt: Still not sure if that's the way to go, but I'm trying to find alternatives to the classic event callback mechanism

19:32 yeah that sounds sensible

19:32 Chousuke: you can also try using agents.

19:32 ceninan: just a quick newb-question here; could you do what grrrt wants, but somehow "kill" a queue?

19:33 Chousuke: agents queue the actions sent to them automatically.

19:33 grrrt: I'm actually using that already

19:33 I have an 'in-ui' macro that calls Swing's invokeLater

19:33 ceninan: (ie. no more events are accepted)

19:34 grrrt: an agent + queue combination sends the result of whatever's called in the ui-thread to the caller of in-ui

19:35 hm. food for thought, thanks Chousuke

20:36 I often find myself wanting a 'let-default' function, e.g. in situations like this: (let [v (if nil? val) "some default" val])

20:36 is there a better way to do this?

20:37 arbscht_: try (let [v (or val "default")] ..)

20:38 grrrt: that'd work in this case, but I wonder if there's a more general way of doing it (i.e. with predicates other than nil?)

20:39 (let [s (if sequential? arg) arg [arg]) is another one

20:39 - except I'm missing a few () there

20:41 arbscht_: I can't think of a better way to express that

20:41 it seems clear enough as it is

20:41 grrrt: glad I'm not the only one :)

20:42 ok fair enough

21:07 rhickey: (or val default) is the right idiom for nil/non

21:08 grrrt: rhickey: thanks.

21:15 JAS415: is there a way to tell (in java) if a class is a subclass of another class

21:16 grrrt: instanceof would do it

21:16 ("hello world" instanceof String) == true

21:17 JAS415: what if I have something like 'clojure.lang.LazilyPersistentVector' and 'clojure.lang.IPersistentVector'?

21:18 grrrt: ,(doc isa?)

21:18 clojurebot: "([child parent] [h child parent]); Returns true if (= child parent), or child is directly or indirectly derived from parent, either via a Java type inheritance relationship or a relationship established via derive. h must be a hierarchy obtained from make-hierarchy, if not supplied defaults to the global hierarchy"

21:18 JAS415: and i want to dispatch depending on whether a metadata tag is a subclass of 'clojure.lang.IPersistentVector'

21:18 oo cool

21:18 that would do it

21:24 ataggart: so, I need to modify the last segment in a variable-length list of values. e.g., '("a" "b" ) --> '("foo" "baz"). Is there a better way than something like (cons new-val (drop 1 (reverse orig-list)))

21:24 oops

21:24 that example should be ("a" "b" "c") --> ("a" "b" "d")

21:26 grrrt: ataggart: instead of using drop/reverse you could use the butlast function

21:27 ataggart: yeah I looked at that but couldn't figure out how to append the new value to the end of it

21:28 and my example solution should actually be (reverse (cons new-val (drop 1 (reverse orig-list))))

21:29 which just looks bad to me

21:29 grrrt: ,(concat (butlast ["a" "b" "c"]) ["d"])

21:29 clojurebot: ("a" "b" "d")

21:29 grrrt: that's one option - don't know if that's the best

21:30 ataggart: ah yes that would do it.

21:31 it has to bet better than a double reverse

21:31 thanks!

22:29 JAS415: is there a way to update metadata?

22:29 (and preserve what is already there)

22:33 ,(def alter-meta!)

22:33 clojurebot: DENIED

22:33 JAS415: ,(doc alter-meta!)

22:33 clojurebot: "([iref f & args]); Atomically sets the metadata for a namespace/var/ref/agent/atom to be: (apply f its-current-meta args) f must be free of side-effects"

22:52 JAS415: why would this work at the repl but not in a source file?

22:52 (let [inlining-arity (rule-set (fn [x] (> x 1)))

22:52 set-symbol-inline-arity (fn [& symbols]

22:52 (map (fn [x] (println x) (alter-meta! x #(assoc %1 :inline-arities inlining-arity))) symbols))]

22:52 (set-symbol-inline-arity #'+ #'* #'- #'/ #'< #'<= #'> #'>= #'==))

22:52 (source file at toplevel)

Logging service provided by n01se.net