#clojure log - Dec 31 2008

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

0:00 * Chouser calls it a day.

0:00 falconai: thanks for you help Chouser

0:10 i sometimes see defn written as defn- , what's the difference?

0:11 hiredman: defn- is like java's protected

0:12 falconai: thx

0:14 clojurebot: svn rev 1188; added speculative load when no .clj or .class resource found, for Dalvik VM

0:14 svn rev 1189; unified clojure.main, patch from Stephen C. Gilardi

0:14 svn rev 1190; Make sure all integer ops return smallest representation, patch from Christophe Grand fixed inc/dec long for max/min values

0:14 svn rev 1191; made Repl and Script public again

0:14 svn rev 1192; made method matching handle differ only in return type, resolving to more-derived return type when bridge methods are involved tweaked RT.load for Android tweaked DynamicClassLoader parenting for Android Android now works if you comment out bean in core_proxy.clj (java.beans is not supported on Android)

1:15 timothypratley: (def a (atom 1))

1:15 (swap! a + @a)

1:16 when will @a be evaluated... ie: is it possible that it gets updated before the function + is called?

1:19 "Changes to atoms are always free of race conditions." <--- I read this as meaning no to my question

1:20 but want to understand why... ie: swap! is not a normal function

1:23 Well understand is probabbly a bit much, I'd be happy with confirming this is true :)

1:28 ericlavigne: I imagine that swap! is a macro that locks 'a while performing the operation (+ @a)

1:28 Looks like a no-op though, as you are adding up one number.

1:29 Oh, never mind, I see that swap! uses the first argument for two things.

1:29 So a gets doubled each time.

1:29 timothypratley: that is right. What I want to know is:

1:30 (swap! a * 2) is obviously free of race condition

1:31 while (swap! a + @a) on the surface looks like @a could be evaluated to be 1, but meanwhile another thread changes a to be 2,

1:31 so when swap! applies + to a it does 2 + 1

1:31 ie: a race condition

1:31 ericlavigne: In that case swap! will fail (not change anything) and try again.

1:32 timothypratley: really? I don't think swap! can fail...??? its not transactional

1:32 ericlavigne: The description of swap! says that the function must be free of side-effects because it may be called more than once. That is a good indication of how it deals with race conditions.

1:32 gnuvince: "Internally, swap! reads the current value, applies the function to it, and attempts to compare-and-set it in. Since another thread may have changed the value in the intervening time, it may have to retry, and does so in a spin loop."

1:33 timothypratley: ah!

1:33 great, that explains it perfectly thanks.

1:40 So on the group discussion, Mark E suggested (defn atom-set [a val] (swap! a (constantly val)))

1:41 Now that would create a race because val is evaluated by the atom-set function?

1:50 Chouser: 'swap!' would read 'a', pass it to '(constantly val)' (which ignores it), and then attempts to set 'a' to the value of 'val'

1:51 if no other thread changed 'a', it succeeds and is done.

1:51 if 'a' changed between the time that 'swap!' read 'a' and when it attempted to set 'a', it will go round and try again.

1:52 I don't think that qualifies as a race condition.

1:53 timothypratley: but a was read before swap! was ever in scope: [a val] binds it

1:54 Chouser: no, 'a' is the atom object. you read it's current value by using @ or deref

1:54 timothypratley: (atom-set a (+ @a @a))

1:54 <--- maybe that explains what I'm trying to describe better

1:55 surely here (+ @a @a) gets evaluated and bound to val

1:56 Chouser: yes, I see what you're saying. Using @a in an atom-set of 'a' successfully defeats the purpose of atom and introduces a race condition.

1:56 Congrats. :-)

1:57 timothypratley: hahahaha well thanks... but I still want to confirm how this is avoided by (swap! + @a)

1:57 ie: if swap! is a macro

1:57 then @a wont be evaluated

1:57 but if it is a function, it would be

1:57 Chouser: swap! is a function not a macro

1:57 timothypratley: is there a way I can easily tell what swap! is?

1:58 if it is really a function, then arguments should be evaluated before the function is even invoked (I think - is this really true)

1:58 Chouser: several ways. (doc swap!) doesn't report "Macro" (compare to (doc defn))

1:58 timothypratley: ah! :)

1:59 Chouser: (:macro ^#'swap!) returns nil

1:59 timothypratley: what about your source slurper?

2:00 hmmm I'll try that

2:00 Chouser: typing "swap!" (without quotes) at the repl returns a function instead of throwing an exception

2:00 yep, (source swap!) reveals its defined using 'defn' not 'defmacro'

2:01 and yes, all arguments to a function are evaluated before the function is invoked.

2:02 I think that deref'ing the atom within the args to 'swap!' will generally lead to a race condition. Is this what you were originally contending?

2:02 timothypratley: precisely

2:03 Chouser: yeah, I think you're correct. It is unnecessary and should be avoided.

2:04 Unnecessary because the correct value of the atom to use is passed in to the function you provide to 'swap!'

2:05 This should be pretty easy to test if I can think of the function.

2:08 replaca: Q for you guys: I'm about to extend java.io.Writer so I can build a wrapper that will keep track of what's being printed by print, prn, etc. Can I do this via proxy? I know that I can extend the class, but I need a way of getting at the data I stashed (the current column #).

2:08 I'd rather not do gen-class if I don't have to.

2:08 Chouser: replaca: yes, it's common to have proxy close over state.

2:09 replaca: But I've not done proxy before and I don't see how I can stash/recover a ref

2:09 but can I add a method to retreive it? Or what's the mechanism?

2:09 basically, I want to add a "getCurrentColumn()" method

2:09 but perhaps I want to think about it differently

2:10 Chouser: no, you can't add a method using 'proxy', but you can either make the ref itself or another fn that closes over it visible to the outside.

2:11 replaca: I had to do something quite similar for the 'source' macro. Do you use that?

2:11 replaca: hmmm, that makes sense. I'm not sure how I'll do that in the context of my program (which is throwing Writers around)

2:12 no, is it in contrib?

2:12 Chouser: yes, clojure.contrib.repl-utils

2:12 replaca: ahh, I'll take a look.

2:13 Chouser: I extended PushbackReader, but also for tracking line numbers.

2:13 ah, yes, you may need to start throwing around objects that contain writers.

2:14 replaca: yeah, that's a bunch of conditionals I'd rather not deal with, since I end up pasing them to "print" et al at the bottom

2:14 might be easier just to go the gen-class route

2:14 Chouser: {:writer #<Writer> :col-num (ref 42)}

2:15 bleh, I'd avoid gen-class it at all possible for new application structure.

2:15 replaca: actually, that might work now that I think of it

2:15 Chouser: s/it/if/

2:15 replaca: (I've already got gen-class for typed exceptions)

2:16 Chouser: yeah, I'd recommend avoiding those too. :-)

2:16 replaca: Yeah, I think my problem is I'm prone to do the Java thing for things that feel like Java

2:16 Chouser: but I'm less confident about avoiding typed exceptions. Perhaps there are contexts in which they are the best available answer.

2:17 replaca: and both exceptions and writers feel like I'm "entering java space"

2:17 one of the interesting things about clj

2:18 I keep changing my mind about the exceptions

2:18 Chouser: readers and writers are definitely mutable, which makes dealing with them feel a little less clojurey, but you can still keep those parts remarkably well-contained.

2:18 replaca: one thing I wonder about is the degree to which we'll end up making things that are consumed by other jvm languages

2:19 in which case things like typed exceptions fit

2:19 (the big thing is that I like to be able to specify exactly which exceptions I want to catch)

2:19 Chouser: I've started using the pattern (take-while pos? (repeatedly #(.read rdr)))

2:20 replaca: is take-while lazy?

2:20 Chouser: yep

2:20 replaca: mmm, nice

2:21 Chouser: replaca: you know CL, right?

2:21 replaca: oh yeah :)

2:21 Chouser: so have you considered handling "exceptional cases" using a dynamically bound function instead of a java Exceptoin?

2:21 I don't know CL but I'm under the impression that's a common idiom.

2:22 replaca: right now I'm doing the column-aware directives in CL format, so I want to wrap the stream I'm handed with one that watches what's written and keeps track of newlines.

2:22 Yeah, but clojure really does it the java way, with (try ... catch...)

2:22 Chouser: (binding [*my-specific-error-fn* (fn [details] ...)] (foo ...))

2:23 replaca: although in my case, I could do it as you suggest

2:23 but I do need the non-local exit

2:24 cause I'm 82 layers deep and I realize that I've got a bad parameter

2:24 Chouser: hm, yeah.

2:24 replaca: but then I want to add info to that higher up the stack

2:24 so I can tell the user where he screwed up :-)

2:25 but I might be able to turn that inside out a little bit and then throw a more generic exception

2:25 Chouser: well, you could 'set!' all the info you need into a dynamic var, throw a general Exception, and when you 'catch' be able to get everything you need.

2:26 replaca: I like your first sol'n better! :-)

2:26 Chouser: heh

2:26 replaca: it keep everything together

2:26 *keeps

2:26 in fact I like it a lot

2:26 Chouser: but as you say, you may need to 'throw' to bail out of nested iteration etc.

2:27 replaca: yeah, but you do it like this:

2:27 (binding [*my-specific-error-fn* (fn [details] ...)] (throw (Exception. (str ...error message container both external state and details arg...)))

2:28 *my parens didn't balance :-)

2:29 then I can just call *my-speci...* froom the error point

2:29 nice

2:29 Chouser: oh, the 'throw' is inside the (fn [details] ...) ? makes sense.

2:30 replaca: yeah, so the error site doesn't worry about it

2:30 Chouser: the error site still has to pass in appropriate 'details', but doesn't need to know that you're using Java exceptions or how that info is stored, etc.

2:31 replaca: basically at the error site I have a specific error ("Directive ~Q unrecognized") and a location of that, but not he global state about the format and such. I want to show where in the format string the bad directive was

2:32 right now I have an "InternalFormatException" that has a message (inherited) and :state field that has the position in the format string

2:35 Chouser: Using this mechanism, is there an equivalent to re-throwing the same exception?

2:36 When the *my-spec* fn is called, it still sees itself as the value of *my-spec*, so is there any way to call the outer binding (if any)?

2:36 replaca: well, I rethrow another exception (a FormatException) which has the complete error message

2:36 oh, in the new way

2:37 I'm not sure I completely understand the Q

2:37 Chouser: oh, I guess you could capture the outer value lexically and get to it that way.

2:37 replaca: yeah, that's exactly what I was thinking

2:37 that would be the point, kind of

2:38 so you end up using dynamic binding instead of throw-catch

2:39 which is kind of a cool translation

2:39 Chouser: but still using throw-catch for flow control.

2:39 replaca: yeah, but flow control all the way out of my universe

2:39 rather than inside my universe

2:40 so from my point of view, I'm just using throw

2:40 which is also nice because of clojure's war with checked exceptions

2:41 which makes you have to unwrap things in unpredictable ways

2:41 Chouser: oh, you don't need to use throw to escape from your own section of call stack?

2:42 replaca: I do, but I won't need to catch it again, because I can do all the error processing in the bound function and throw once and for all

2:42 then the caller can catch if he wants or just get an error

2:42 but he probably just wants an error

2:43 Chouser: ah...

2:43 replaca: the intermediate catch was only to give him a better error

2:43 by giving hi a message with precise context

2:43 *hi -> him

2:44 Chouser: so you were specifically using catch and re-throw to add details.

2:44 replaca: yeah

2:45 like this:

2:45 com.infolace.format.FormatException: Directive "<" is undefined

2:45 ~15<~S~;~^~S~;~^~S~>

2:45 ^

2:46 just to get that little ^ in the right place :-)

2:46 Chouser: heh, yeah.

2:46 but a very helpful little ^ it is.

2:46 replaca: but it's the principle of the thing

2:46 yeah, esp. given the fear of "format" :-)

2:47 as was discussed earlier

2:47 Chouser: ok, so this is an even better case for the use of a dynamically-bound function than I was thinking.

2:47 replaca: yeah, could be

2:51 wow, thanks for the brainstorm. I think I can get all my AOT requirements out of the way now

2:52 sweet

2:52 Chouser: yeah, it's a worthy goal. :-)

2:52 replaca: I'm writing up the column-writer now and I think I've got it

2:52 Chouser: excellent!

2:52 replaca: I thought it was worth trying for :-)

2:53 Chouser: I've going to learn how to use your format, aren't I.

2:55 replaca: :-)

2:55 it's a lisp thang :)

2:55 Chouser: funny, it doesn't *look* like lisp.

2:55 replaca: but folks have really been arguing about it for 20 years, so it's up to me to keep it going

2:56 yeah, that's cause you look at the format string, but when you look at the *arguments* it is

2:56 because it let's you give lisp arguments without a lot of control flow around them

2:57 that's what I've always liked about it

2:57 but I get why people don't like it so much, too

2:57 Chouser: I'm a sucker for that kind of argument.

2:58 replaca: but I also have always disliked printf and it's only gotten worse in Java, C# etc.

2:59 once you've learned to love ~[ and ~{ you're doomed :-)

2:59 I even added Roman numerals today

2:59 Chouser: are the ~ just to escape control chars and allow literal text inthe format string?

2:59 replaca: now that's a feature added by someone who stayed up way too late some night back in 1984 :-)

2:59 yeah, like % in printf

3:00 so %s from printf is ~a in format

3:00 Chouser: If so, could we flip that around and escape plain text instead?

3:00 replaca: yeah, internally that's kind of what I do

3:00 Chouser: Then your example above would look like 15<S;^S;^S> or something

3:00 replaca: it's actually a list of lambdas

3:01 now I'm confused

3:01 Chouser: in the (very few) format strings I've seen there appears to be very little plain text.

3:01 replaca: yeah, that's cause lispers are mostly printing structures

3:01 Chouser: naw, don't be confused. I don't know what I'm talking about.

3:01 replaca: and don't care too much about the text

3:01 :)

3:02 the cool one is something like ~{~s: ~8.2d~}

3:03 *the cool one is something like ~{~s: ~8.2d~%~}

3:04 which will print something like this (("corn" 82.5) ("wheat" 13.3)...)

3:04 as:

3:04 Corn: 82.50

3:04 Wheat: 13.30

3:04 and you can line them up and stuff

3:06 Chouser: hm, a bit like destructuring.

3:11 replaca: yeah, or regexes as someone said earlier

3:12 in fact "destructuring regexes" would be cool

3:12 where you got rid of the intermediate group crap and just went straight into sexprs

3:14 Chouser: I think that's what perl6 does -- regexs are callable and can compose other regexs linearly, or can use matched text in-place, etc.

3:15 backtracking must make that all rather interesting to think about

3:15 replaca: yeah, it's too late for me to think about that now! :)

3:15 talk to you later - thanks for your help

3:16 Chouser: :-) yep!

3:54 lisppaste8: Chouser pasted "musings on exception handling" at http://paste.lisp.org/display/72867

4:03 Chouser annotated #72867 with "benefits" at http://paste.lisp.org/display/72867#1

5:30 knapr: I compile successfulyl but when I try to run it fails. should a hmm.class fiel be able to run when you do java hmm ?

5:48 lisppaste8: knapr pasted "compile, run error" at http://paste.lisp.org/display/72868

5:48 knapr: ^^ how should I run that program?

5:48 and when making jars how do I do that? it is just zipped class-files right? but that doesnt seem to do the trick

6:34 hoeck: knapr: there is the jar command which creates java archives

6:35 knapr: to be able to run it with java -jar myprog.jar you need to put a manifest file into the jar

6:36 knapr: you may also look into clojure.jar (opens with winrar) to see how it should look like

6:38 knapr: cant i just run the class file?

6:38 hoeck: of course yes

6:40 knapr: how?

6:40 i get exception thread main or something

6:40 should the clojure function be called -main or main?

6:40 hoeck: mhh, -main needs an argument for commandline args

6:47 and then run with java -cp your-path-to-classes;path-to-clojure.jar progs.comex.compileexample

6:49 so yes, the function should be called -main

7:44 Lau_of_DK: Good afternoon everyone

9:10 duck1123: Can anyone tell me why (partition-by odd? [1 2 3]) blows the stack?

9:22 AWizzArd: duck1123: which svn?

9:23 duck1123: one sec

9:23 AWizzArd: is this in core?

9:23 duck1123: 1185

9:23 partition-by is in seq-utils

9:24 clojurebot: latest?

9:24 clojurebot: latest is 1192

9:25 duck1123: contrib is rev 313

9:26 durka: clojurebot: latest contrib is 313

9:26 clojurebot: Ok.

9:26 durka: clojurebot: latest contrib?

9:26 clojurebot: latest contrib is 313

9:27 duck1123: clojurebot: latest contrib is 334

9:27 clojurebot: Alles klar

9:28 duck1123: I'm not running the latest

9:29 AWizzArd: latest is also broken

9:30 duck1123: it works fine with a list, but not a vector

9:31 it wasn't what I was looking for anyway. I wanted a seq broken into those that match, and those that don't. This wasn't it

9:33 AWizzArd: you will have to write your own filter for that, if you want to do it efficiently

9:34 otherwise you could simply say [(filter odd? numbers) (remove odd? numbers)]

9:34 duck1123: This is a one-off transformation script, so efficiency isn't a concern. I just thought there was a fn that did exactly that.

9:59 craigmarshall9: Can someone give me a hint towards implementing my own sort function please?

10:00 RSchulz: Do you need to implement sort, or do you just need to sort things?

10:00 craigmarshall9: I am trying to implement sort as a learning exercise, but am stuck at the first hurdle!

10:00 RSchulz: Have you implemented sorting algorithms before?

10:00 craigmarshall9: I just don't seem able to think in an FP way yet...

10:01 I could do it in python or similar, yes.

10:01 RSchulz: I'm still a complete rookie at FP.

10:02 Which sort algorithm are you implementing?

10:02 duck1123: FP is a little different, because you're not going to be going around and mutating your variables

10:02 lenst: merge sort seems a good match for FP

10:02 duck1123: have you implemented sort recursively in another language before?

10:02 craigmarshall9: I don't have a particular algorithm in mind (I wouldn't know the names or details of any, anyway), just anything that actually does a sort would be good enough at the moment.

10:03 No - the recursive nature is half the problem, and the "no variables" is the other half :-)

10:03 Actually, now I think about it, I have played with both quicksort and bubble sort in python.

10:03 duck1123: We had to do a recursive sort in my C++ class a couple weeks ago. My clojure experience really helped there.

10:04 geofft: You can write a quicksort with FP if you have the function that duck1123 wanted earlier

10:04 split into sublists less the pivot and greater than the pivot, and then recurse.

10:04 craigmarshall9: Yes - that approach sounds familiar.

10:05 I think maybe I should be attempting easier things with clojure at this point though.

10:06 duck1123: it's interesting that functional and imperative programming have different ideas about what is easy

10:07 walters: shouldn't be surprising, different languages are good at different things

10:07 craigmarshall9: I'm only just at the stage of "Add a supplied 'param' to the start, middle and end of a list/vector" as far as FP goes...

10:09 Okay - I'm going now, off to see if I can make quicksort work.

10:09 (thanks)

10:09 duck1123: does anyone remember the key command to change namespaces in slime off hand?

10:10 drewr: duck1123: I just type it at the REPL...

10:10 (in-ns '...)

10:10 That and M-p are pretty sufficient.

10:11 duck1123: right, there is a command that'll prompt you inthe minibuffer with completion

10:11 hoeck: C-c M-p ?

10:11 duck1123: I found it while reading the slime manual, but can't remember it

10:12 hoeck: that's it, thanks

10:12 drewr: Cool, didn't know about that one.

10:13 duck1123: I was looking for a whay to implement that, when I discovered it had already been done. :)

10:13 I just wish it used ido-completing-read

10:16 craigmarshall9: Well - with the power of google, I found this: http://swisspig.net/r/post/blog-200603301157

10:16 (LISP quicksort)

10:42 duck1123: There needs to be an (i-need 'symbol) function. Searches all namespaces for a function with that name. Uses that function if only one result, otherwise returns list of matching namespaces. for REPL use only.

10:43 (i-need 'spit)

10:43 AWizzArd: duck1123: that function is available in Firefox, when you visit google.de :-)

12:13 CardinalFang: Hi all. I'm eager to write some apps for Android, but I don't want to use Java. My worry is that importing Clojure will make my apps uncomfortably big, for a phone's memory. Before I dig in a lot, I want to know: If my code is simple, can I decouple the "eval" part of Lisp/Clojure, so I don't need a Lisp interpreter in the JVM? Maybe I can get the compilation part of Clojure to get from Lisp to a ".class" or ".jar" file, without the space used by an

12:13 interpreter later.

12:14 walters: CardinalFang: there's no interpreter

12:14 CardinalFang: Would you prefer the word "compiler"?

12:15 walters: i doubt the compiler is very large, though i could be wrong

12:15 CardinalFang: It doesn't have to be "very large" to be too large.

12:16 rhickey: CardinalFang: there are lots of opportunities to trim things down, but no work done yet. I think a first target would be to get rid of metadata in the compiled code. Stripping out the compiler is a bigger task, as there is some utility code in there that is used even when not compiling. Dropping ASM would be a huge cut

12:25 CardinalFang: rhickey, ah, thanks.

12:25 danm_: good morning

12:27 CardinalFang: (Whew! I feared my question would reveal my shallow understanding of the internals of Lisps and seem incredibly silly.)

12:29 craigmarshall9: Does anyone know what this error means: Don't know how to create ISeq from: Integer

12:30 walters: craigmarshall9: someone called e.g. (seq 42) ?

12:31 hoeck: craigmarshall9: like in (map + 1)

12:38 craigmarshall9: I think it means I don't know how to treat a single integer as a sequence, but I don't think my code is trying to do that.

12:41 good evening :-)

12:48 replaca: Q: do proxies handle overloading? I'm trying to proxy java.io.Writer by overriding only the write method that is defined as abstract and I'm getting a "wrong number of args" exception on the write. This makes me think it's using my write func for a different overload.

12:48 lisppaste8: replaca pasted "Using a proxy to wrap java.io.Writer" at http://paste.lisp.org/display/72877

12:49 replaca: but I could be doing something stupid, too. :-)

12:49 vogelrn: craigmarshall9: Did you fix your problem? It might be that you forgot your argument list

12:51 lisppaste8: replaca annotated #72877 with "How I'm calling it" at http://paste.lisp.org/display/72877#1

12:51 craigmarshall9 pasted "Boken quicksort" at http://paste.lisp.org/display/72878

12:53 craigmarshall9: Yes - that's what it looks like - I'm trying to debug a quicksort function, and I've spotted "(first coll)", but I thought coll was a single element collection at that point...

12:55 Chouser: replaca: proxy method implementations can provide multiple arity bodies, just like regular functions.

12:56 replaca: hmm, ok. Time to debug, I guess. Thanks!

12:57 craigmarshall9: I've got something broken somewhere!

13:10 triddel1: Can a def be made lazy? I have some clojure code that works just the way I want... I've even compiled it into a class and used from Java (which will be the main use.) Now I'm just trying to add a constructor for one string variable I need as parameterized state. Since this string is not available unless an object is created, other defs are try to execute (load configuration files) with no value and failing on compile.

13:10 vogelrn1: craigmarshall9: You need to have (list (first coll)) instead of (first coll) in the if statement

13:10 otherwise it tries to concat an int

13:16 craigmarshall9: you also need to handle the 0 count case separately from the 1 count case then

13:17 replaca: so proxy does support overloads, but it appears to have a small bug. If you don't override all the overloads of a method from an abstract class, it won't go to the superclass for the ones you didn't implement.

13:18 lisppaste8: replaca annotated #72877 with "Corrected implementation" at http://paste.lisp.org/display/72877#2

13:19 replaca: I would tell you I shouldn't need the second version of (write ...) in the proxy pasted here

13:43 Chouser: triddel1: your problem is at compile time?

13:44 replaca: are you sure you can still get to the 3-arg overload of write?

13:44 triddel1: Chouser: yes... probably my misuse of something.... I have a def like this: (def app-cfg (load-yaml-config (str solo-path file-sep "application.yaml")))

13:45 Chouser: replaca: I think to provide both you might need the format (write ([cbuf off len] ...) ([s] ...))

13:45 triddel1: that tries to load a file... the path string is something I'm trying to now do as a constructor value

13:46 Chouser: triddel1: I think you may be able to test *compile-files* to get what you want.

13:46 triddel1: so clojure still executes this on compile I guess

13:46 Chouser: (def app-cfg (when-not *compile-files* (load-yaml-config ...)))

13:47 craigmarshall9: What does it mean when a function starts : (defn foo [[pivot & vals ]] - specifically the double square brackets?

13:47 Is that documented anywhere?

13:48 Chouser: craigmarshall9: that's destructuring. same format as 'let': http://clojure.org/special_forms#let

13:48 triddel1: Chouser: or maybe there is also a better way... what's easiest way to basically get a parameterized field value through a constructor? when I say :state state, this is not know to clojure functions right?

13:48 craigmarshall9: thanks

13:50 triddel1: Chouser: but I'll look at using *compile-files*

13:57 replaca: Choser: Hmmm, I don't know. Let me try. But my bigger point is that I shouldn't need the 1 argument version (since it's supplied by the superclass)

13:59 *Chouser: that is :-)

14:01 chrisn: has anyone here used miglayout?

14:02 AWizzArd: OMG, Rich is Santa! http://www.dancingsantacard.com/?santa=6977602 :-)

14:04 vogelrn1: that's slightly frightening :P

14:06 rhickey: ho ho ho!

14:51 craigmarshall9: Is there a vuilt-in function that will tell me whether an item is in a collection? Like the python's "in"?

14:51 *built-in

14:51 I want to do (in? "w" '("x" "y" "z")) and get false, for example.

14:53 hiredman: you could use some

14:53 (doc some)

14:53 clojurebot: Returns the first logical true value of (pred x) for any x in coll, else nil.; arglists ([pred coll])

14:53 craigmarshall9: Okay - thanks.

14:54 pjb3: craigmarshall9: clojure contrib has an includes?

14:54 craigmarshall9: okay - thanks for that too

14:54 vogelrn1: craigmarshall9: as I learned recently, specifically like (some #{item} coll)

14:55 craigmarshall9: excellent, I'd already made the in? function, but thought I'd better use a standard one if one exists.

14:55 And several do, apparently!

15:02 RSchulz: Q: Is destructing binding implemented in Clojure or Java?

15:02 "destructuring"

15:03 rhickey: RSchulz: Clojure

15:03 RSchulz: Excellent, thanks.

15:03 Did you invent the algorithm yourself?

15:04 rhickey: nothing to invent really - I did first impl, Chouser has helped along the way, see destructure in core.clj

15:05 craigmarshall9: @ line 2260 approximately

15:06 RSchulz: OK. But it's similar to tree regular expressions, isn't it? Similar to RELAXNG schema validation? I could never find any good references.

15:07 rhickey: http://groups.google.com/group/clojure/browse_frm/thread/38d2477f7d7133a/391f86cea65444eb

15:07 craigmarshall9: Q: How would one go about counting unique items in a list? Is it possible with reduce? I would normally start a new list and only copy the item across if it weren't already there, but isn't this impossible in clojure?

15:09 Another idea I've had is automatically map them to the keys of a hash-table, then return them, but ... Again this seems difficult.

15:09 rhickey: craigmarshall9: (count (distinct your-list))

15:09 craigmarshall9: Ha! Thanks.

15:09 RSchulz: rhickey: Thanks for the reference.

15:10 rhickey: RSchulz: I'm afraid it's rather mechanical, it's not unification or anything

15:10 RSchulz: Yes, since it's one-sided, it wouldn't have to have the properties of unification. Still pretty interesting.

15:54 duck1123: okay, if I have a file containing a form, what's the best way to read that into a var? I can't figure out how to get a PushbackReader from a filename.

15:55 Chouser: (read (java.io.PushbackReader. (java.io.FileReader. "/tmp/foo.clj")))

15:57 duck1123: thanks

17:52 replaca: condp is awesome! It's a great addition to core.

18:04 AWizzArd: HNY!

18:07 replaca: AWizzard: right back at ya!

18:09 RSchulz: I'm clinging to 2008 for another 8 hours, 51 minutes and 15 seconds

18:11 Chousuke: I'm in 2009 already

18:12 so far so good.

18:18 replaca: I'm whipping around the Sun in the same orbit as RSchulz apparently

18:18 hoeck: happy new clojure year 2009!

18:18 replaca: In SanFran, we still have a while to go

18:19 Dare we hope that 2009 is clojure's breakout year? Wouldn't that be fun!

18:20 dreish: I thought I read once about a way to get an unquoteable quote _without_ namespace resolution. I.e., '(foo ~(+ 1 2) bar) evaluating to (foo 3 bar) instead of (user/foo 3 user/bar). Anyone know of that?

18:22 RSchulz: replaca: Not that orbit where you can make 364 gifts given at the rate of one every other day last only one year.

18:22 (I'm in Googleville, by the way.)

18:23 duck1123: <-- Michigan

18:23 replaca: ha-ha! Nice place to be. I'm in SoMa/North Beach, depending on the tim eof day

18:24 *tim eof -> time of

18:27 dreish: I don't see anything in LispReader. My vote would be for #`

18:30 replaca: dreish: I did that before, but I think it meant skipping backquote and doing some consing

18:30 dreish: replaca: You know about the ~'sym trick, right?

18:31 replaca: Which one is that? Maybe it's how I did it...

18:31 dreish: I have to admit this isn't an actual need. I was just playing around with quoting.

18:31 Leap second in 30 minutes, folks.

18:31 replaca: Hold on tight!

18:31 dreish: replaca: Inside a syntax-quote, ~'x will become x, rather than user/x. Go ahead and try it at a repl.

18:32 In case you _really_ want variable capture, that's the way to do it.

18:32 replaca: That's right, now I remember!

18:33 dreish: ,(meta '#^Object x)

18:33 clojurebot: {:tag Object}

18:33 dreish: ,(meta #^Object 'x)

18:34 (clojurebot doesn't want to say it, but the answer is nil)

18:34 gnuvince: Have we got an interpreter?

18:34 ,(+ 3 4)

18:34 clojurebot: 7

18:34 gnuvince: ooh!

18:34 Who did that?

18:34 dreish: clojurebot: author

18:34 clojurebot: excusez-moi

18:35 dreish: Hmm. Can't remember who wrote clojurebot.

18:35 It's had that for at least a week or two.

18:35 gnuvince: I think it's a Java bot

18:35 cmvkk: just tell the bot to do something really lengthy and time consuming and then wait and see who comes in here and yells at you.

18:35 gnuvince: Did they get around the obvious problems of side-effecting code?

18:36 replaca: I think chouser and hiredman were working on it

18:36 They discussed the sandbox a lot

18:36 dreish: ,(apply + (range 0 10000000))

18:36 clojurebot: 49999995000000

18:36 gnuvince: ,(println "hello")

18:36 clojurebot: hello

18:36 gnuvince: ,(throw (Exception. "sorry"))

18:36 clojurebot: java.lang.Exception: sorry (NO_SOURCE_FILE:0)

18:37 gnuvince: neat

18:37 dreish: ,(time (apply + (range 0 10000000)))

18:37 clojurebot: "Elapsed time: 2811.943 msecs"

18:37 49999995000000

18:45 RSchulz: clojurebot is the brainchild of hiredmind.

18:45 clojurebot: hiredmind?

18:45 clojurebot: It's greek to me.

18:45 RSchulz: clojurebot: hiredmind ?

18:45 clojurebot: Titim gan �ir� ort.

18:45 RSchulz: clojurebot: who is hiredmind?

18:45 clojurebot: Pardon?

18:45 RSchulz: He used to know his creator...

18:45 Chouser: clojurebot: hiredman?

18:45 clojurebot: hiredman is an evil genius.

18:45 RSchulz: Maybe his KB wasn't fully restored after the crash.

18:45 There we go.

18:46 Oh. That's it, _hiredman_ not, hiredmind.

18:46 I like hiredmind...

18:47 hiredman: clojurebot: who is your creator?

18:47 clojurebot: No entiendo

18:47 RSchulz: Were your ears ringing?

18:47 hiredman: Chousuke has done a lot of great work in his clojurebot tree on github, I just haven't had time to do anything with it

18:48 durka: i think clojurebot needs an answering machine service

18:48 RSchulz: Not to mention and Elisa module.

18:49 clojurebot: I'm feeling down.

18:49 clojurebot: I don't understand.

18:49 durka: that would fulfill the lisp/ai stereotype

18:49 RSchulz: clojurebot: Well, this time of year...

18:49 clojurebot: Titim gan �ir� ort.

18:49 RSchulz: You know, Weisenbaum wrote Elisa to prove to people that AI was a sham. Instead, people confided in it!

18:50 replaca: Actually, he proved that psychotherapy was a sham :-)

18:50 RSchulz: Well, _Rogerian_ psychotherapy, anyway...

18:53 retep: BTW: Happy new year. At least in germany.

19:24 durka: what's the idiomatic way to concatenate a bunch of strings?

19:24 i.e. (concat root-path "/" class-name ".class")

19:25 gnuvince: ,(str "foo" "bar" "baz")

19:25 clojurebot: foobarbaz

19:26 durka: aha

19:26 was about to use format, but i don't need any formatting so it would be overkill

19:36 i'm writing a thing to automatically find missing imports

Logging service provided by n01se.net