#clojure log - Oct 29 2009

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

0:04 qed: whats the quickest way to make (a .. z)

0:04 (\a \b \c \d \e \f \g \h..\z)

0:05 hiredman: ,(int \a)

0:05 clojurebot: 97

0:05 hiredman: ,(map char (range 97 (+ 97 25)))

0:05 clojurebot: (\a \b \c \d \e \f \g \h \i \j \k \l \m \n \o \p \q \r \s \t \u \v \w \x \y)

0:05 hiredman: ,(map char (range 97 (+ 97 26)))

0:05 clojurebot: (\a \b \c \d \e \f \g \h \i \j \k \l \m \n \o \p \q \r \s \t \u \v \w \x \y \z)

0:06 hiredman: ,(->> [\a \z] (map int) (apply range) (map char))

0:06 clojurebot: (\a \b \c \d \e \f \g \h \i \j \k \l \m \n \o \p \q \r \s \t \u \v \w \x \y)

0:06 qed: hiredman: thanks

0:06 hiredman: is that the thrush combinator?

0:06 ive never seen it with the >>

0:07 hiredman: sort of

0:07 mwoelker: ,(map char (range (int \a) (int \z)))

0:07 clojurebot: (\a \b \c \d \e \f \g \h \i \j \k \l \m \n \o \p \q \r \s \t \u \v \w \x \y)

0:07 qed: hiredman: what's ->> called

0:07 mwoelker: darn

0:07 hiredman: it could also be the thrush, just slightly different

0:08 ->> puts stuff in the last arg position, -> in the first

0:08 tomoj: wooby: suppose a chain ends in 1

0:08 then it enters an infinite loop of 1's

0:08 hiredman: (function _ arg arg etc) vs (function arg arg etc _)

0:08 tomoj: searching through it for 89 will never terminate

0:08 adityo: ~ good morning

0:08 clojurebot: Pardon?

0:08 adityo: ~good morning

0:08 clojurebot: Huh?

0:09 hiredman: :D

0:09 adityo: :)

0:09 hiredman: ,((comp (partial map char) (partial apply range) (partial map int) list) \a \z)

0:09 clojurebot: (\a \b \c \d \e \f \g \h \i \j \k \l \m \n \o \p \q \r \s \t \u \v \w \x \y)

0:09 tomoj: "ends in 1" is misleading

0:10 because "ends in 1" really means "has an infinite number of ones as a tail"

0:10 wooby: tomoj: thanks, i figured it out earlier

0:10 tomoj: ah

0:10 wooby: tomoj: that's exactly what was happening

0:10 Dawgmatix: any clojure reading material recommendations ? pointers to both code and tuts appreciated

0:11 wooby: tomoj: i fixed and it's running, est. 20 hours to answer :)

0:11 tomoj: I always forget, will counting a lazy seq allow it to be garbage collected as it counts?

0:11 haha

0:11 yeah I expect you have to come up with some clever solution

0:11 hiredman: Dawgmatix: you seen the rhickey videos?

0:11 Dawgmatix: hired yes I saw those

0:12 wooby: tomoj: i wrote a has-89 function that recurs and checks for 1

0:13 tomoj: I just wrote something which returns either 1 or 89

0:13 also seems very slow

0:13 wooby: oh wow, it got it

0:13 renice for the win

0:13 hiredman: http://delicious.com/clojurebot is all the urls pasted to the channel, so you might dig through those

0:14 tomoj: wooby: are you doing (count (filter ..)) ?

0:14 wooby: tomoj: http://gist.github.com/221142

0:14 tomoj: ok, so I guess count will allow a lazy seq to be garbage collected

0:14 wooby: it appears so

0:15 Dawgmatix: thankoo hired

0:15 will look through those

0:15 wooby: tomoj: although an earlier version ran out of memory

0:15 tomoj: I wonder how fast your digits-of is compared to mine

0:15 wooby: tomoj: what does yours look like?

0:16 hiredman: Dawgmatix: all of the urls rhickey pasted are tagged with rhickey or rhickey_

0:17 tomoj: wooby: https://gist.github.com/1b2c0b1a7fb5807caa3d

0:17 my digits is 4 times slower than your digits-of

0:17 I guess because of all the function calls?

0:17 Dawgmatix: okay hired

0:18 tomoj: well, and arithmetic in general

0:19 for some reason I thought math would be faster than dealing with strings

0:20 wooby: you would think

0:20 probably the fastest would be bit shifting

0:20 piccolino: How would one write "(require 'clojure.contrib.str-utils2 :as s])" in the form of :require for use in ns? I am getting compile errors no matter how I try to do it.

0:20 tomoj: but how would you use bit shifting for base 10?

0:21 hiredman: well, uh, you have a dangling ] there

0:21 tomoj: (:require [clojure.contrib.str-utils2 :as s])

0:21 piccolino: Oops, that [ is there in my code.

0:22 Hm. Then it gives me a compile error : No such var: s/map-str.

0:23 hiredman: ,(require '[clojure.contrib.str-utils2 :as s])

0:23 clojurebot: nil

0:23 hiredman: ,s/map-str

0:23 clojurebot: #<str_utils2$map_str__7819 clojure.contrib.str_utils2$map_str__7819@90d0ea>

0:24 hiredman: clojurebot: works on my machine

0:24 clojurebot: http://haacked.com/images/haacked_com/WindowsLiveWriter/IConfigMapPathIsInaccessibleDueToItsProt_1446B/works-on-my-machine-starburst.png

0:24 wooby: tomoj: something along the lines of digit = (number % (int)pow(10,++place))

0:25 piccolino: Hm, OK.

0:25 wooby: tomoj: in a do/while, checking for digit == number where number is the input

0:27 tomoj: oh, wow. when I say 4x slower, that was a math error

0:27 it's more like 40x slower

0:28 but using (int (quot n 10)) instead of (int (/ n 10)) gives a 10x speedup, so now it is 4x slower

0:32 seems like (zero? n) is also significantly faster than (== n 0)

0:33 hiredman: makes sense

0:42 wooby: tomoj: it's weird, you'd really think it would be faster

0:42 tomoj: maybe it just boils down to function size :)

0:43 hiredman: less code to execute is less code

0:43 Hecktor: Is there a builtin function that returns the first not nil item in a sequence?

0:43 tomoj: I guess read-string is very fast on single digits

0:44 and no math involved

0:44 you get all the modulos by powers of ten automatically because it's a string

0:44 hiredman: ,((comp first (partial drop-while nil?)) [nil nil 1 2 3 4])

0:44 clojurebot: 1

0:45 tomoj: hmm

0:45 is there any real difference between (first (remove nil? ..)) and (first (drop-while nil? ..))

0:45 hiredman: huh

0:45 wooby: ,(first (drop-while #(nil? %) [nil nil 1]))

0:45 clojurebot: 1

0:45 tomoj: since you're only asking for the first I guess they do the same

0:46 hiredman: wooby: nil? is a function, you don't need to rewrap it like that

0:46 piccolino: hiredman: Ah, the problem is that map-str was not in str-utils2 1.0-compatible.

0:46 hiredman: tomoj: right

0:46 wooby: hiredman: oh right, thanks

0:46 ,(first (drop-while nil? [nil nil 1]))

0:46 clojurebot: 1

0:46 Hecktor: cool

0:46 somnium: ,(some #(or % %) [nil nil nil 1])

0:46 clojurebot: 1

0:47 hiredman: :(

0:47 qed: hiredman: sorry i lost my buffer

0:47 what is ->>?

0:47 hiredman: ,(some identity [nil nil 1])

0:47 clojurebot: 1

0:47 wooby: fancy

0:47 somnium: I always forget about identity

0:47 tomoj: ,(some identity [nil false nil 1])

0:47 clojurebot: 1

0:47 hiredman: qed: ->> is like -> but it puts the arg in the last spot instead of the first

0:48 (f _ arg2 arg3) vs (f arg1 arg2 _)

0:48 somnium: ,(str (count "identity") (count #(or % %)))

0:48 clojurebot: java.lang.UnsupportedOperationException: count not supported on this type: sandbox$eval__4819$fn__4821

0:48 qed: hiredman: i think i maybe misunderstood how the thrush combinator works

0:48 hiredman: erm

0:48 qed: it reverses computability right?

0:48 wooby: ,(some identity [nil false 1])

0:48 clojurebot: 1

0:48 hiredman: it's like Tax = xa

0:49 qed: I don't know that

0:49 what is T

0:50 hiredman: the thrush

0:50 so (-> a b) = (b a)

0:50 wooby: seems like it's function un-nesting kinda

0:50 qed: hiredman: right, reverses computability

0:51 hiredman: (->> a b) = (b a)

0:51 but (-> a (b c)) = (b a c) and (->> a (b c)) = (b c a)

0:51 wooby: so (->> a b c) = (c (b a)) ?

0:52 hiredman: without args -> and ->> are identical

0:52 qed: i gotcha

0:52 thats a neat little structure

0:52 hiredman: it is

0:52 qed: i like it

0:52 tbh i feel like im sort of cheating by using it

0:53 tomoj: did I read that rhickey doesn't like autocurrying?

0:53 hiredman: you just get this sort of flow data through your functions

0:53 tomoj: well I don't expect you to know whether I read that or not, but I mean, is that true?

0:53 hiredman: tomoj: dunno

0:54 I would love to have autocurrying, that is the main reason I want metadata on functions

0:55 to keep track of arity information

0:55 tomoj: hmm

0:55 what about functions with overloaded arity

0:55 hiredman: it's tricky

0:56 qed: who asked about autocurrying?

0:56 tomoj: <-

0:56 qed: tomoj: http://groups.google.com/group/clojure/msg/d20660b459abffeb

0:56 tomoj: why thank you

0:56 qed: :)

0:59 tomoj: I just noticed the example in clojure.http.resourcefully uses https

0:59 so I guess clojure.http.client can do https? someone was asking about that the other day

1:18 chouser: ~seen maacl

1:18 clojurebot: maacl was last seen quiting IRC, 788 minutes ago

1:21 hiredman: ,(int (/ 788 60 60))

1:21 clojurebot: 0

1:21 hiredman: ,(int (/ 788 60))

1:21 clojurebot: 13

1:21 hiredman: ,(int (/ 788 60 24))

1:21 clojurebot: 0

1:21 hiredman: ,(double (/ 788 60 24))

1:21 clojurebot: 0.5472222222222222

1:21 chouser: hiredman: ah, thanks.

1:21 :-)

1:43 wavis_: ,clojure.contrib.seq-utils

1:43 clojurebot: java.lang.ClassNotFoundException: clojure.contrib.seq-utils

1:43 hiredman: ,(require '[clojure.contrib.seq-utils :as seq-utils])

1:43 clojurebot: nil

1:44 felzix: is there any way to get more information out of a NullPointerException?

1:44 line number would be awesome

1:45 hiredman: depends on what is generating it

1:45 felzix: is there a way to determine that?

1:45 tomoj: I hate when I don't get line numbers

1:45 hiredman: well, if there is a way to get a line number you will get one

1:45 so if you aren't getting one, well, :(

1:46 tomoj: clojure backtraces are largely still mysterious to me

1:46 felzix: I mean, I know the general location of the problem

1:46 hiredman: tomoj: have you seen clojure.stacktrace?

1:46 tomoj: hiredman: no. I will investigate

1:46 I've just been peering at what slime gives me

1:47 hiredman: it may be similar to what you get from slime

1:47 tomoj: bunch of extra crap you don't care about?

1:47 hiredman: I don't use slime

1:47 tomoj: I mean, usually what I would expect to be at the top of the backtrace is buried deep down somewhere

1:47 under a bunch of internal crap

1:49 hiredman: http://gist.github.com/221188

1:49 wavis_: ,seq-utils

1:49 clojurebot: java.lang.Exception: Unable to resolve symbol: seq-utils in this context

1:50 hiredman: wavis_: seq-utils is just an alias for the clojure.contrib.seq-utils namespace now

1:50 tomoj: yeah, like that crap

1:51 hiredman: uh, that is nice cleaned up stack trace

1:51 tomoj: well, when I do something like that in a file, the line number I do it on is not on the top of the trace

1:51 (and sometimes isn't there at all)

1:52 hiredman: I almost always get a line number from a loaded file

1:52 tomoj: for example your second attempt doesn't have a NO_SOURCE_FILE:XX

1:52 hiredman: but if I am just dumping stuff into the repl

1:52 Raynes-: My heavens, how did I ever life without Paredit.

1:52 tomoj: Raynes-: :D

1:53 hiredman: second attempt?

1:53 tomoj: when you just do (e) or whatever it was

1:53 hiredman: (e) is a sort of prettyprinter for *e

1:53 comes with clojure.stacktrace

1:53 tomoj: ooh, I get it

1:53 Raynes: I've never used Paredit before. Just straight Emacs. My life has been empty up until this point.

1:53 tomoj: I thought that was causing another error

1:54 * hiredman tries to think of something that would cause a gnarly stacktrace

1:55 tomoj: https://gist.github.com/9f0155f80915338175ad

1:56 maybe swank is screwing it up

1:57 it doesn't show the file in which the exception occurs at all

1:58 hiredman: well, makes me feel good about not using emacs

1:58 what is the file name?

2:00 tomoj: .../clojure/contrib/json/read.clj

2:00 I changed something around in there to intentionally cause an error

2:00 maybe next time I have a real error with a bad stacktrace I will try it in a pure repl and see if swank is the problem

2:00 if so that really needs to be fixed

2:01 hiredman: maybe talk to technomancy

2:01 tomoj: it seems like the top section of the stacktrace might be missing or something

2:02 so far I have yet to have a nasty debugging session in clojure anyway :)

2:04 * hiredman has had a few

2:05 mikehinchey: tomoj: hit 1 to see the cause

2:05 tomoj: mikehinchey: wat

2:05 mikehinchey: tomoj: on the slime stacktrace screen

2:05 tomoj: yeah I understood

2:05 that was my "wat" of disbelief

2:05 thank you!

2:06 I don't think I ever even read the second restart

2:06 hiredman: I almost always end up with (prn x) and (doto x prn) sprinkled around

2:06 tomoj: I hate when I start doing that

2:06 mikehinchey: I liked it better when the cause was shown on the same screen instead of a "restart"

2:07 tomoj: I'm just happy I can see the cause now at all

2:07 now I just have to figure out how to get slime debuggers for compile errors

3:07 wavis_: does anyone know if there is a library out there for composing math expressions and treating them as numbers?

3:09 for example

3:09 ,(/ (+ 1 (Math/sqrt 5)) 2)

3:09 clojurebot: 1.618033988749895

3:11 wavis_: would instead give just a composed expression

3:11 arsatiki: There's clojuratica for interfacing with mathematica

3:12 wavis_: hmm... does mathematica run headless on linux?

3:12 wooby: silly question, how can i test if a number is whole?

3:13 arsatiki: wavis: I have not used clojuratica myself, but I assume it just uses the mathematica kernel, not the GUI

3:14 wavis_: i will look into that then. thanks!

3:15 i could always do something like (list / (list + 1 (list #(Math/sqrt %) 5)) 2)

3:16 ... or not

3:16 felzix: wooby: You mean test if a float or double is a whole number?

3:17 wavis_: ,(= 0 (rem 4.5 1))

3:17 clojurebot: false

3:17 wavis_: ,(= 0 (rem 4.0 1))

3:17 clojurebot: true

3:17 felzix: you could do (= (int 1.1) 1)

3:17 ,(= (int 1.1) 1)

3:17 clojurebot: true

3:17 felzix: hmm

3:18 nvm..

3:18 ah, duh. (= (int 1.1) 1.1)

3:22 Licenser: ,(= (int 1.1) 1.1)

3:22 clojurebot: false

3:22 felzix: but ,(= (int 1.0) 1.0)

3:22 ,(= (int 1.0) 1.0),

3:22 clojurebot: true

3:23 Licenser: that makes sense

3:23 they have the same value

3:23 felzix: ,(int 1.0)

3:23 clojurebot: 1

3:23 felzix: it just means floats can be usefully compared against integers

3:23 Licenser: side quetion, is there a ofline documentation for clojure?

3:24 and that is good

3:24 felzix: Best I know of is downloading the api html file.

3:24 Licenser: narf

3:25 felzix: wooby: does that answer your question?

3:25 arsatiki: L: you can always use the doc in REPL :)

3:25 Licenser: arsatiki: I know, but it's not as nice as a document you can work with

3:27 wooby: felzix: sure does, thank you

3:27 i don't think i've ever had as much fun programming as i do with clojure

3:27 what's with this language!

3:28 Licenser: wooby: did you try ruby?

3:28 but I agree clojure is fun, yet it gets very frustrating when you start to get java exeptions :/

3:28 arsatiki: true

3:28 wooby: Licenser: yeah :\

3:29 the java interop is awesome but dealing with java stuff comes with its own shenanigans

3:29 Licenser: which is currently the one but issue I have with clojure, that and a sometimes less then helpful documentation

3:29 but it's still a really incredible language

3:30 and considering it is only 2 years old, it is just amazing

3:30 wooby: it really is

3:30 ruby, that's the dynamically typed scala variant isn't it? ;)

3:31 Licenser: teehee I think ruby is older then scala and is't a functional language either

3:32 wooby: i'm kiddn', yeah its much older... but it does have nice functional bits

3:32 stuff just all uses smalltalk names

3:32 Licenser: I know you can do functional programming in ruby me thinks, and it is a joy to program too most of the time

3:33 One thing that gets me sad so is that you have a hard time as soon as you want to do anything in paralell

3:33 Which is the reason why I'm here :P so good that ruby has a horrible concurrency support, I'd have missed a lot

3:37 wooby: is there something like split-between, like for splitting the seq [1 2 3 3 2 1] between 3 and 3 given a comparator like (fn [a b] (== a b))?

3:37 or just (== %1 %2) i suppose

3:38 Licenser: don't forget the # but I#ve no clue

3:39 hiredman: ,(doc split-with)

3:39 clojurebot: "([pred coll]); Returns a vector of [(take-while pred coll) (drop-while pred coll)]"

3:39 wooby: hiredman: it seems like your pred is only fed 1 element at a time though

3:40 hiredman: correct

3:40 Licenser: what would you expect to happen when you encouther [1 2 3 4 3 2 1]?

3:40 wavis_: you could (partition 2 1 %) your list and get the index with which to split the original

3:42 wooby: Licenser: it would return the whole seq

3:43 Licenser: hmm partitioning won't work sice it might partition with 2 3 and then 3 2

3:43 wooby: you have a tricky question

3:44 hiredman: it's not tricky, but the clojure sequence library is designed for laziness, so nothing scans more than one element at a time, so if you want that you have to roll your own

3:44 Licenser: I say reduce is the way

3:44 there you can know the last element

3:44 but it'd be ugly slow I think

3:45 wooby: yeah

3:45 Licenser: hmm actually not soo much

3:45 hiredman: why would you need to know the last element?

3:45 Licenser: as you store the lists in reverse order

3:45 wooby: i'm going with take-while since i'm only concerned about the first chunk

3:45 wavis_: ,(let [l [1 2 3 3 2 1] p (partition 2 1 l)] (split-at (count (first (split-with #(= %1 %2) p))) l))

3:45 clojurebot: java.lang.RuntimeException: java.lang.IllegalArgumentException: Wrong number of args passed to: sandbox$eval--4944$fn

3:45 hiredman: oh

3:45 last as in previous

3:45 Licenser: wavis_: take 1 2 3 4 4 3 2 1 as list it breaks it already

3:45 hiredman: yap

3:47 * Licenser thinks about the line (reduce (fn [list elemetn] (if (= (first list) element) (make a new list) (conj list element)) [1 2 3 4 4 3 2 1])

3:47 Licenser: the make a new list thing is the tricky part but that code would work I think

3:48 wooby: ah, yeah a fold left

3:48 Licenser: I think I slowly get the hang of lisp

3:52 hiredman: ,((juxt :a :b :c) {:a 1 :b 2 :c 3})

3:52 clojurebot: [1 2 3]

3:53 Licenser: ,(doc juxt)

3:53 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)]"

3:53 Licenser: what the hel is a juxta position?

3:55 hiredman: it means, uh, sort of side by side

3:56 ~google define juxtaposition

3:56 clojurebot: First, out of 60900 results is:

3:56 juxtaposition - definition of juxtaposition by the Free Online ...

3:56 http://www.thefreedictionary.com/juxtaposition

3:56 hiredman: yeah

3:58 wavis_: ,(let [l [1 2 3 3 2 1] p (partition 2 1 l)]

3:58 (split-at (inc (count (first (split-with #(not (= (first %) (first (rest %)))) p)))) l))

3:58 clojurebot: EOF while reading

3:59 wavis_: ,(let [l [1 2 3 3 2 1] p (partition 2 1 l)] (split-at (inc (count (first (split-with #(not (= (first %) (first (rest %)))) p)))) l))

3:59 clojurebot: [(1 2 3) (3 2 1)]

3:59 Licenser: ,(let [l [1 2 3 4 4 3 2 1] p (partition 2 1 l)] (split-at (inc (count (first (split-with #(not (= (first %) (first (rest %)))) p)))) l))

3:59 clojurebot: [(1 2 3 4) (4 3 2 1)]

3:59 Licenser: nice

4:00 wavis_: needs more testing, like with zero length seqs etc...

4:00 g'night all

4:03 Licenser: okay very strange question, how can I join the clojure google group w/o a google account?

4:22 bye people

4:22 see you when I'm back home :D

4:23 Fossi: hi

4:32 hiredman: ,(-> (->> [1 2 3 3 2 1] (partition 2) (split-with (comp not (partial apply =))) (map (partial apply concat)) ((juxt identity identity)) ((flip update-in) (juxt first (comp (partial take 1) second)) [0])) (update-in [0] (partial apply concat)) (update-in [1] (comp rest first rest)))

4:32 clojurebot: [(1 2 3) (3 2 1)]

4:32 hiredman: hmm

4:33 ,(-> [1 2 3 3 2 1] (->> (partition 2) (split-with (comp not (partial apply =))) (map (partial apply concat)) ((juxt identity identity)) ((flip update-in) (juxt first (comp (partial take 1) second)) [0])) (update-in [0] (partial apply concat)) (update-in [1] (comp rest first rest)))

4:33 clojurebot: [(1 2 3) (3 2 1)]

4:33 hiredman: flip is not in core though :(

4:35 oh

4:53 tomoj: clojure.contrib.http.agent gives me an InputStream for the response body

4:53 I wrap this in an InputStreamReader and then a PushbackReader

4:53 reading from the PushbackReader gives -1 (eof) immediately

4:53 while if I don't wrap and just read from the InputStream, I get the expected bytes from the response body

4:53 ideas?

4:55 oh, actually, that's not what's happening

4:55 it's just that calling stream inside the handler gives a different input stream, and that input stream eofs immediately for some reason

4:55 hmm

5:22 ordnungswidrig: *knock* *knock*

6:04 Licenser: wow they've free wifi at the airport wooh!

6:06 wooby: wooties

6:07 http://gist.github.com/221336 fruits of the evenings efforts

6:11 adityo: wooby: cool

6:11 arsatiki: wooby: since keywords act as functions, you can just say (map :leg triangles)

6:15 ysmolsky: how to get access to meta reader data from runtime?

6:16 wooby: arsatiki: oh awesome thanks

6:16 ysmolsky: i want to pass function a to a function b and from inside of the function b to read actual reader meta data of function a

6:21 Licenser: clojure is really really dense, I'm impressed I've started to write a map application as web page and it has < 200 lines

6:22 hmm since there are two ways to access map keys (:key map) and (map :key) which is the preffered one?

6:23 ysmolsky: which is read better in the context i guess

6:25 Licenser: hmm so no guideline

6:28 ysmolsky: (defn a [x] x)

6:28 (defn b [fun] (extract real name of "fun", arguments "fun" has, return it))

6:28 (b a) -> {:name "a", :args [x]}

6:28 how do i make function b? :)

6:31 Chousuke: you can get the args via reflection, but you can't get the name in all cases

6:32 (b (fn [] foo)) <- what is the name? :)

6:32 ysmolsky: i need only for non anonymous cases. just cannot figure out how to make without macros.

6:32 arsatiki: ysmolsky: if you have access to the var, then you can find the information inside the metadata

6:33 ysmolsky: i know, but how to access it?

6:33 (defn expand-method [m]

6:33 (let [mmeta ^#'m]

6:33 mmeta))

6:33 gives me exception: Unable to resolve var: m in this context

6:33 Chousuke: that won't work :)

6:34 var takes a symbol as a parameter. it's not evaluated

6:34 ysmolsky: ah.. well, which direction to look for?

6:34 Chousuke: I must first question the purpose of this endeavour ;)

6:35 you really shouldn't depend on the names of things :/

6:35 ysmolsky: ok. answer will be long. i want to make life easy for one who will use my rpc server, so one can pass just functions to the server fun like this:

6:35 (create-jsonrpc {:host "localhost"

6:35 :port "3000"

6:35 :methods [foo bar baz]})

6:36 Chousuke: and they need to know those "foo" "bar" "baz" strings?

6:36 ysmolsky: after that i need to create map like name of function to real functions symbols

6:36 those foo bar are funtcions

6:36 Chousuke: symbols? why symbols?

6:36 why not just the functions? :P

6:37 ysmolsky: oh not symbols, but functions

6:37 just to be able to call them by the "string"

6:37 Chousuke: right. so pass in a map of name -> fn instead

6:38 ysmolsky: i know, but i like challenges :)

6:38 Chousuke: there's no way for you to win this challenge

6:38 arsatiki: or you could pass the vars :methods [#'foo #'bar ...]

6:38 but that is sucky.

6:38 Chousuke: and would fail with anonymous functions.

6:39 just let the user pass in a map

6:39 arsatiki: yeah

6:39 Chousuke: that way, it'll be more flexible.

6:39 ysmolsky: i see. just wanted to get know how far reflection of clojure goes :)

6:39 Chousuke: functions don't know their names because in most cases they don't have one.

6:39 ysmolsky: ok

6:39 Chousuke: or might have multiple. or one name might map to multiple functions.

6:40 (because of closures)

6:40 Licenser: ysmolsky: do you have a page about your RPC server?

6:40 I'd be interested in such a thing

6:40 ysmolsky: anyway, i still to get to know the count of arguments of the function. is there a way?

6:40 Chousuke: you can use reflection for that.

6:40 it's tricky though.

6:40 ysmolsky: Licenser: not yet, but i will drop url here when its in github

6:41 Chousuke: I think chouser had some code for it somewhere.

6:41 Licenser: thanks

6:41 Chousuke: clojurebot: pastes

6:41 clojurebot: No entiendo

6:41 Chousuke: hm

6:42 arbscht: a function doesn't necessarily have one count of arguments

6:42 Chousuke: yeah.

6:42 ysmolsky: i know that i could just try to apply whatever user send to function and see if it thrown exception, but, it would be great to know it in advance.. or maybe not

6:43 ok, i will try exception way for the beginning

6:44 Chousuke: using reflection involves taking advantage of implementation details, too, so I guess the exception method is safer.

6:44 Licenser: what is your JSON RPC based on? Restful HTTP?

6:46 ysmolsky: well, i want to make 1st version more general, but i'm planning to add restful too ..

6:47 do you have any example of well designed restful lib for java/python?

6:48 Licenser: Nope sadly not but I was thinking about something like that, a easy way to export resources / functions on a REST interface

6:48 * Licenser has not worked with java or pythin in a long while

6:49 shmichael: Hello everyone. I am trying to test if symbols in my code are macros. I tried writing a macro? function.

6:49 (defn macro? [exp] (-> exp var meta :macro))

6:50 This yields #<CompilerException java.lang.Exception: Unable to resolve var: exp in this context (NO_SOURCE_FILE:265)>

6:51 ysmolsky: hehe, same problem

6:51 shmichael: If I explicitly use a specific symbol, the expression is valid

6:51 ,(-> let var meta :macro)

6:51 clojurebot: true

6:51 Licenser: ysmolsky: but this is clojure you don't need to bother about java or pyhtin

6:53 ysmolsky: Licenser: just.. I have never used restful libs, so gotta to see how thats done in popular libs, not only python or java, maybe ruby, whatever actually

6:53 Chousuke: shmichael: the var special form doesn't evaluate its argument, which is your problem

6:53 shmichael: you're always asking for the var named "exp"

6:53 shmichael: Chousuke: Is this a flaw in var or am I doing something wrong?

6:53 Chousuke: shmichael: it's not a flaw in var

6:53 shmichael: you need to make your macro? a macro :)

6:54 OR you can have it take a symbol as an argument

6:54 Licenser: ysmolsky: my idea was basing it on compojure you can create a REST-Full HTTP frontend with that

6:55 Chousuke: like: (defn names-a-macro? [sym] (-> (resolve sym) meta :macro))

6:55 ,(:macro ^(resolve '->))

6:55 clojurebot: true

6:55 Chousuke: ,(:macro ^(resolve 'foo))

6:55 clojurebot: nil

6:55 Licenser: back when I tried I had barely any idea of clojure or compojure so it went horrible wrong, I quite to work with clojure for 2 weeks :P

6:55 ordnungswidrig: Licenser: uh, I hear REST on top of compojure. Did I miss anything? Is there still a library?

6:55 Licenser: hm?

6:55 ordnungswidrig: s/still.*y/a library yet/

6:56 shmichael: Chousuke: thanks, I will try it out

6:56 Licenser: Compojure is needed to take care of the HTTP part, (you can use anything else too I guess) but the REST protocoll is up to the user to implement

6:57 you can just use the default compojure routes to make a restufll interface

6:57 ordnungswidrig: Licenser: do you know erlang's webmachine?

6:57 Licenser: ordnungswidrig: nope, never worked with erlang

6:57 ysmolsky: Licenser: I see your point. when I will have some general json rpc server I can add more specified solutions..

6:57 Licenser: ysmolsky: mongodb and with that somniums mongodb driver for clojure might be interesting

6:57 ordnungswidrig: Licenser: making a correct restful interface is hard. implementing correct HTTP is hard. compojure / ring are very basic.

6:58 Licenser: Take a look at webmachine, at least at the monster flow diagram.

6:58 Licenser: this was very enlighting to me.

6:58 Licenser: http://bitbucket.org/justin/webmachine/wiki/WebmachineMechanics

6:58 Licenser: http://bitbucket.org/justin/webmachine/wiki/BigHTTPGraph

6:59 Licenser: I know that it's hard but it wraps the webserver icely for clojure quite nicely

6:59 :P

6:59 ordnungswidrig: Licenser: yes, but the decision on E-Tag, how to negotiate content-types and so on is what compojure doesn't for you.

7:00 Licenser: I've no idea what E-Tag is :P

7:00 and yes that's true

7:01 ordnungswidrig: good greif that is a graph

7:01 ordnungswidrig: Licenser: You see, speaking good HTTP is very hard. I'm doing web based development for 10+ years now. I remember a time where the only interaction was something like a "query" field in HTML and CGI for the NCSA server. Yet, since webmachine I know I spoke only a whimsy dialect of pidgin HTTP.

7:02 shmichael: OK, for the record here is my macro? implementation:

7:02 (defmacro macro? [exp] (if (symbol? exp) `(:macro ^(resolve '~exp)) false))

7:03 Licenser: ordnungswidrig: I know HTTP is horrible complex

7:03 ordnungswidrig: Licenser: for a project I'm currently sketching a REST library on top of compojure. For every resource you define some multimethods which represent the decision nodes in webmachines graph.

7:04 Licenser: oi cool will it be OpenSource?

7:05 ordnungswidrig: Licenser: so, for a simple resource which is available with GET in a singe content type, you'll be able to do sth. like

7:06 (defmethod clojure-rest/content-types-provided ::article

7:06 [_ _ _]

7:06 { "text/html" (fn [_ request context]

7:06 (let [id (urldecode ((request :route-params ) :id))]

7:06 (str "Hello, article no." id ". The message is: " ( context :message ) )))})


7:06 wooby: ordnungswidrig: are you doing it state machine style?

7:06 Licenser: looks nice

7:07 ordnungswidrig: wooby: I try to avoid state ;-) The "context" will be passed along when working on a request

7:08 Licenser: hmm isn't one of the 'issues' with http that it is stateless?

7:08 avital-: ,(symbol? let)

7:08 clojurebot: java.lang.Exception: Can't take value of a macro: #'clojure.core/let

7:08 ordnungswidrig: Licenser: Btw. I'll be happy when I pushed the whole shebang to github and I merge the first improvement from a person completely foreign to me. Yes, it will be opensource. At least I hope it will be good enough.

7:08 Licenser: yes, http is stateless

7:09 Licenser: what do you mean by issue? Positive or negative?

7:09 Licenser: That depends on what you do :P

7:09 somtimes it is negative, sometimes positiv

7:09 ordnungswidrig: Licenser: you started the issue on stateless, so you decide :-)

7:09 wooby: Licenser: a state machine is an abstraction of a system that transitions between various 'states'

7:10 Licenser: and glad to hear that, I'll look into it once it is gitted

7:10 ordnungswidrig: what I mean is, it isn't either negative nor positve in general, at least not in my eyes :P that sometimes is a issue, then it's negative

7:10 ordnungswidrig: wooby: If you want, it is a statemachine. But a DAG of states. And the state is held by the "instruction pointer" :-)

7:10 Licenser: and sometimes it does not matter then it's positive

7:10 wooby: lol

7:11 ordnungswidrig: thanks, i like the idea now ;)

7:11 ordnungswidrig: wooby: a state machine in the sense of "very-big-bunch-of-ifs-and-conds"

7:12 to unknot the pile-of-ifs I'm looking still for a good abstraction. Something like an Either Monad.

7:13 Licenser: ordnungswidrig: you're from germany?

7:14 wooby: maybe a like a formal grammar, which your request handler evaluates input against?

7:14 avital-: ,(resolve 'map)

7:14 clojurebot: #'clojure.core/map

7:15 ordnungswidrig: Licenser: Neu-Ulm, Germany

7:15 avital-: ((fn [map] (resolve 'map)) 2)

7:15 Licenser: We should start to make a german Clojure community, you're the 3rd german I find here

7:15 hoeck1: Licenser: +1

7:15 Licenser: then hoeck1 is the 4th I find :P

7:16 avital-: ,((fn [map] (resolve 'map)) 2)

7:16 clojurebot: #'clojure.core/map

7:16 wooby: i too am from germany

7:16 * Licenser himself comes from Berlin

7:17 hoeck1: Licenser: sth like a clojure-de channel would be nice, but I suspect it would get much traffic

7:17 wooby: born in munster, moved to US when 2, more fluent in clojure than german :\

7:18 Licenser: Poor you wooby ;) you missed out on some darn good ruladen

7:18 ordnungswidrig: wooby: have a look at webmachines http diagramm. currently the imlementation is like (if-not (valid-method? resource request context) [501 "not implemented"] (if-not (content-type-accepted? resource request context) [415 "Unsupported media type"] (generate-body resource request context)))

7:19 btw +1 for a german clojure user group geclug

7:19 Licenser: hoeck1: noone stops us to make a clojure-de channel but all the smart guys hang out here so I'm not sure if it would make much sense

7:19 hoeck1: Licenser: exactly

7:19 Licenser: or we teach them german

7:20 ordnungswidrig: Licenser: that'll be harder than lerning some clojure

7:20 Licenser: true

7:20 we could make a clojure to german translator in clojure

7:20 ordnungswidrig: anybody know how to set the line width in ERC?

7:26 hoeck1: ordnungswidrig: maybe: m-x customize-variable [ret] erc-fill-column

7:28 ordnungswidrig: hoeck1: let's set 123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.


7:28 hurray

7:28 is there a state-monad available in clojure?

7:29 wooby: you could do that fairly simply, no?

7:30 ordnungswidrig: wooby: i'm lazy :)

7:30 Chousuke: ordnungswidrig: clojure.contrib.monads

7:31 ysmolsky: tests facility was moved to clojure.core?

7:32 wooby: awesome, state-m-until

7:34 Chousuke: ysmolsky: yes.

7:34 it's now clojure.test

7:40 gerry_: (deftype person [name age])

7:41 (person "gerry" 18)

7:41 java.lang.StackOverflowError

7:41 ??

7:42 hello to all

7:44 Chousuke: is that the new deftype?

7:44 * ordnungswidrig failed on haskell monads and repeats this on clojure monads

7:45 Chousuke: heh.

7:45 gerry_: yes

7:46 i dont know what's wrong

7:47 ordnungswidrig: ok, paredit together with viper is somewhat confusing

7:48 gerry_: (doc deftype)

7:48 -------------------------

7:48 clojure.core/deftype

7:48 ([name [& fields] & [[& interfaces] & methods]])

7:48 Macro Dynamically generates compiled bytecode for an anonymous class with the given fields, and, optionally, interfaces and methods. The Name will be used to create a dynamic type tag keyword of the form :current.ns/Name. This tag will be returned from (type an-instance).

7:48 clojurebot: "clojure.contrib.types/deftype;[[type-tag constructor-name docstring? attr-map?] [type-tag constructor-name docstring? attr-map? constructor] [type-tag constructor-name docstring? attr-map? constructor deconstructor]]; Define a data type by a type tag (a namespace-qualified keyword) and a symbol naming the constructor function. Optionally, a constructor and a deconstructor function can be given as well, the defaults being

7:48 gerry_: A factory function of current.ns/Name will be defined, overloaded on 2 arities, the first taking the designated fields in the same order specified, and the second taking the fields followed by a metadata map (nil for none) and an extension field map (nil for none).

7:48 See defclass for a description of methods and generated interfaces. Note that overriding equals and hashCode is not supported at this time for deftype - you must use the generated versions.

7:50 clojurebot? ;(

7:51 any ideas?

7:52 ordnungswidrig: is there a if-not-let

7:56 gerry_: no

7:56 if-let not work?

7:57 ordnungswidrig: gerry_: yes, but there is a if-not as well. but I look for something else:

7:58 raek: what is the preferred way to convert a string to an int?

7:58 adityo: Integer/parseInt

7:58 raek: (Integer/decode s) ?

7:58 kthx

7:58 wooby: ,(read-string "5352")

7:58 clojurebot: 5352

7:59 raek: ah, that's neat

7:59 ,(read-string "900000000000000000000000000000000000000")

7:59 clojurebot: 900000000000000000000000000000000000000

8:00 hoeck1: gerry_: the type creation works, but the printing fails

8:00 raek: ,(Integer/parseInt "900000000000000000000000000000000000000")

8:00 clojurebot: java.lang.NumberFormatException: For input string: "900000000000000000000000000000000000000"

8:00 adityo: cool

8:00 gerry_: hoeck1: type not support print yet?

8:02 ordnungswidrig: gerry_: if have a test function that returns [true, value] or [false, value] and I'd like to handle it nicely. (foo test if-form else-form) where if-form and else-form are beeing passed the value.

8:02 hoeck1: gerry_: it should be printed somehow, so I think its a bug

8:02 * adityo time to get rid of Integer/parseInt from his code

8:02 ysmolsky: ,(BigInteger. "990")

8:02 clojurebot: 990

8:02 ysmolsky: (BigInteger. "abc" 16)

8:03 ,(BigInteger. "abc" 16)

8:03 clojurebot: 2748

8:03 ysmolsky: ,(BigInteger. "ff123")

8:03 ,(BigInteger. "ff123")

8:03 clojurebot: java.lang.NumberFormatException: For input string: "ff123"

8:03 ysmolsky: BigInteger is faster than read-string

8:04 gerry_: Person

8:04 #<user$Person__22 user$Person__22@1a897a9>

8:04 type can be printed, but not for objects

8:05 (Person 1 1) => got stackoverflowerror

8:07 hoeck1: right, object exists,i can test it

8:07 (def me (Person "gerry" 18))

8:08 (:age me) -> 18

8:09 hoeck1: you also could do a (defmethod print-method :user/person [the-person writer] (print-method (str the-person) writer))

8:10 raek: hmmm, I can't get my clojure script working

8:10 it just quits without printing anything

8:10 gerry_: hmm, permethod for perobject

8:11 adityo: ,(time (Float/parseFloat "123.75243"))

8:11 clojurebot: 123.75243

8:12 "Elapsed time: 0.222 msecs"

8:12 raek: what are the differences between an ordinary clojure program and a clojure script?

8:12 adityo: ,(time (read-string "123.75243"))

8:12 clojurebot: 123.75243

8:12 "Elapsed time: 0.19 msecs"

8:13 ambient: raek there are differences?

8:13 ysmolsky: adityo: dont' benchmark on single call

8:14 raek: like (ns your-ns (:gen-class)) and (defn -main [& args] ...)

8:14 adityo: ysmolsky: true!

8:14 raek: but I don't know if I have to use those

8:14 tomoj: if you want an executable jar, you do

8:15 raek: oh, wait

8:15 java -cp clojure.jar clojure.lang.Script script.clj

8:15 not

8:15 java -cp clojure.jar clojure.lang.Script < script.clj

8:15 tomoj: clojure.main

8:17 raek: ok, got it working now

8:17 hoeck1: gerry_: it seems that the problem is, that there is no print-method defined for the generated type

8:17 raek: thank you all

8:18 gerry_: hoeck1: yes

8:18 hoeck1: gerry_: and the :default print-method tries to remove the :type tag from the object

8:18 gerry_: oh?

8:19 hoeck1: gerry_: for which type would then return a java object, so it could be printed at least as a plain java object

8:19 jagguli: adityo, G0SUB: hi

8:20 gerry_: (deftype [#^int age])

8:20 hoeck1: gerry_: but the generated type has no :type attribute and so the :default print-method is invoked again trying to remove the type-tag ... stackoverflow

8:20 G0SUB: jagguli

8:20 gerry_: java.lang.IllegalArgumentException: Wrong number of args passed to: core$deftype (NO_SOURCE_FILE:0)

8:20 oops

8:21 (deftype a [#^int age])

8:21 java.lang.UnsupportedOperationException: Can't type hint a primitive local (NO_SOURCE_FILE:22)

8:21 primitive int cant be type hint

8:22 hoeck1: ic

8:22 does deftype support primitive fields?

8:28 adityo: jagguli: hey

8:29 gerry_: defclass Person [name age])

8:29 nil

8:29 user=> (new Person "gerry" 18)

8:29 java.lang.IllegalArgumentException: Unable to resolve classname: Person (NO_SOURCE_FILE:24)

8:31 chouser: gerry_: I think for deftype you just call Person as a function to create new ones

8:32 gerry_: chouser: yes, but for defclass i have to use new

8:34 need i compile it at first or something?

8:34 hoeck1: gerry_: for defclass, yes

8:35 gerry_: hoeck1: so i need put it into one clj file, and compiling it before using it?

8:35 hoeck1: gerry_: right, just like gen-class

8:39 gerry_: from datatypes wiki, deftype could support primitive type and imporove perf , is that right?

8:42 chouser: gerry_: I think that's right.

8:42 gerry_: but deftype not support primitive type hints

8:44 chouser: I see that. I think it's probably just a bug.

8:46 gerry_: chouser: deftype and defclass still underway, so it's not a bug :)

8:47 maybe not finished yet

8:48 chouser: well, sure. but I mean I think the support is there and there was probably a small oversight that is breaking it

8:49 gerry_: include type object printing

8:58 fabe: hi

8:59 im currently learning clojure and found the http://clojure.org/Atoms example confusing

8:59 ysmolsky: how to thrown exception of custom class from clojure?

9:00 chouser: ysmolsky: avoid it if possible, otherwise you have to create your custom class using gen-class and compile ahead-of-time.

9:00 fabe: it suggestes the memoizer momoized the call before (def fib (memoize fib))

9:01 chouser: ysmolsky: there are also a couple compromise solutions in contrib: condition, error-kit, except

9:02 fabe: that example tries out 'fib' once before it's memoized so you can see how long it would normally take.

9:02 oh, you mean that the first call after 'memoize' is already faster? Did you try it yourself?

9:04 ysmolsky: ok. what is the best way to wrap situation like this? i thought about returning keywords like this to replace situation when keyword cannot be found:

9:04 (defn fun-dispatch [table]

9:04 (fn [method args]

9:04 (if-let [f (table method)]

9:04 (apply f args)

9:04 :notfound)))

9:05 fabe: i know what it does im juste saying its easy to missunderstand it

9:08 chouser: ysmolsky: returning 'nil' is pretty common. The 'get' function allows you to pass in a "not-found" value to return instead if you want to detect the difference between nil and not-found.

9:09 rhickey: gerry_: fixed

9:09 gerry_: cool

9:09 * chouser undoes his ugly strip-meta hack.

9:12 gerry_: rhickey: type object printing seems not fixed?

9:13 i still got stackoverflowerror

9:14 chouser: he fixed the primitive support

9:14 gerry_: yes, i just tried it

9:19 ysmolsky: how do you think reading Seibel's PCL worth anything applied to clojure? does it have some pattern or idioms useful for clojure programmer?

9:20 gerry_: ysmolsky: that's for cl, i don't think that's much helpful, but just my personal thought

9:22 and if you compare cl and common lisp syntax, you will hate verbose of common lisp :)

9:22 faux: ysmolsky: http://blog.thinkrelevance.com/2008/09/16/pcl-clojure

9:26 gerry_: s/clojure/cl

9:26 s/cl/clojure oops

9:26 :)

9:36 (-> me :meta :type) => nil

9:36 (:type me) => nil

9:36 chouser: gerry_: (type me) ?

9:37 gerry_: :usr/Person

9:44 AWizzArd: I try to start slime with the NEW branch of Clojure. I get: java.lang.NoSuchMethodError: clojure.lang.RestFn.<init>(I)V (pprint.clj:1)

9:44 What does this mean?

9:44 chouser: AWizzArd: it means you need to rebuild contrib and other libs you may be trying to load

9:46 AWizzArd: ok

9:49 Maybe Clojure Contrib is not compatible with the current NEW branch?

9:50 chouser: oh, right. sorry. http://groups.google.com/group/clojure-dev/browse_thread/thread/91ca1a8b524b7349?hl=en

9:50 so for now just don't use contrib.

9:50 AWizzArd: One example Exception: Name conflict, can't def deftype because namespace: clojure.contrib.pprint.PrettyWriter refers to:#'clojure.core/deftype (PrettyWriter.clj:51)

9:51 gerry_: deftype name conflict exists

9:51 AWizzArd: yes, I see

9:52 but well, for testing purposes I could just modify my own checkout of contrib, maybe by fully qualifying those few cases

9:53 chouser: or just add (:refer-clojure :exclude [deftype])

9:53 ysmolsky: what special name can i use to test that this file is being run through clojure.main? something *...*

9:57 jdz: ,(find-doc "compiling")

9:57 clojurebot: ------------------------- clojure.core/*compile-files* nil Set to true when compiling files, false otherwise. ------------------------- clojure.core/gen-class ([& options]) Macro When compiling, generates compiled bytecode for a class with the given package-qualified :name (which, as all names in these parameters, can be a string or symbol), and writes the .class file to the *compile-path* directory. When not compiling, d

10:12 AWizzArd: Is there already a code example of where deftype is used?

10:18 gerry_: i think no

10:20 you may use it as defstruct at least

10:24 haptiK: hi

10:25 AWizzArd: rhickey: I tried: (deftype person [name age]) And when I then do (person 1 2) I get: No message. [Thrown class java.lang.StackOverflowError]

10:26 gerry_: :)

10:27 chouser: AWizzArd: printing doesn't work at the moment. do (def p (person 1 2)) then you can use p, just don't print it.

10:28 lpetit: chouser: can printing already be extended via protocols ? :-)

10:30 chouser: heh

10:33 (defmethod print-method :user/Person [o w] (.write w (str "#<Person " (:title o) " " (:age o) ">")))

10:37 AWizzArd: yes

10:38 rhickey: printing is todo

10:39 will eventually be a protocol once there are protocols

10:40 AWizzArd: rhickey: In my tokenization module I had to make only small fixes at two places and got a 40% speedup. Thank you!! *handshaking*

10:40 rhickey: so, today I think even less of ASsociative support being the default. If I still had defstruct available I'd probably have a 3rd version deftype/class/struct, although you might want expando classes and types. In any case, I think opt in might be better than opt out

10:40 AWizzArd: that's great!

10:41 AWizzArd: this vs defstructs?

10:41 AWizzArd: In other places I still use maps instead of deftyped objects, so I can speed up it even more. So far the results look all correct and I can't see a problem.

10:41 Yes

10:41 chouser: AWizzArd: you're using deftype or defclass?

10:41 AWizzArd: The main container was changed. In the next days I can try to replace other throw-away objects by types. Looks really promising I must say.

10:42 deyftype

10:42 deftype

10:42 chouser: so cool.

10:42 AWizzArd: I just don't have so much time today, and it already took some time to get Slime running, and to compile contrib. But now I made the most obvious test.

10:43 cemerick: AWizzArd: whoa, good to know

10:43 AWizzArd: deftype/defclass is exactly the functionality we needed to speed up the very important core routines. Now I will see where I can stil use it.

10:44 But this is a real nice speedup, with basically no real changes.

10:44 cemerick: rhickey: can I lobby you for a deftype-time flag or somesuch, rather than the conj > assoc, getx morass?

10:45 rhickey: cemerick: ?

10:45 cemerick: rhickey: w.r.t. opt-in expando

10:46 rhickey: opt-in just means that deftype won;t give you expando by default, but when you get expando (how tbd) it will be just like now (which is just like defstruct)

10:46 no morass

10:46 gerry_: AWizzArd: do you use primitive type in your module with deftype?

10:48 shmichael: I'm trying to check performance for an implementation of a fibonacci sequence. However, it seems I am not getting a linear computation time.

10:48 (def fib (lazy-seq (for [x (iterate inc 0)] (if (< x 2) x (+ (nth fib (- x 2)) (nth fib (- x 1)))))))

10:48 This is odd, since lazy-seq should cache values

10:49 On the other hand, the following implementation demonstrates linear time:

10:49 (def fib-seq (lazy-cat [0 1] (map + (rest fib-seq) fib-seq)))

10:49 jdz: shmichael: nth is linear time

10:49 shmichael: and you have 2 of them

10:49 AWizzArd: gerry_: well, as I understand it deftype gives my indeed a pojo. But I did not have to write a .java file.

10:49 chouser: In (lazy-seq (for ...)), lazy-seq isn't doing anything for you. 'for' already returns a lazy seq

10:50 shmichael: jdz: that would make the running time 2n

10:50 AWizzArd: Before deftype I had to write a class in Java for my short lived objects. I need to create millions of those, and it just is a bit expensive to create the powerful Clojure structs.

10:50 jdz: shmichael: not if you do that for every next number in your sequence

10:52 shmichael: jdz: Agreed. So I have to use a hash-map?

10:52 jdz: shmichael: why? why don't you use the second version you pasted?

10:53 shmichael: jdz: Because I'm trying to understand all the nooks and crannies

10:53 It's just educational

10:55 rhickey: primitives don't help deftype when used with :field access

10:56 cemerick: oh, that's a good point

10:56 chouser: maybe help with memory usage or cache lines, just not avoiding box/unbox?

10:56 cemerick: rhickey: does that change with the planned case support?

10:56 AWizzArd: better (. field my-object)?

10:56 cemerick: no, probably not

10:57 chouser: AWizzArd: yes, but you only get that with defclass not deftype

10:57 (.field my-objecT)

10:57 rhickey: primitives might help inside any methods defined

10:57 cemerick: which help, primitives? - no, case is about the keyword lookup

11:00 gerry_: rhickey: could i just compile defclass in repl with (compile (defclass ...)) and not put it to file?

11:01 shortcut compile

11:03 rhickey: gerry_: that's not how compile works

11:05 gerry_: put compiled class file to default/setting Dir and i can use it just like in java.lang or something alike?

11:06 rhickey: gerry_: I don't want to talk about premature optimization :)

11:07 gerry_: just my fancifulness :)

11:09 rhickey: so, I can auto-gen accessors even for deftype, that internally use .field, for another 15-20% boost, but would like to do that with deterministic names, like Foo-a, Foo-b etc rather than make you do that manually or having a bunch of naming options

11:09 at that point there might not be a significant benefit to case, or even to .field directly

11:10 the only caveat being that on re-eval, the Foo-a accessors will no longer work on old instances

11:11 does anyone want this?

11:13 cemerick: hard to know at this point. The re-eval issue is unfortunate, since deftype should be re-eval safe otherwise.

11:15 rhickey: cemerick: right, it is otherwise (but old instances won't have new fields etc), of course no one is forcing you to call these

11:15 gerry_: 15-20% boost is worth

11:16 rhickey: but I imagine this explicit accessor use might be limited to module internals... still won't help old instances

11:17 cemerick: of course, the first thing I'd do is redef Foo-a to just about anything else. ;-)

11:18 rhickey: cemerick: like what?

11:19 srader: no way to have .field access with deftype?

11:19 cemerick: rhickey: hrm, perhaps not. There'll likely be multiple types in each namespace. I've got my head stuck in gen-class.

11:19 rhickey: srader: no

11:20 srader: but this accessor Foo-a I have been talking about will do that for you

11:21 srader: the speed up sounds good

11:21 rhickey: CL has a :conc-name option to set a prefix (other than the default struct name) for all accessors

11:23 cemerick: yeah, I vaguely remember a bewildering set of options for defclass in CL

11:23 rhickey: cemerick: oh yeah, defclass even worse than defstruct

11:24 cemerick: I thankfully only lost ~6 mo. to that years ago.

11:24 rhickey: but standard names have value in that they are predictable, given a Type T you know how to create/access

11:25 cemerick: definitely. I'm always a little shy of autogenerated names, though of course it's unavoidable sometimes.

11:25 rhickey: well, I've got it written already, so I'll put them in

11:26 would like so input on how people would like to opt-in for Associative/struct-map-like

11:26 some input

11:27 AWizzArd: Could this be a parameter for deftype? :eval-safe true

11:33 rhickey: AWizzArd: what would that mean?

11:34 notallama: a choice between the fast version and the reeval-safe version, i'm assuming

11:35 AWizzArd: The auto-generated accessors that you can offer even with deftype that internally use .field

11:36 rhickey: notallama: :field is re-eval safe, accessors wrapping :field when eval-safe?

11:36 I hate having lots of options

11:37 and the most important right now is opt-in for expando

11:38 AWizzArd: so you will keep the :field accessor

11:38 rhickey: AWizzArd: oh yes, this is not instead of that

11:38 AWizzArd: k, that is configurable enough imo

11:40 rhickey: Foo:a for accessors? so when you want to speed up (:field x) code just do (Foo:field x)

11:41 chouser: I still have an inappropriate affinity for little bits of syntax like that.

11:41 rhickey: chouser: is that a positive statement? :)

11:42 chouser: heh

11:42 AWizzArd: So (:field x) will make a little lookup and (.field x) will only work for the latest evaled version, but may be 10-20% faster.

11:43 rhickey: AWizzArd: .field is not a deftype feature

11:43 (Foo:field x)

11:44 chouser: (user/Foo:field x) ?

11:44 oh, sure it's still just in whatever namespace, so either wya

11:44 way

11:44 rhickey: chouser: outside of the namesapce, yes

11:45 srader: why not just have :field use the accessor function?

11:46 ordnungswidrig: is it good style for a function to return either a string or a map? The function will be passed as a handler-type-function in my rest library.

11:47 a handler-function shall be allowed to either return a body or a map with {:headers {..} :body the-body-value}

11:47 rhickey: srader: (:field x) ==> (get x :field), it's inherently a lookup

11:48 ordnungswidrig: the calling function will have to analyze the type of the returned value. This smells, I think. But I have no better idea.

11:48 gerry_: (Foo-field x) maybe better ,x:y:z could be reserved

11:48 cemerick: rhickey: the question is, do you have other, better plans for colon-delimited symbols?

11:48 I do like the colon better than a dash.

11:49 AWizzArd: so, (Foo:field x) for a deftype would be as efficient like a (.field x) for a defclass?

11:49 rhickey: AWizzArd: tbd if HotSpot does something different with them, one being wrapped

11:50 AWizzArd: Can you make (Foo:field x) also available for defclasses?

11:50 rhickey: cemerick: opened up a while ago - http://clojure.org/reader - "A symbol can contain one or more non-repeating ':'s."

11:50 AWizzArd: cemerick: yes, I also like the colon better.

11:56 The-Kenny: hm... will it be possible to use defclass in the repl? (Without compiling the sources etc.)

12:01 rhickey: The-Kenny: use deftype

12:02 does someone want to do simple (non-readable) print while I do case?

12:15 mikehinchey: rhickey: I have a patch that fixes contrib, by adding exclude deftype to all of the broken namespaces. Would that be easier than getting individual authors?

12:16 rhickey: mikehinchey: sure, I'll try it

12:16 could you please post it on assembla?

12:17 djork_: ,"yay for clojurebot from my phone"

12:17 clojurebot: "yay for clojurebot from my phone"

12:17 djpowell: I'm a bit confused. (.field o) currently works on deftype instances. Is that just an accident?

12:18 rhickey: djpowell: that will use reflection

12:18 and thus be much slower than (:field o)

12:18 djpowell: ah - cause o can't easily be type hinted once it crosses function boundaries and stuff?

12:19 cause it uses an anonymous class

12:19 rhickey: djpowell: the type is anonymous, generated anew each time you evaluate the deftype

12:20 djpowell: yeah, I see now

12:22 rhickey: so more syntax options for those playing along:

12:23 case will basically look like this:

12:23 (case x

12:23 :k (foo)

12:23 :j (bar)

12:23 (baz))

12:23 chouser: yummy

12:23 rhickey: where :j and :k can be at leasy symbols/keywords/string, but possibly others like vectors etc

12:24 however sometimes you want more than one constant to map to the same outcome

12:24 thus they need to be grouped

12:24 mikehinchey: rhickey: I put it on assembla for clojure, exclude-deftype.patch

12:25 rhickey: mikehinchey: thanks!

12:25 mikehinchey: where?

12:25 oh, assembla for clojure, not contrib?

12:26 mikehinchey: yes, contrib would have made more sense

12:27 chouser: do you have a plan for how the deftype obj will hook into print-method

12:27 djpowell: sry, what is case? is this something related to deftype?

12:29 chouser: rhickey: like will deftype types all derive from :clojure.core/deftype? or just provide .toString on the deftype?

12:30 Chousuke: what about C-switch-style fall-through for case? The proposed syntax wouldn't support it, but... hmm.

12:30 rhickey: mikehinchey: applied -thanks very much!

12:30 Chousuke: it'd get repetitive to write (case :x a :y a :z :a :w :b :default)

12:30 with the actual variable there :P

12:31 hiredman: so :z :a :w :b all fall through?

12:32 mikehinchey: rhickey: you're welcome

12:32 Chousuke: no

12:32 rhickey: chouser: should be inside the deftype/defclass, generate print-method based on type tag or class respectively

12:32 Chousuke: hiredman: I meant you should have been able to write something like (case x [:x :y :z] a, ...)

12:32 but that would mean x can

12:32 can't be a vector

12:33 rhickey: chouser: in general, it will be bad to base anything off of implementation detail class of generated deftype/classs since they are being used by users to define classes with their own semantics

12:35 AWizzArd: rhickey: will this case construct be used for hashes?

12:35 chouser: rhickey: ok, so a custom defmethod for each deftype

12:35 rhickey: chouser: I think so

12:36 there can be some implementation helper function

12:36 chouser: sure

12:36 rhickey: (print-me me fields)

12:37 should just print #:Foo{:a 1 :b 2 :c 3 :extra1 4 :extra2 5}

12:37 so, back to case:

12:37 (case x

12:37 (:i :k) (foo)

12:37 :j (bar)

12:37 (baz))

12:38 here, is (:i :j) a single data structure or a group of 2 keys?

12:38 presuming we definitely want case for vectors if any aggregate

12:39 Chousuke: what about a set?

12:39 does order matter if the end result is going to be the same?

12:39 djork: just curious here. what's the case for having both (:foo some-map) and (some-map :foo) be valid

12:39 rhickey: Chousuke: whatever aggregate is used for grouping will no longer be available for switching

12:40 djork: well, some maps are not keyed by keywords, so you have to have (map akey)

12:40 djork: right

12:41 Chousuke: and :foo as a function works for sets/java maps too, right?

12:41 djork: or can a keyword be a function of other types?

12:41 rhickey: but some maps are used more like objects than collections, where (field-of x) makes more sense than (find-in-x key)

12:42 hiredman: a keyword can be a function of any ILookup, right?

12:43 AWizzArd: rhickey: one option for case could be to add explicit separators. That may be useful anyway to make it visually more clear where the "when" part is and where the "then" part is.

12:43 rhickey: AWizzArd: sounds icky

12:43 hiredman: ~def c.l.RT

12:43 Raynes: Is there anyway to 'unuse' something in the REPL?

12:44 hiredman: around like 616 is the get method keywords use

12:44 AWizzArd: Raynes: you an ns-unmap things

12:44 rhickey: hiredman: right now the promise is vague

12:44 Raynes: Thanks. :)

12:44 chouser: (case x (:a a) (:a :b :c a-or-b-or-c))

12:45 hiredman: not overspecified

12:45 rhickey: actually it promises get, but I'd like to narrow that

12:45 chouser: aargh, the grouping parens are back!

12:45 I got rid of them everywhere else

12:45 chouser: yes. but only one level -- don't others do 2?

12:46 no, I hate it nevermind.

12:46 at least use vectors there if anything

12:46 (case x [:a a] [:a :b :c a-or-b-or-c])

12:46 Chousuke: yeah. looks like function calls :(

12:46 rhickey: chouser: I hate always grouping like that

12:47 so, let's presume we want to avoid it

12:47 It's a matter of sacrificing some data structure, sets or lists would be prime candidates in my book

12:48 (case x

12:48 #{:i :k} (foo)

12:48 :j (bar)

12:48 (baz))

12:49 we haven't used sets as syntax yet

12:52 gerry_: if x itself is one set?

12:52 rhickey: gerry_: you wouldn't be able to case on sets

12:53 wooby: it's cool to be a fly on the wall and watch awesomeness unfold, the case form looks fantastic

12:54 gerry_: then, use sets not bad

12:58 chouser: #{#{:i :k}} could match a set

12:58 in which case I'd vote for vectors instead

12:58 and suddenly this sounds very familier.

12:59 (case [:a :b] [[:a :b] [:b :c]] ab-or-bc)

13:01 rhickey: chouser: how would you match a set of one set/ vector of one vector?

13:01 mikehinchey: or: (case [:a :b] ([:a :b] [:b :c]) ab-or-bc)

13:01 chouser: like (case [[:a]] ...) right?

13:01 Raynes: I thought deftype was in Clojure now?

13:02 chouser: Raynes: 'new' branch only

13:02 rhickey: right

13:02 Raynes: Oh, I see.

13:02 * Raynes snatches the new branch. :D

13:02 AWizzArd: (case x [:a -> 1] [:b -> 2] [:c :d -> 3] [[:x :y] -> 4] [[1 2 #{3 4}] :clojure -> 5])

13:02 chouser: I know I've done this, I just can't find where.

13:02 rhickey: Raynes: snatch latest contrib as well

13:03 Raynes: rhickey: Already did. :)

13:03 chouser: anyway, the logic is: case will wrap an implied [] around every test expression unless it's already a vector

13:03 so, (case [[:a]] [[[:a]]] got-it)

13:03 mikehinchey: I meant: (case :a a ([:a :b] [:b :c]) ab-or-bc) - the () doesn't conflict with any data structure

13:04 chouser: mikehinchey: it conflicts with lists. plus it looks like you're looking something up in the [:a :b] vector unless you look carefully to see this is an unevaluated from in a case expression.

13:04 unevaluated form in a case form

13:04 rhickey: chouser: I know we've had this conversation before, but I wouldn't want to have to explain that

13:05 chouser: I just explained it. one line!

13:05 :-)

13:05 I guess that might be an argument for using literal set intead of vector -- just less likely you'll be using it for anything other than grouping your tests.

13:06 mtm: hmm, I'm not seeing deftype in my latest pull from github; is this on a different branch than 'master'?

13:06 chouser: one way of looking at it is that you can pretend that collection type can't be matched, but if you really need to you actually can do it.

13:06 rhickey: chouser: the problem is (case [[:a]] [[[:a]]] got-it) will haveto be explained over and over, even if it is one line

13:06 somnium: (case x :a : 1 :b : 2 [:c :d] : 3 #{:e :f} : :g)

13:06 rhickey: but yes, I see sets as much less likely

13:07 chouser: maybe inside case "," is not whitespace.

13:07 :-) :-)

13:07 (case x :a 1, :b 2, :c :d :e 3)

13:10 rhickey: chouser: so, set of one set to match a set?

13:11 all questions go to you? :)

13:11 using sets, it may never come up

13:11 chouser: they all do anyway, don't they? ;-)

13:11 right

13:12 with vectors people are going to trip over it

13:12 ...be surprised that (case [:a :b] [:a :b] match) fails

13:12 Licenser: hmm a curiose question, the clojure book says: Clojure does not optimize tail recursion because java can't do that. But as it strikes me can't the optimisation be done before java ever sees the bytecode?

13:13 rhickey: chouser: I think so, vectors probably the most popular aggregate-as-key

13:13 chouser: rhickey: right.

13:13 lists would not match vectors in a case?

13:14 Raynes: mtm: It's on the 'new' branch.

13:14 chouser: (case x '(:a) :list [:a] :vector) ?

13:14 rhickey: actually they will, it will be based on hash for table lookup, then equals for confirmation

13:14 mtm: Raynes: thanks

13:14 Raynes: Hrm. It appears that the new branch breaks slime.

13:14 Or kind of breaks something related to slime.

13:14 kefka: I've got a question: what Errors can be thrown by a clojure function (assume I haven't created new Exception or Error classes) that should not be caught, but require process shutdown?

13:15 OutOfMemoryError is obviously fatal, while StackOverflowError is not, for example.

13:15 rhickey: chouser: the quote not need - keys are unevaluated, must be constants

13:15 kefka: (the fn that caused the StackOverflow is terminated, but the process keeps running)

13:15 rhickey: but who uses lists?

13:15 chouser: Licenser: yes, clojure could take some occurances of self-calls and turn them into 'recur'. But it would make (foo a b) behave differently depending on where it appears in a single function -- would actually be *more* confusing that current behavior.

13:16 ordnungswidrig: kefka: anything that extends java.lang.Error is considered unrecoverable

13:16 Licenser: hmm so how is tail call optimisation actually done usually?

13:16 and chouser thanks for the answer ;)

13:16 chouser: rhickey: if lists match vectors, then lists could actually be used for grouping tests -- the only drawback then being it looks like a call.

13:16 rhickey: I knew you would say that :)

13:16 mikehinchey: :)

13:16 chouser: rhickey: of course you did.

13:17 rhickey: that was the first grouping example I posted, but you didn't take the bait

13:17 mikehinchey: and if lists are unevaluated, not used for grouping, they also look strange

13:18 somnium: would the set notation only be used to distinguish groupings? (case x :a 1 :b 2 #{:c :d} 3 :e 4)?

13:18 kefka: ordnungswidrig: How unrecoverable? For example, if a thread goes off and does a computation, and that computation throws StackOverflowError, the computation should die, but does the whole process need to be killed?

13:19 chouser: arg. gah. grrrr. () is better than the other options is so many ways...

13:19 in so many

13:19 * rhickey ...

13:19 Raynes: http://gist.github.com/221618 with 'new' Clojure. It then polls slime forever. Not sure if I'm the only one who got this. Just throwing it out there.

13:20 chouser: (case x (one-of :a :b) a-or-b)

13:20 hehe

13:20 ordnungswidrig: kefka: javadoc says: "An Error is a subclass of Throwable that indicates serious problems that a reasonable application should not try to catch. Most such errors are abnormal conditions. The ThreadDeath error, though a "normal" condition, is also a subclass of Error because most applications should not try to catch it. "

13:20 chouser: Raynes: welcome to the experimental branches. -)

13:20 rhickey: chouser: I think a lot of the groups will look like obvious non-functions -> (:a :b :c) ([1 2] [3 4])

13:21 Raynes: chouser: I'm not complaining. Just letting you guys know that it does that, in case you didn't know about it. :)

13:21 chouser: I think AWizzArd said he got slime working

13:23 mikehinchey: Raynes: slime works for me, but my swank-clojure is old. is it looking for pprint, or something else in contrib?

13:23 ordnungswidrig: kefka: this might be enlighting: http://stackoverflow.com/questions/951635/how-to-handle-stackoverflowerror-in-java/951672#951672

13:23 chouser: fn arity overloads, letfn, proxy, defclass, deftype, case

13:23 kefka: ordnungswidrig: Thanks

13:23 Raynes: mikehinchey: I think so.

13:25 kefka: ordnungswidrig: And certainly the point is relevant that AssertionFailedErrors and StackOverflowErrors won't occur in reasonable code.

13:25 On the other hand, I don't want to do a System shutdown when they occur.

13:26 ordnungswidrig: What is the recommented cure against let/if/let/if/let staircasing?

13:26 drewr: ordnungswidrig: there's if-let

13:27 if you're staircasing that then you probably need to break your fn apart

13:27 Licenser: hrm fnparse is broken :/

13:27 chouser: got it. double parens. that looks even less like a fn call

13:27 ordnungswidrig: drewr: can if-let destructurize?

13:27 chouser: (case x ((:a :b)) aorb)

13:27 or maybe (case x ([(:a :b)]) aorb)

13:28 Chousuke: ergh

13:28 drewr: ,(if-let [foo false] :foo :bar)

13:28 clojurebot: :bar

13:28 drewr: ,(if-let [[foo bar] [false true]] :foo :bar)

13:28 clojurebot: :foo

13:28 krumholt: hi i have a question. i wanted to make a stream that only one agent would print on. i implemented it like this http://paste.lisp.org/display/89509 the agents value is the stream it should write on. but it is not writing on the correct stream. can anyone see an obvious error?

13:28 somnium: what if one is an expression? (case x (((:a {:a 1}))) 2) ?

13:28 drewr: ordnungswidrig: it depends on what you're trying to express

13:28 ordnungswidrig: ,(if-let [[foo bar] [false :qux]] bar :baz)

13:28 clojurebot: :qux

13:29 ordnungswidrig: ,(if-let [[foo bar] [true :qux]] bar :baz)

13:29 clojurebot: :qux

13:29 mikehinchey: Raynes: did you get the recent commit for contrib to fix for new?

13:29 chouser: krumholt: use 'binding' not 'let'

13:30 krumholt: i'll try that

13:30 chouser: rhickey: I gotta get lunch, but think on ([()]) ...it'll grow on you, I'm sure of it.

13:31 Raynes: mikehinchey: Yep.

13:31 ordnungswidrig: drewr: I have (let [[t val] (f)] (if-not t :fail (let [[t val2] (g val)] (if t :fail-other val2))))

13:31 AWizzArd: if you want to allow case that it can on the one hand allow complex structures as keys, such as the vector [1 2 3], but on the other hand also allow the user to list many keys on which a "then" part can fire, then a separating construct would be needed.

13:32 rhickey: AWizzArd: not so, see above

13:32 hiredman: it occurs to me that a MetaException might be useful

13:33 djpowell: hmm, defclass can't extend classes? is that temporary?

13:33 hiredman: an exception that supports the alter-meta!

13:33 (I'd really like to get rid of ReaderException)

13:34 krumholt: is it possible that if you use (println) in an agent it is not printing to *out*?

13:35 mikehinchey: rhickey: a quoted vector or set? so the case macro looks for quote. Or maybe ~ unquote would be more clear.

13:35 hiredman: *out* might have a different value in the thread the agent action is running on

13:36 AWizzArd: A very efficient (case ...) construct might get us a step closer to pattern matching.

13:36 rhickey: mikehinchey: then you can't match a list starting with quote

13:36 hiredman: AWizzArd: you've seen the match macro?

13:37 krumholt: hiredman: i thought of that and did (binding [*out* my-stream] ...) in the agent but it's still printing to the wrong stream

13:37 AWizzArd: hiredman: no

13:37 mikehinchey: but unquote isn't legal unless the macro looks for it to use it

13:37 hiredman: ~google clojure pattern matching

13:37 clojurebot: First, out of 1700 results is:

13:37 brool » Pattern Matching In Clojure

13:37 http://www.brool.com/index.php/pattern-matching-in-clojure

13:38 mikehinchey: (case x :a a ~[:b :c] b-or-c)

13:38 rhickey: (case '(unquote ...) ...)

13:39 a copiler might have that

13:39 compiler

13:39 AWizzArd: anyway, i was aiming a bit at the efficiency.

13:40 rhickey: would this case construct be used in conjunction with perfect hashes?

13:45 drewr: ordnungswidrig: I don't immediately see a way to clean that up

13:45 Licenser: Woooh I managed to join the google group with my own email address

13:51 ordnungswidrig: does (f) always return only 2 values?

13:57 fabe: hi

13:58 how do i best access a value of a primitave java array?

13:58 somnium: ,(doc aget)

13:58 ,(doc aget)

13:58 clojurebot: "([array idx] [array idx & idxs]); Returns the value at the index/indices. Works on Java arrays of all types."

13:59 chouser: fabe: http://clojure.org/java_interop#toc27

13:59 fabe: thx

14:10 somnium: is it possible to define type-overloaded methods with gen-class?

14:11 or only object || one type hint?

14:14 Fossi: clojurebot: gen-class

14:14 clojurebot: No, Fossi, you want gen-interface + proxy

14:14 Fossi: somnium: there you have it ;)

14:17 somnium: :)

14:18 I can't wait for 1.1 ...

14:19 Raynes: (doc aget)

14:19 clojurebot: "([array idx] [array idx & idxs]); Returns the value at the index/indices. Works on Java arrays of all types."

14:20 Raynes: somnium: When doing (doc ..), it appears you can leave out the comma.

14:21 somnium: ah, creature of habit I guess

14:21 wooby: trying to compile fnparse, get "Could not find clojure.lang.Compile" whilst clojure.jar is most definitely on my classpath... anyone know whats up?

14:24 somnium: I think someone else mentioned that ^^

14:28 duncanm: hmm, how do i use condp again?

14:28 ,(let [s "foo"]

14:28 (condp #(.equals s %2)

14:28 "foo" "Win"

14:28 :else "Lose"))

14:28 clojurebot: EOF while reading

14:28 duncanm: hmm

14:28 why didn't that work?

14:29 in emacs, i get :else

14:29 somnium: he can't handle newlines

14:29 duncanm: oh

14:29 , (let [s "foo"] (condp #(.equals s %2) "foo" "Win" :else "Lose"))

14:29 clojurebot: :else

14:29 duncanm: oh

14:30 aha

14:30 ,(let [s "foo"] (condp #(.equals s %2) s "foo" "Win" :else "Lose"))

14:30 clojurebot: "Win"

14:31 rhickey: ,(let [s "foo"] (condp = s "foo" "Win" :else "Lose"))

14:31 clojurebot: "Win"

14:31 duncanm: oh nice

14:33 rhickey: ,(let [s "foo"] (condp = s "foo" "Win" "Lose"))

14:33 clojurebot: "Win"

14:33 duncanm: heh

14:33 rhickey: ,(let [s "foops"] (condp = s "foo" "Win" "Lose"))

14:33 clojurebot: "Lose"

15:00 duncanm: is there a reason why I can't use vars this way? http://gist.github.com/221708

15:00 it says Exception in thread "main" java.lang.IllegalArgumentException: Invalid assignment target (FileMonitor.clj:135)

15:00 oh, there's a stray unref there, i was trying out refs

15:04 hiredman: duncanm: I am pretty sure set! is only for setting fields (java interop)

15:04 duncanm: hiredman: it says "Note - you cannot assign to function params or local bindings. Only Java fields, Vars, Refs and Agents are mutable in Clojure."

15:04 hiredman: yeah

15:04 duncanm: hiredman: for this sort of thing, what's the more idiomatic way of doing it?

15:04 hiredman: mutable doesn't mean you can use set!

15:04 duncanm: use a ref?

15:05 hiredman: what is workers?

15:05 oh

15:05 duncanm: monitor and pyramid are SwingWorkers

15:05 hiredman: workers is nil

15:05 nothing

15:05 so you can do nothing to it

15:05 duncanm: oh, but if it's an empty list

15:06 hiredman: so?

15:06 lists are immutable

15:06 duncanm: right

15:06 hiredman: and nil is not an empty list

15:06 no is nothing

15:06 nil

15:07 duncanm: hiredman: so what's the idiomatic way to do something like this in clojure?

15:07 wooby: hiredman: how do i start clojurebot? i'd like to run it on a different network

15:07 hiredman: wooby: rlwrap java -server -Djava.security.manager -cp $CLASSPATH:./clojurebot/ clojure.main -i clojurebot/hiredman/clojurebot.clj -r

15:08 namor: Is there a library to transform/simplify boolean terms in Clojure?

15:08 hiredman: duncanm: I don't know what you are doing

15:08 wooby: hiredman: thank you, is there some way to configure it?

15:09 duncanm: hiredman: i want to toggle these workers, when i call this function the first time, it'll start the workers, if i call it again, it'll terminate the workers

15:09 hiredman: wooby: clojurebot/hiredman/clojurebot.clj

15:09 Chousuke: duncanm: you need a global ref holding the workers

15:09 wooby: hiredman: got it, thanks again

15:10 hiredman: :(

15:11 wooby: there is alot of #clojure specific stuff

15:13 the list of all the required namespaces in clojurebot.clj are almost all different plugins, when you load the plugin's namespace it registers it wires in

15:13 so by taking things out of that list, you can disable plugins

15:13 wooby: i see

15:13 it sure does a lot of stuff, holy crap man

15:14 hiredman: :D

15:16 a lot of stuff is bit rot, like the svn stuff

15:16 the twitter stuff, I should find something to do with clojurebot's twitter account

15:18 Chousuke: duncanm: http://gist.github.com/221716 something like this?

15:18 oops, forgot the stars from one 'workers' :/

15:19 duncanm: Chousuke: i made it work without a global

15:19 Chousuke: well, a closed-over ref will do too I guess.

15:19 duncanm: Chousuke: http://gist.github.com/221718

15:19 right

15:20 Chousuke: those multiple dereferencing operations are somewhat dangerous

15:20 duncanm: Chousuke: why is that?

15:21 hiredman: you should turn the whole thing into a single transaction

15:21 wooby: hiredman: woo runninng! had to excise a lot of clojurebot's brain though

15:21 Chousuke: if you run the function simultaneously in multiple threads you will likely get a non-empty result from the first deref, but an empty one from the next.

15:21 hiredman: wooby: yeah

15:21 Chousuke: hiredman: can't. it has side-effects.

15:21 wooby: hiredman: it's awesome though, what a cool program, thanks

15:21 hiredman: Chousuke: send the side effects off to an agent

15:22 Chousuke: or you could just read the ref once so there's no problem :/

15:22 hiredman: hmm

15:23 or, you could make two functions

15:23 Chousuke: actually, I'm not sure if that model for queuing workers is good.

15:23 hiredman: one that returns a vector of spun up workers

15:23 Chousuke: it looks like you should use an agent or something :/

15:23 hiredman: and another that spins down a vector of workers

15:23 Chousuke: and send it "stop" and "go" :P

15:24 duncanm: hmm, actually, it'd be fun to write a blog post detailing how to use the techniques of clojure's STM for writing GUI programs

15:25 hiredman: well, you can treat the EDT sort of like an agent

15:25 duncanm: hiredman, Chousuke: i'm sure what i'm doing now (having a toggle button that fires off some job) is a pretty common thing to do in GUI programs.

15:25 Chousuke: duncanm: I would use an agent for that.

15:25 or just a thread.

15:25 that runs and then dies.

15:25 duncanm: SwingWorker is some sort of thread, right?

15:25 hiredman: and you use blockingqueues for eventhandlers

15:26 Chousuke: is there a need to store the swingworkers somewhere?

15:26 hiredman: and you turn the events into an infinite lazy seq

15:26 duncanm: Chousuke: it's for cancelling the job

15:26 Chousuke: hm.

15:26 duncanm: hiredman: that reminds me of the Rx framework stuff Erik Meijer is doing for .NET

15:26 hiredman: yeah

15:27 that is what made me do it :P

15:27 clojurebot: hydra?

15:27 clojurebot: Pardon?

15:27 duncanm: hiredman: do you have some sketches of code for doing that?

15:27 hiredman: i'd love to compile a list of 'best practices' for writing Swing code using Clojure

15:27 hiredman: duncanm: http://paste.lisp.org/display/87611

15:27 Chousuke: duncanm: the toggling nature of the function just doesn't please me :P

15:27 hiredman: I dunno if it as a best practice

15:27 I just think it's neat

15:29 duncanm: hiredman: looks interesting, i had a glance, but i need to look into it more deeply

15:29 i'm new to all the Concurrency APIs in Java

15:30 hiredman: hydra is like a multicast que, you stick stuff in, and it comes out multiple places

15:30 the fancy stuff is derefing a hydra produces an end point, which is an infite sequence of stuff that is put into the hydra

15:31 and the hydra is an IFn, so you can all it as a function, and any arguments you pass it get put in the hydra

15:32 there is a (uneeded) delay in there, but, meh

15:32 Chousuke: can you ever stop the queue? :P

15:33 hiredman: not as currently implemented

15:36 so you just do filters, maps, and doseqs over the infinite sequence of events

15:37 duncanm: sigh, i feel like i'm such a naughty boy for writing all this code with SET!s

15:38 Chousuke: heh.

15:38 you'll get over it.

15:38 hopefully :P

15:38 duncanm: hiredman: i have this script that has a handful of globals, and I wrote an INITIALIZE! function, but now it says I can't use SET! to alter root bindings

15:38 hiredman: correct

15:38 you can't use set!

15:38 ever

15:38 duncanm: Chousuke: no, i know, i mean, i wrote Scheme before, but in Scheme, i don't get yelled at when I use SET! - i feel a bit dirty, but no yelling ;-P

15:39 hiredman: (except to set fields)

15:39 chouser: and thread-bound vars

15:39 duncanm: so i have to change them all to refs, and add deref to all the places that use the value

15:39 hiredman: chouser: :(

15:39 duncanm: just don't mutate stuff

15:40 duncanm: hiredman: well, i want some state that's closed over a bunch of functions

15:40 hiredman: :(

15:40 Chousuke: heh.

15:40 duncanm: either i write all of them as internal defines, or i have to do this, right?

15:40 hiredman: state is bad

15:41 duncanm: hiredman: state is useful, it just needs to be managed properly (which i'm not doing) ;-P

15:41 Chousuke: with Clojure, the mutable stuff is (almost) all java. And who learns Clojure to write Java? :)

15:41 duncanm: Chousuke: i do ;-) i use clojure to write portable shell scripts ;-)

15:41 ambient: well, writing java with clojure is still better than writing java with java imho

15:41 hiredman: duncanm: no, managing state can help mitigate it, but it is still bad

15:42 Chousuke: it's also necessary :)

15:42 though people tend to use it even when it's not :/

15:43 rhickey: aargh - contrib defines case!

15:43 chouser: rhickey: do you want deftype and defclass objects to print the same?

15:43 Chousuke: rhickey: :/

15:43 duncanm: rhickey: stuartsierra's fcase.clj?

15:43 hiredman: contrib has a lot of stuff in it

15:44 rhickey: chouser: for now, sure, anything is better than stack overflow :)

15:44 Chousuke: Wonder if it'd help to segment the core namespace a bit? it's getting quite large :(

15:44 rhickey: duncanm: yep

15:45 chouser: rhickey: is there a way to opt out of IObj and ILookup? I'm not seeing it.

15:45 Chousuke: if you split it up, by default you could still import all the subnamespaces to keep compatibility... hm.

15:45 rhickey: chouser: there are no opts yet in or out

15:45 but you can't rely on them

15:45 since one out is just for user to define same interfaces

15:45 chouser: right, I think I'm relying on both and wanted to opt out to see the failure.

15:46 I'll hack it. thanks.

15:47 rhickey: you should have full access to the fields, and you will have access to the class by name while in those macros

15:47 lots of the generated code does that

15:47 AWizzArd: is there a way to get a seq of all fields of a deftype?

15:47 rhickey: so it's not really anonymous for you. also can rely on __meta and __extmap

15:48 hiredman: AWizzArd: implement ISeq :P

15:49 rhickey: (deftype Foo [a b c])

15:49 (seq (Foo 1 2 3))

15:49 ([:a 1] [:b 2] [:c 3])

15:49 chouser: that's exactly what I'm relying on now, and shouldn't.

15:49 rhickey: right

15:50 there is also IDynamicType but you shouldn't need it

15:50 chouser: yep

15:52 __meta and __extmap may not exist, right? what do you mean I can rely on them?

15:55 rhickey: chouser: they will exist

15:55 chouser: even on defclass?

15:55 rhickey: they may not be used, but will be null

15:55 chouser: yes, defclass no different in terms of expando and meta

15:56 chouser: ok, thanks.

15:58 but those fields are only accessible via reflection

15:58 wagjo: hi there, I'm trying to make a lazy seq, which returns characters from file. I open a file with (with-open [r (reader file)] .... ) but I don't know how to transform it into lazy seq, any hints?

15:58 something like line-seq but returning individual characters instead of lines

15:59 chouser: wagjo: maybe something like (repeatedly #(.read r))

16:01 hiredman: ((fn me [rdr] (lazy-seq (cons (.read rdr) (me rdr)))) r)

16:02 wagjo: thank you, gonna try

16:02 chouser: pretty much the same, aren't they? Neither quits at eof.

16:03 hiredman: yes

16:04 chouser: (take-while #(> % -1) (repeatedly #(.read r)))

16:04 (map char (take-while #(> % -1) (repeatedly #(.read r))))

16:04 rhickey: chouser: which only by reflection?

16:04 chouser: (->> #(.read r) repeatedly (take-while #(> % -1)) (map char))

16:05 rhickey: .__meta and .__extmap only by reflection

16:05 oh

16:05 no, you said I have the classname.

16:05 so I can hint to that. sorry.

16:07 rhickey: right

16:08 although by doing so you'll have the same brittleness on re-eval

16:09 chouser: hm.. the old instances will have the old type, and so will use the old print-method.

16:09 rhickey: so better to rely on IMeta and IDynamicType/getExtensionMap for deftypes

16:09 chouser: you should be binding the print method to type, not class, for deftypes

16:09 i.e. the tag

16:10 chouser: oh. indeed I am. sheesh. You can see I barely have my head around this if at all.

16:10 rhickey: the type function ties into deftype types already

16:10 chouser: so: brittleness.

16:10 rhickey: will be gone if you use IMeta and IDynamicType/getExtensionMap for deftypes

16:11 chouser: so deftype and defclass instances can look the same (for now anyway) but should be generated differently

16:11 rhickey: you'll need IDynamicType/getDynamicField as well

16:12 chouser: defclass using direct hinted field access, deftype using IMeta (IObj?) and getExtensionMap

16:12 rhickey: chouser: yes

16:12 getDynamicField will get you out of ILookup

16:12 metadata will not be opt-outable I think

16:13 chouser: I can assume extmap has no keys that match a field?

16:14 rhickey: chouser: won't matter will it, for printing?

16:14 you can just seq that onto the end

16:15 chouser: yep, np.

16:16 * rhickey adds yet more lines to Compiler.java, always darkest before the dawn

16:16 chouser: :-)

16:19 it's ok to assume deftypes implement IObj?

16:19 rhickey: IMeta

16:20 should be enough

16:20 chouser: oh. sorry, had those swapped in my head

16:20 duncanm: chouser: i'm looking over your gist to me earlier, where's the test in the IF-LET form?

16:20 rhickey: yes, IMeta

16:20 duncanm: chouser: http://gist.github.com/221716

16:20 chouser: duncanm: not me. Maybe Chousuke?

16:21 duncanm: oh sorry

16:21 chouser: misfired ;-P

16:21 Chousuke: ping

16:21 chouser: lowercase is insufficient apparently. ;-)

16:21 duncanm: i wonder when the videos from this year's JVM summit will be out

16:23 hiredman: duncanm: (seq @*workers*) is the test

16:23 if let does something, and binds the result to a name, and then (if that-name something something-else)

16:25 duncanm: hiredman: is there a shorter form for writing this? http://gist.github.com/221780

16:25 ordnungswidrig: how can I filter a map on the values?

16:25 duncanm: ordnungswidrig: use filter

16:26 oh

16:26 ,(vals {:a :b :c :d})

16:26 clojurebot: (:b :d)

16:26 duncanm: like that

16:26 ordnungswidrig: duncanm: but I need a map

16:27 duncanm: you want to get {:b :d} back?

16:27 hiredman: if you call seq on the output of .listFiles you don't need to call empty?

16:27 kotarak: ,(into {} (filter (fn [[_ v]] (even? v)) {:a 1 :b 2 :c 4 :d 3}))

16:27 clojurebot: {:b 2, :c 4}

16:27 ordnungswidrig: kotarak: yes, like that

16:27 kotarak: ordnungswidrig: there you go.

16:28 duncanm: hiredman: why is that?

16:28 robewald: hi, what version of clojure does the API on the web refer to?

16:28 hiredman: ,(seq [])

16:28 duncanm: hiredman: oh well, it's okay, i'm fine with that function, i was hoping i can learn some new clojure idioms

16:28 clojurebot: nil

16:29 duncanm: hiredman: but i still have the method call .getAbsolutePath

16:29 hiredman: you could use juxt (my new favorite function) to get a pair of :width and :height instead of a map

16:29 duncanm: correct

16:30 ,(if (seq []) :foo :bar)

16:30 clojurebot: :bar

16:30 hiredman: ,(if (seq [1]) :foo :bar)

16:30 clojurebot: :foo

16:30 ordnungswidrig: kotarak: thanks

16:30 duncanm: how does juxt work? it's not in the api page

16:30 hiredman: ,(doc juxt)

16:30 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)]"

16:31 kotarak: ,((juxt inc dec) 2)

16:31 hiredman: dunno if that is an actual improvement

16:31 clojurebot: [3 1]

16:31 somnium: is there any obvious reason why this won't compile <- http://paste.lisp.org/display/89523 ?

16:31 robewald: or more specifically which git branch. SVN seems to be deprecated.

16:31 somnium: it compiles in slime, but when I do (compile ...) I get cannot create ISeq from Symbol ...

16:31 kotarak: hiredman: well, it generates 3 more functions: the one by juxt and #(.getWidth %) and #(.getHeight %)....

16:32 hiredman: kotarak: *shrug*

16:32 rhickey: I have to ask, is there a reason there is no 'flip' in core?

16:34 rhickey: hiredman: have you needed it?

16:34 I haven't

16:34 hiredman: hmmm

16:34 kotarak: What does flip do?

16:34 somnium: hiredman: I think there's one in contrib

16:35 hiredman: I wrote one, but yes, I don't think I really used it for anything

16:35 kotarak: reverse the order of arguments

16:35 kotarak: ah ok.

16:35 hiredman: ,((flip /) 3 8)

16:35 clojurebot: 8/3

16:38 hiredman: ,(pl (⌽/ 3 8))

16:38 clojurebot: Invalid token: ⌽/

16:38 hiredman: :(

16:38 ,(pl (⌽vector 3 8))

16:38 clojurebot: #<sandbox$uncurry__4597$uc__4599 sandbox$uncurry__4597$uc__4599@c64bc2>

16:38 hiredman: huh

16:39 oh, right, wrong symbol

16:39 ,(pl (↕vector 3 8))

16:39 clojurebot: [8 3]

16:39 hiredman: and you wonder why all the symbols never caught on

16:40 ordnungswidrig: huh, there's unicode in my irc

16:40 kotarak: Es geschehen noch Zeichen und Wunder.. ;)

16:40 ordnungswidrig: ,(doc pl)

16:40 clojurebot: "([& forms]); replaces a $ b with (a b) walking right to left replaces a · b with (comp a b) left to right ⌽a with (uncurry a) left to right ↕a with (flip a) left to right"

16:41 hiredman: ~translate from de: Es geschehen noch Zeichen und Wunder

16:41 clojurebot: It happened before signs and wonders

16:41 ordnungswidrig: hiredman: that's translated a little too literally

16:42 kotarak: hehe

16:42 hiredman: ~translate to de: ok

16:42 clojurebot: OK

16:43 spuz: I'm looking at some clojure contrib code and I see a lot of ::state ::result etc. what does :: mean?

16:43 ordnungswidrig: hiredman: leo.org suggests "Well, Miracles do happen!"

16:43 hiredman: ,::state

16:43 clojurebot: :sandbox/state

16:43 hiredman: ,:state

16:43 clojurebot: :state

16:43 kotarak: hiredman: "There are still miracels and wonders..." maybe more useful translation. An exclamation if something improbable happens.

16:44 ,`cons

16:44 clojurebot: clojure.core/cons

16:44 kotarak: ,'cons

16:44 clojurebot: cons

16:44 hiredman: :: namespace qualifies a keyword with the currect namespace

16:44 it also lets you use alias

16:45 ordnungswidrig: kotarak: not necessarily improbable but sth. you don't expect to happen anymore. Like a decision of a municipal authority.

16:45 hiredman: if you foo.bar alias as bar in your current namespace, ::bar/foo will be :foo.bar/foo

16:48 somnium: does every function in a gen-class have to take a 'this argument or only methods?

16:49 kotarak: somnium: gen-class is independent of the namespace. Only methods take this.

16:49 somnium: kotarak: thank you.

16:51 I keep getting unable to resolve symbol this when I take them out of the non methods...

16:52 hiredman: well, uh, stop trying to use names you haven't bound to a value

16:52 kotarak: somnium: well, you use it there, you have to pass it as an argument.

16:52 somnium: ok, that's how it was, and it could load the namespace, but I got an error on (compile my-namespace)

16:53 lisppaste8: Chouser pasted "deftype redef-and-print anomoly" at http://paste.lisp.org/display/89526

16:53 kotarak: somnium: what might "an error" be?

16:53 hiredman: chouser: arraymap strikes again?

16:53 somnium: cannot create ISeq from Symbol, or vice versa

16:54 chouser: rhickey: is that good or would it be better to merge the extmap with the dynamicfields?

16:54 hiredman: well, stop trying to make an iseq from a symbol

16:54 kotarak: somnium: you quoted something, which you should not. probably somewhere in the ns clause

16:54 somnium: ah, I hope so :)

16:55 chouser: hiredman: nope, overlap between extmap and fields -- can't get there without chanding a deftype on the fly and then poking around at old objects.

16:57 hiredman: Oh

16:57 * hiredman is trailing on datatypes

16:58 rhickey: chouser: I think it tells the user something important

16:58 chouser: ok. it's not entirely accurate -- I mean the value isn't actually stored twice.

16:58 somnium: kotarak: I'm sorry, I'm out of my depth. It compiles in slime but not with (compile). perhaps my mistake will be clear here? http://paste.lisp.org/display/89523

16:58 chouser: Anyway, that works, including metadata, for deftype.

16:58 rhickey: looks nice, maybe we should elide the namespace/package for this non-readable print?

16:59 chouser: defclass isn't there yet.

16:59 ok.

17:00 I gotta go blow leaves around -- you want that patch as-is, or wait for defclass?

17:01 scottj: What higher level good alternatives are there to SQL? (in general, no specific application atm)

17:02 ordnungswidrig: what would be the easiest way to make a date string according to rfc1123 (used in SMTP/Mail and HTTP): Sun, 06 Nov 1994 08:49:37 GMT

17:03 is there a lib or must I go via java?

17:03 hiredman: there is some java class

17:03 simpl date formater?

17:04 http://java.sun.com/javase/6/docs/api/java/text/SimpleDateFormat.html

17:04 ordnungswidrig: hiredman: I know the java :-)

17:04 hiredman: well, there you go

17:05 ordnungswidrig: hiredman: but I avoid it because I managed to go without calling java until now. But now is the time to learn how to do it.

17:05 somnium: scottj: there is contrib.sql and also higher level clojureql

17:05 hiredman: are you kidding me?

17:05 calling java is nothing

17:05 chouser: rhickey: print-deftype.diff

17:05 rhickey: on clojure assembla. bbl.

17:06 ordnungswidrig: hiredman: a little :-)

17:06 rhickey: chouser: cool - thanks!

17:07 hiredman: ,(import '(java.text SimpleDateFormat))

17:07 clojurebot: java.text.SimpleDateFormat

17:09 hiredman: ordnungswidrig: http://github.com/hiredman/clojurebot/blob/master/hiredman/clojurebot/github.clj has some date format snippets

17:12 ordnungswidrig: hiredman: I made it :-) http://gist.github.com/221836

17:31 qed: mmmmm, map!

17:32 hiredman: ,(bean (Date.))

17:32 clojurebot: {:seconds 43, :date 29, :class java.util.Date, :minutes 32, :hours 14, :year 109, :timezoneOffset 420, :month 9, :day 4, :time 1256851963466}

17:34 hiredman: ,(-> (Date.) bean ((juxt :date (comp (partial + 1900) :year) :month)))

17:34 clojurebot: [29 2009 9]

17:37 hiredman: ,(into {} (map (juxt class identity) '({} [] #{})))

17:37 clojurebot: {clojure.lang.PersistentArrayMap {}, clojure.lang.PersistentVector [], clojure.lang.PersistentHashSet #{}}

17:43 wooby: (doc juxt)

17:43 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)]"

17:43 wooby: awesome

17:47 ,(juxt (+ 1) (+ 2) 3)

17:47 clojurebot: #<core$juxt__4916$fn__4934 clojure.core$juxt__4916$fn__4934@9458ea>

17:47 hiredman: ,((juxt (partial + 1) (partial + 2)) 3)

17:47 clojurebot: [4 5]

17:47 wooby: aha

17:48 ordnungswidrig: it's like map but applying a list of functions to a value instead of an function to a list of values?

17:51 kotarak: ,(map #(% 3) [(partial + 1) (partial + 2)])

17:51 clojurebot: (4 5)

17:51 qed: what are partials

17:52 kotarak: qed: partial makes a new function function which calls the given function with the provided arguments + any additional arguments: ((partial + 1) 2) <=> (+ 1 2)

17:53 qed: kotarak: ahh i see

17:53 kotarak: (partial f arg1 arg2) is equivalent to #(apply f arg1 arg2 %&)

17:54 qed: thanks for that :)

18:00 * ordnungswidrig goes to sleep now

18:01 * qed meditates for 15 min

18:03 wooby: ,(-> {:one {:two "X"}} (:one) (:two))

18:03 clojurebot: "X"

18:15 rhickey: case is alive!! http://github.com/richhickey/clojure/commit/5ebed57e1d6d7dc8230fa51e6cd34e22dc1f3a42

18:16 AWizzArd: yay, grats

18:17 btw, I find it good that there now is case.. but I am curious why you added it now. Will it be of use for implementing Clojure in Clojure?

18:17 chouser: AWizzArd: deftype will use case internally for fast lookup when you do (:myfield deftype-obj)

18:17 kotarak: What is it with emacs, that it can't add a trailing newline?

18:18 AWizzArd: chouser: good

18:19 kotarak: do you try it with Strg+o ?

18:19 kotarak: AWizzArd: what?

18:20 AWizzArd: kannst Steuerung + o drücken, das fügt eine neue Zeile ein

18:21 kotarak: AWizzArd: I don't use emacs. But I noticed that often files have only an incomplete line at the end, when they come from emacs users.

18:21 drewr: kotarak: yes, you have to hit return after adding a line at the end

18:22 you're talking about text files ending with \n instead of \n\n?

18:22 or no newline at all?

18:23 chouser: :-( case groups with ()

18:23 AWizzArd: Why should they end with \n\n? From a windows pov I could understand \r\n.

18:23 kotarak: drewr: no newline at all

18:23 AWizzArd: chouser: can you show a minimal example?

18:23 kotarak: But this is rather off-topic. Just some observation.

18:27 rhickey: chouser: sorry

18:29 chouser: AWizzArd: (map #(case % (1 2) :a (3) :b 4 :c (5 6 7) :d :other) (range 10)) ==> (:other :a :a :b :c :d :d :d :other :other)

18:31 duncanm: it'd be nice if range can generating a descend seq

18:31 s/generating/generate/

18:31 AWizzArd: duncanm: maybe you can use iterate?

18:32 ,(take 10 (iterate dec 20))

18:32 clojurebot: (20 19 18 17 16 15 14 13 12 11)

18:32 duncanm: ah

18:32 cemerick: ,(range 10 0 -1)

18:32 clojurebot: (10 9 8 7 6 5 4 3 2 1)

18:32 duncanm: oh!

18:32 cemerick: ,(range 50 0 3/5)

18:32 clojurebot: ()

18:33 wooby: ,(range 1 0 -0.1)

18:33 clojurebot: (1 0.9 0.8 0.7000000000000001 0.6000000000000001 0.5000000000000001 0.40000000000000013 0.30000000000000016 0.20000000000000015 0.10000000000000014 1.3877787807814457E-16)

18:36 kefka: ,(range 0 1 0.1)

18:36 clojurebot: (0 0.1 0.2 0.30000000000000004 0.4 0.5 0.6 0.7 0.7999999999999999 0.8999999999999999 0.9999999999999999)

18:36 wooby: strange

18:37 ,(map #(/ 10 %) (range 0 10 1))

18:37 clojurebot: java.lang.ArithmeticException: Divide by zero

18:38 wooby: ,(map irc://irc.freenode.net/#(/ 10 %) (range 1 11 1))

18:38 clojurebot: java.lang.ClassNotFoundException: irc://irc.freenode.net

18:38 chouser: (map #(case % 1 2 (map inc[1 2]) (range 3) (range 4) (+ 1 2) (inc x) :y) '(map inc range))

18:38 djork: hah

18:39 ,(map #(/ 10 %) (range 1 10 0.1))

18:39 clojurebot: (10 9.09090909090909 8.333333333333332 7.692307692307691 7.1428571428571415 6.666666666666664 6.249999999999998 5.882352941176468 5.555555555555554 5.26315789473684 4.999999999999998 4.76190476190476 4.545454545454543 4.34782608695652 4.166666666666664 3.999999999999998 3.846153846153844 3.7037037037037015 3.5714285714285694 3.4482758620689635 3.3333333333333313 3.2258064516129012 3.1249999999999982 3.0303030303030285 2.9

18:39 djork: ,(map #(/ 10 %) (range 8 11 0.1))

18:39 clojurebot: (5/4 1.234567901234568 1.2195121951219514 1.2048192771084338 1.1904761904761907 1.1764705882352944 1.162790697674419 1.1494252873563222 1.1363636363636367 1.1235955056179778 1.1111111111111116 1.0989010989010994 1.086956521739131 1.0752688172043017 1.0638297872340432 1.052631578947369 1.0416666666666672 1.030927835051547 1.0204081632653068 1.0101010101010108 1.0000000000000007 0.9900990099009909 0.9803921568627458 0.97087

18:39 djork: err sorry, I'm just spamming onw

18:39 wooby: lol

18:40 chouser: ,(range 0 1 1/9)

18:40 clojurebot: (0 1/9 2/9 1/3 4/9 5/9 2/3 7/9 8/9)

18:41 spuz: Has anyone used clojure.contrib.http.agent?

18:42 I'm having some really strange problems with the library. Appear to be concurrency issues :o

18:44 The following just hangs on my REPL: (println (string(http-agent "http://www.google.com" :method "POST" :body "param=true")))

18:44 ,(println (string(http-agent "http://www.google.com" :method "POST" :body "param=true")))

18:44 clojurebot: java.lang.Exception: Unable to resolve symbol: string in this context

18:45 spuz: ,(println (clojure.contrib.http.agent/string(clojure.contrib.http.agent/http-agent "http://www.google.com" :method "POST" :body "param=true")))

18:45 clojurebot: java.lang.ClassNotFoundException: clojure.contrib.http.agent

18:45 spuz: I guess clojurebot doesn't use the contrib libraries

18:55 wooby: hiredman: is there a way to send a message via clojurebot from vimclojure or whatever?

18:56 AWizzArd: spuz: I am using it

18:57 spuz: yes, (string ...) hangs

18:57 You can write your own my-string

18:57 hiredman: wooby: you could run clojurebot via vimclojure

18:57 AWizzArd: (let [a (http-agent ...)] (await-for a 2000) (string a))

18:57 The-Kenny: wooby: I think that would result in spam... You could ask the guys from codepad.org very nicely to include clojure-support. There is a vim-plugin which handles codepad.org

18:57 hiredman: or start clojurebot via the same nailgun instance as vimclojure

18:58 oh

18:58 wooby: hiredman: that's what i have going on

18:58 hiredman: it's really cool

18:58 hiredman: i think sendMsg is my guy, but I can't figure out what to feed it for the first arg

18:59 hiredman: from core?

18:59 wooby: looks like the pircobj is in a ref maybe?

18:59 correct

18:59 spuz: AWizzArd: I don't get it, the doc says the string function will block until the response is completed, but in this case the response never completes

18:59 request even

18:59 hiredman: wooby: yeah

18:59 sendMsg is pretty old and low level

19:00 it is really just a wrapper over pircbot's sendMessage method

19:00 the first arg is a instance of Pircbot

19:00 spuz: for example, this returns fine: (println (result (http-agent "http://www.google.com" :method "POST" :body "param=true")))

19:00 hiredman: which is the :this key in the map that is the bot

19:01 spuz: so maybe something is broken with (string ...)

19:01 AWizzArd: spuz: I also don't understand why string is broken, it looked fine at a first glimpse.

19:01 cemerick: Does pmap ever run ahead of its consumer? I'd like to ensure I'm squeezing everything I can from my cores...

19:01 wooby: (:this @*bots*) ?

19:01 hiredman: cemerick: yes

19:02 wooby: no, when you run run-clojurebot the result is map {} which is The Bot

19:02 this gets but into @*bots*, I guess

19:02 but I've never really used that at all, Chousuke added it

19:03 I gotta run

19:03 wooby: hiredman: alrighty, thakns for your help, this is a lot of fun to play around with

19:09 konr: Do you use scrum or any other methodology to write software?

19:26 wooby: what's the reason for using defonce?

19:35 cemerick: wooby: so reloading a file doesn't clobber any established bindings

19:35 wooby: thanks

19:57 cddr: any examples of using compojure to write out some POST'ed XML to a file?

20:17 sdeobald_: Hey folks. I'm naively about to attempt to port a Ruby library (xml-to-hash) we've built at work to Clojure. Seems like the Clojure version will be much cleaner than the Ruby version.

20:17 With that in mind, it seems like it would be clean enough that someone may have written it already.

20:18 Has anyone seen a function that would turn this: {:tag :TestElement, :attrs {:name "pat", :value "ok"}, :content nil} into this? {:TestElement {:name "pat" :value "ok"}}

20:20 djork: hmm

20:20 destructuring would go a long way there

20:22 wooby: {(:tag thing) (:attrs thing)}

20:22 ?

20:22 or rather

20:22 no, that's right i guess

20:22 where 'thing' is your hash there

20:23 djork: ,((defn foo [thing] {(:tag thing) (:attrs thing)}) {:tag :TestElement, :attrs {:name "pat", :value "ok"})

20:23 clojurebot: Unmatched delimiter: )

20:23 djork: oops

20:23 ,((defn foo [thing] {(:tag thing) (:attrs thing)}) {:tag :TestElement, :attrs {:name "pat", :value "ok"}})

20:23 clojurebot: DENIED

20:23 djork: huh

20:24 wooby: clojurebot doesn't let you defn

20:24 djork: oh

20:24 right

20:24 that was stupid code anyway

20:24 I mean to just use fn

20:25 wooby: ,(let [thing {:tag :TestElement, :attrs {:name "pat", :value "ok"}, :content nil}] {(:tag thing) (:attrs thing)})

20:25 clojurebot: {:TestElement {:name "pat", :value "ok"}}

20:25 djork: clojurebot: I love you.

20:25 clojurebot: It's greek to me.

20:25 wooby: lol

20:25 djork: :( our love can never be

20:26 sdeobald_: Ah, sorry. TestElement was just an example.

20:26 I basically want to follow that same pattern for any arbitrary xml struct-map that comes out of clojure.xml/parse

20:28 wooby: sdeobald_: so you could use something like clojure.contrib.lazy-xml and lazily map nodes to the format you need

20:31 sdeobald_: wooby: Thanks, I'll check it out.

20:31 wooby: np

20:39 chouser: that's nice, but it's not destructuring

20:40 ,(let [t {:tag :TestElement, :attrs {:name "pat", :value "ok"}, :content nil}, {:keys [tag attrs]} t] {tag attrs})

20:40 clojurebot: {:TestElement {:name "pat", :value "ok"}}

20:53 gregoryg: (message "hello")

21:00 wooby: does anyone have a link to that clojure reading list that rich posted? i'm having trouble finding it

21:02 chouser: wooby: http://www.amazon.com/Clojure-Bookshelf/lm/R3LG3ZBZS4GCTH

21:03 wooby: thank you

21:10 i've heard good things about this PAIP book

21:17 tomoj: any clojure.http.agent user's around?

21:18 if I call stream on an agent that uses the default handler, I can read bytes out of the response just fine

21:18 if I use a custom handler which calls stream on the agent and returns it, it EOFs immediately

21:20 man

21:21 myself asking this question yesterday is in the google results today

21:28 konr: What methodology do you use to program in non-OO languages, like Clojure?

21:31 wooby: konr: bottom up and functional

21:31 konr: wooby: but how do you do things like estimate the cost of creating the software

21:32 wooby: the methodology I'm using for Java uses things like the number of classes

21:32 wooby: I wonder if there is anything outside that mentality

21:33 wooby: konr: well typically in languages like clojure your development iterations are faster, because you're developing interactively

21:33 konr: i'm not very experienced but that methodology seems to fit well with all the agile approaches to doing things

21:35 konr: in general you'd spend less time planning and UMLing and more time trying things out, working toward the simplest working thing possible

21:35 konr: then after that your dev becomes functionality driven, and you can do bug fix accounting and stuff to estimate progress

21:46 tomoj: I think you estimate the same way you'd estimate before

21:47 why should OOP have anything to do with your estimation?

21:47 rhickey: deftype/class now use case

21:47 no more need for Foo:blah accessors, will be removing

21:47 (:field x) is faster

21:48 chouser: hah. nice.

21:49 is case doing "perfect hashes"? I can't tell by looking.

21:49 rhickey: chouser: yes, the min-hash code here: http://github.com/richhickey/clojure/commit/5ebed57e1d6d7dc8230fa51e6cd34e22dc1f3a42

21:50 chouser: it's short

21:50 rhickey: figures out the smallest masked/shifted set of bits that is unique amongst the key set

21:50 cemerick: that's stellar

21:50 rhickey: then inside the compiler it builds a tableswitch instruction, filling in any blanks with the default

21:51 cemerick: rhickey: you said this would be applicable to isa?, etc as well?

21:51 rhickey: well, case is there for all purposes now

21:51 its quite neat, works with everything thanks to the pervasive immutability and plentiful literals

21:52 cemerick: but this isn't the DIY perfect hash dispatch that will be needed for protocols

21:52 I'm not sure if I can get that to map to tableswitch or not

21:53 cemerick: I see how it'd work for exact matches, but I don't see the connection to a-la-carté hierarchies.

21:53 rhickey: but my last patch generally tweaked keyword lookup as well, so all of Clojure should be a tad faster

21:53 cemerick: rhickey: were you surprised by AWizzArd's 40% figure, or no?

21:54 rhickey: cemerick: you just figure out the answer once, then rebuild the perfect hash, i.e. you cache the results of lookup

21:54 cemerick: no, I saw that here first

21:54 cemerick: oooh, I get it now

21:54 * cemerick thunks head on desk

21:54 rhickey: defstruct was never about perf, it was about reducing the waste given lots of instances with the same key set

21:55 cemerick: rhickey: right, I was wondering if 40% is a differential you'd expect, compared to structs / maps

21:55 rhickey: more surprising was just now where (:field x) is faster than (Foo:field x)

21:56 cemerick: its easy to get speed by leveraging specificity - after all tese are now classes generated per use, vs one-class-fits-all

21:56 these are

21:57 I haven't done any comparisons to defclass (.field x), I imagine HotSpot can do more with that, but very happy with the all-dynamic perf

21:59 cemerick: I didn't know what to expect, in absolute terms, other than faster

22:09 churib: why returns (take (/ 10 3) '(1 2 3 4) --> (1 2 3 4) four elements?

22:10 tomoj: ~def take

22:11 it keeps subtracting 1 until the number is zero or negative

22:11 and (/ 10 3) is not 3

22:11 clojurebot: is is

22:13 churib: ah, thanks!

22:13 digash: ,(take 5 (iterate dec (/ 10 3)))

22:13 clojurebot: (10/3 7/3 4/3 1/3 -2/3)

23:52 gerry_: (time (dotimes [i 50000]

23:52 (let [b (struct Person1 (str "ok" i) i)]

23:52 (println (:name b)))))

23:53 =>2833 mmsecs

23:53 (time (dotimes [i 50000]

23:53 (let [b (Person (str "ok" i) i)]

23:53 (println (:name b)))))

23:54 =>2790 msecs

23:54 not much perf improvement??

23:55 (deftype Person [#^String name #^int age])

23:55 tomoj: maybe most of your time is spent printlning?

23:55 gerry_: (defstruct Person1 :name :age)

23:58 time of printing should be same

23:59 but this little benchmark isnot useful anyways

23:59 Knekk: gerry_: if println is the bulk of your time you might still have made significant gains, but println is obscuring them

Logging service provided by n01se.net