#clojure log - Oct 11 2008

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

6:28 Lau_of_DK: In emacs, the default binding for Clojure-eval-defun is (C-M-x) but this does not work for some reason, simply no reaction. How do I bind this function (that I dont even know whats called) to something like C-c c ?

6:30 tWip: Does C-h k C-M-x describe the command?

6:31 I think it should be lisp-eval-defun

6:31 Lau_of_DK: tWip, it does not, no reaction

6:32 but yes, the command is lisp-eval-defun

6:32 tWip: you could try M-x local-set-key

6:32 to bind it

6:33 Lau_of_DK: What is the shortcut for ending the key-sequence, if I press enter it does includes that in the mapping

6:35 tWip: It should work without enter

6:35 I'm not really an emacs master myself.

6:35 Lau_of_DK: Ok, I'll fiddle with it. Thanks alot tWip

6:35 Hun: are you sure the major-mode is proper? it might just eval it as a emacs-lisp-defun

6:36 here C-M-x is bound to slime-eval-defun which sends stuff through swank

6:37 Lau_of_DK: If you mean wether or not I'm on Clojure-mode, then yes I am

6:37 Hun: oh, clojure-mode. don't know that, i use slime with clojure here

6:39 Lau_of_DK: Same here, Clojure-mode only handles formatting I think

6:40 Anyway, we can drop the subject, because when I bound it to C-x C-x it actually works, so I'm up and running

6:40 Thanks alot for your input, both of you

7:04 leafw: is there any reason why (map println (range 0 10)) prints numbers mixed up with the sequence full of nils ?

7:05 I would expect the sequence to print at the end, not at every iteration

7:25 fyuryu: leafw: you should avoid side effects in map

7:25 leafw: (doseq i (range 0 10) (println i))

7:26 leafw: it was just a test

7:32 I can't find how to say: do this N times.

7:33 without (doseq i (range 10) (....)) , where I don't need the i at all

7:33 same for looping. And for map, it creates and returns a seq that I don't need

7:34 kotarak: leafw: then you use side-effects. I would try to eliminate the side-effects if possible.

7:35 side-effects are not the way clojure encourages..

7:35 leafw: I need the side effects.

7:35 I know. Thanks anyway. this is an exisiting library, can't override its behaviour, just script it nicely.

7:35 kotarak: then what changes between the loops?

7:35 Iterate over that instead of "i"

7:36 leafw: I am processing lines of an image with multiple threads. Each thread grabs the next available line for processing.

7:36 the side effect is the editing of that image. And no I can't afford to duplicate it, not enough RAM.

7:40 fyuryu: for i in range(N): do_something() is a a common idiom in python

7:40 it translates nicely to Clojure with doseq or dotimes

7:41 leafw: dotimes, that's it

7:42 got erased from my mind for some reason

7:46 still, dotimes also uses an iterator ... never mind

8:17 I am puzzled by an error message: java.lang.IllegalArgumentException: Unable to resolve classname: int (macro_multithread.clj:72)

8:17 the code: (let [#^int offset (* width row)]

8:17 ...)

8:18 where width and row are also declared as #^int

8:18 kotarak: Hmmm... int is no class. Try #^Integer maybe.

8:19 I don't whether one can declare basic types like this.

8:19 I don't know ..

8:19 leafw: (let [#^int i 0] (println i))

8:19 this works.

8:20 but I am not sure if it does what I intend

8:21 debugging clojure remains ... hard. Very hard.

8:23 and with macros, java stack traces are wrong.

8:23 i.e. they don't point to the right line on the code

8:27 and it would be great if macroexpand would print the statements with indentation and in separate lines ...

10:14 Chouser: leafw: I think primitive locals are declared thus: (let [offset (int (* width row))] ... )

10:15 leafw: that is casting, which sets the value, but does not add type declaration to the offset (I think)

10:15 Chouser: yeah, I know one woudl think that, but I'm pretty sure that's how you get a primitive local.

10:15 Let me see if I can find an example.

10:16 leafw: ok, let's see

10:16 indeed #^int is not accepted

10:17 rhickey_: leafw: this is pretty well documented at: http://clojure.org/java_interop, under Support for Java Primitives - did you read that?

10:18 leafw: I read indeed, rhickey_

10:19 basically it means it's automatic. i.e. (let [offset 512] would have offset as primitive directly

10:19 is that right?

10:20 rhickey_: No, 512 is an Integer without the (int ..) coercion

10:20 else math would be bad by default

10:20 leafw: by the way I created a macro to multithread the processing, in place, of lines in an image ... if there's something grating about it that I should know, I would appreciate very much. It's named "multithreader" and it's here: http://pacific.mpi-cbg.de/cgi-bin/gitweb.cgi?p=fiji.git;a=blob;f=plugins/Examples/Multithreaded_Image_Processing.clj;hb=HEAD

10:21 rhickey_: ok, then I need to add a couple of casts. Someday ...

10:21 thanks for your infinite patience -- if anything reasures me of the outcome of a project, is the patience of its developer(s)

10:28 Chouser: println will print the number and then return nil

10:29 gah, sorry, I was scrolled way back.

10:41 alec: Is there a clean way to create a map with keys as strings and do case-insensitive lookups, like a Common Lisp equalp hash? I can always hack up an indirect lookup.

10:44 Chouser: I don't think so. I'd just use a transformed string as the key, and keep the original key and value in the map value.

10:45 {"foobar" ["FooBar" "value"]}

10:47 Lau_of_DK: Is there someone in this group, who has superior RegEx skills?

10:48 Chouser: Lau_of_DK: Try asking your question, maybe someone will know something.

10:50 Lau_of_DK: Okay, I just figured that it wasn't too polite to have the actual RegEx discussion in a Clojure group. But since you ask :) I need a Regex that can identify the longest recurring cycle of digits in a string. For instance "1111111" is seen as a 1-digit cycle, and "123456123456" is seen as a 6-digit cycle

10:50 Chouser: hm, that's a good point -- wouldn't want to be OT

10:50 Lau_of_DK: Okay - Feel free to MSG me if anybody has a take on this

10:55 alec: Lau_of_DK: regular expressions are probably inappropriate, but I bet you could write some cool Clojure code taking a dynamic programming approach, and then it'd be on topic

11:02 Chouser: (second (re-find #"^(.*?)(?:\1)*$" "123123123123"))

11:03 hm, I think that's the shortest recurring cycle.

11:04 oh, and that requires my regex patch to clojure

11:05 rhickey_: Chouser: sorry I haven't pulled the trigger on that - not for lack of support for it - just working on extensible print/read

11:06 Lau_of_DK: Chouser, how to I apply the patch, and how does this patch extend Clojures way of doing it ?

11:06 Chouser: rhickey_: np -- I don't see it as urgent, as long as it's inevitable. ;-)

11:06 rhickey_: Chouser: yes, inevitable

11:06 Chouser: Lau_of_DK: skip it. Without my patch, use #"^(.*?)(?:\\1)*$"

11:06 rhickey_: you're changing how read/print work?

11:07 Lau_of_DK: k

11:08 rhickey_: Chouser: extending - #=(java.util.HashMap. {:a 1 :b 2 :c 3}) will read a literal HashMap

11:08 #=(java.util.Date. "Sat Oct 11 11:05:23 EDT 2008") reads a Date

11:08 Chouser: rhickey_: ah, right. forgot you were working on that. Does the syntax keep chaning?

11:09 rhickey_: as does #=(java.util.Date. 2008 10 11)

11:09 #<...> doesn't work because > is not a terminating macro character, i.e. it is a constituent character - can be part of a symbol

11:10 I don't want to repeat the C++ space before > travesty

11:10 Chouser: indeed!

11:12 rhickey_: but I've refined the semantics over the last couple of days - I had ##(expr) which evaluated the expr, but that ends up being too big a hammer for read, so #= constructs values with the unevaluated (i.e. as-read) args

11:13 ends up being very nice, essentially you can read it as - the value you would get from this expression, give literal args

11:14 it means people can extend print/read by just making prints that target #=

11:14 Chouser: Ah! nice

11:14 rhickey_: you can call ctors, static methods and instantiated vars

11:16 plus class literal: #=java.util.ArrayList, and vars: #=(var clojure/rest)

11:17 makes print/read a powerful and easy serialization tool

11:17 tWip: so you could embed java serialized objects in sexp

11:17 rhickey_: always on the todo list but I need it for AOT compilation

11:17 tWip: yup

11:18 tWip: very nice, clojure seems to be going forward in leaps and bounds

11:28 rhickey_: A Clojure-derived Lisp for the AVM2: http://github.com/aemoncannon/las3r/wikis

11:33 Chouser: you and he should talk

11:33 Chouser: yeah, looks like he's done more work than I

11:34 rhickey_: He's transliterated the compiler and dropped a bunch of stuff, I think the ClojureScript approach (just a different backed + support libs) has definite advantages

11:34 back-end

11:34 ClojureScript is still Clojure

11:36 Chouser: are you in touch with him? I see only one post that might be his on the group.

11:40 rhickey_: Chouser: not too much, he contacted me once or twice when starting out, then last night to let me know it was up

11:42 fun - this is the default print behavior:

11:42 user=> (java.util.Date.)

11:42 #=(java.util.Date. "Sat Oct 11 11:36:40 EDT 2008")

11:42 That's with no special print for Date!

11:43 Chouser: I'm way too lazy to solve the problem the he'd done. He's going to have work to do to keep his boot up to date.

11:43 rhickey_: Chouser: right, it's not Clojure anymore

11:43 Chouser: nice. And Date will probably even read that, right?

11:43 rhickey_: exactly

11:44 tWip: how do you know that Date does not have some secret state?

11:44 rhickey_: many types have ctors that can read their toString output

11:44 if they do, this works by default, if not define custom print

11:45 Chouser: but now that print is a multimethod, that's easy to provide without a Clojure patch.

11:45 rhickey_: tWip: if they have a public string ctor, it'd better produce a valid object

11:45 Chouser: right again

11:45 Chouser: And read is sufficiently generic already that new patches there shouldn't be necessary.

11:46 ...with the exception of things like my #"" which want to screw around with quoting rules.

11:46 tWip: yes, but If I have a class that has a public string ctor, but still has some other state that is not printed in toString)

11:46 rhickey_: It solves a fundamental problem, that the reconstitutor might not have the corresponding libs loaded yet, or ever

11:47 tWip: then you define a print-method for that class, this is just a useful default

11:47 tWip: ok, so it is optimistic in trying a public string ctor, if available

11:47 I agree, that it will be very useful in many cases

11:48 rhickey_: the only other possible default is error

11:56 Chouser: aemon's containers can't be called.

11:56 I don't really like how that works in ClojureScript right now.

11:56 But the other solutions I've thought of are all rather clumsy too.

11:57 rhickey_: Chouser: how so?

11:58 Chouser: AFAICT, the only thing that can be called directly in js is a Function.

11:59 A Function can either be made using the constructor and passing in a string (ew!) or literally saying function(){}

12:00 I could possibly make container instances using function(){}, but they'd essentially be closures (which I've now learned is slow) and they wouldn't participate in js inheritence.

12:01 So for now, anytime I generate code to call something that might be a container, I emit foo.apply(this,[...])

12:02 apply works on real functions, and is also a method I've written for AFn.

12:02 rhickey_: sounds ok to me

12:07 Chouser: It's a bit slower than a regular function call. I don't know if it's just the new array being made, or if the call itself has more overhead.

12:07 plus it's ugly :-/

12:08 rhickey_: I missed the array, yeah.

12:10 Chouser: Another option is foo.call(this,arg1,arg2,...), but that's also slower than normal.

12:10 I guess I need to do some more complete profiling and see how fast I can make either of those.

12:11 rhickey_: Chouser: profiling JS is dangerous, as there is so much platform variance, plus there's a perf war going on (can only help in the long run)

12:11 Chouser: yeah

12:12 "complete" includes each test on at least 4 browsers. bleh

12:12 rhickey_: No point in optimizing for anything other than the top-of-the-line engines - V8, WebKit, as they or similar tech will soon win

12:13 and likely be the most viable platforms for ClojureScript

12:13 Chouser: well there's Chrome, WebKit, and Firefox -- plus you still can't afford to ignore IE

12:14 rhickey_: you want to make sure it works there, sure

12:14 Chouser: Opera's not shabby either, and has a good chunk of the mobile market still

12:15 rhickey_: sorry I meant to say et al before, not to limit to V8/WebKit

12:15 just that _optimizing_ for older JS implementation tech is a waste of time, they'll all be doing what V8/WebKit do soon enough

12:17 Chouser: perhaps you have more confidence in IE than I :-)

12:19 rhickey_: people who use IE get what they deserve

12:20 Chrome exists for a reason

12:25 arohner: lisppaste8: url

12:25 lisppaste8: To use the lisppaste bot, visit http://paste.lisp.org/new/clojure and enter your paste.

12:26 arohner pasted "repl no exception" at http://paste.lisp.org/display/68317

12:26 arohner: if you manage to throw an exception that is caught on that line, the repl does not print a stack trace

12:26 the paste fixes that

12:30 still trying to figure out what I did, but the original error was not helpful

12:30 java.lang.RuntimeException: java.lang.IllegalArgumentException: Too many arguments to struct constructor (NO_SOURCE_FILE:0)

12:32 rhickey_: new print/read support is up, rev 1061 - tire-kickers encouraged

12:35 kotarak: rhickey_: Exception in thread "main" java.lang.IllegalArgumentException: Multiple methods match dispatch value: class clojure.lang.APersistentVector$Seq -> interface java.util.Collection and interface clojure.lang.ISeq, and neither is preferred

12:40 Also (doc var) works, but (print-doc var) says "unable to resolve symbol: var in this context".

12:43 Ok. Forget the last one.

12:54 alec: kotarak: I get that one, too, but only when starting via slime

12:54 (the first one, IllegalArgumentException)

12:55 kotarak: the second one is stupidity of mine. Just ignore...

12:56 I get the first one by starting a new REPL and do a (doc doc).

13:00 arohner: found it. resultset-seq explodes if your query has duplicate column names

13:00 rhickey: what would you like resultset-seq to do in that case?

13:03 Chouser: kotarak: you got that exception by doing something like (seq [1 2 3]) ?

13:04 kotarak: Chouser: I did actually (doc doc), but (seq [1 2 3]) also throws the exception.

13:58 achim_p: mmh, there seems to be something wrong with the latest rev - sequences won't print

13:58 (prefer-method print-method clojure.lang.ISeq java.util.Collection)

13:59 that's probably missing in boot.clj

14:18 qawsx: anyone own a lisp-machine?

14:30 Lau_of_DK: Could somebody point me in the right direction of how I make an optimal Decimal expansion in clojure?

15:19 arohner: does anyone else get frustrated by slime's default behavior with exceptions?

15:20 I don't really understand how to use it, and it just gets in my way

15:33 alec: it's not so nice in Clojure because it only gives you the option to abort or move up the stack trace (which is also pretty useless)

15:33 arohner: is the moving up the stack trace supposed to show you the exception cause?

15:34 because that doesn't seem to work

15:34 alec: it does in other lisps; I don't know if there's enough machinery to support it in Clojure yet

15:36 arohner: I'd also like if there were an option to disable the exception thing popping up in emacs, so it would just print the exception in the repl

15:36 alec: that would be a useful improvement

15:36 rhickey_: acj, sorry about print in 1061 - I'd made half a change I didn't intend to check in

15:37 all should be well now, I've made an enhancement so that prefer-method handles entire trees - it was too tedious to make each specific preference

15:38 so, e.g. (prefer-method print-method clojure.lang.IPersistentCollection java.util.Collection) says prefer all IPersistentCollections to all java.util.Collections

15:48 pointerfun: can anyone see me or i need to register?

15:48 Lau_of_DK: We see you :)

15:49 pointerfun: ok so must just be that the c-people are ignoring me

15:50 Lau_of_DK: :(

15:52 pointerfun: ANYONE KNOW C? if i have a function that takes a string should ibe of the type char or char[]?

15:54 arohner: pointerfun: you know this is a channel for a lisp on the jvm. Not really the place for C questions

15:57 danlarkin: char *

15:57 :-D

15:58 pointerfun: *? that menas pointer no?

15:59 danlarkin: pointerfun: you're in the wrong channel, try #c

17:53 H4nsX: lisppaste8: url

17:53 lisppaste8: To use the lisppaste bot, visit http://paste.lisp.org/new/clojure and enter your paste.

17:55 H4nsX pasted "Proper? Slow?" at http://paste.lisp.org/display/68331

18:08 Chouser: looks fine to me. This is to allow replacing individual methods without replacing the whole object?

18:09 H4nsX: no, it is just some syntactic sugar. i'm still thinking of ways to make working with java apis more pleasant, and one of the things that disturbed me was the syntax for proxy, as it allows for object as well as interface instantiation, where i only need interfaces.

18:10 also, i do not like writing the handlers in-line, thus the apply/partial thing. that way, i'll have very short implements clauses when calling the java framework

18:11 i am not sure whether the apply will incur a (notable) performance penalty. i guess not, but as i am new to clojure, i rather ask :)

18:38 Chouser: you don't need the apply if there are not pre-applied-args

18:41 actually, in neither case.

18:46 lisppaste8: Chouser annotated #68331 with "implement without apply" at http://paste.lisp.org/display/68331#1

18:46 Chouser: then you're always incurring a single extra function call, which is the sort of thing HotSpot is supposed to be able to inline away.

21:10 pjb3: So now that maps are Maps, we have another problem

21:10 clojure maps typically are keyed by keywords

21:10 java Maps are typically keyed by Strings

21:11 so passing {:foo "bar"} into a Java method that calls whatever.get("foo") isn't going to work

21:12 So we could write function to convert all the keyword objects in a map to string

21:12 but I'm wondering if there is a way to avoid that

21:44 danlarkin: proxy is confusing me, anyone have an example to point me towards? there's only two uses in clojure-contrib

21:51 Chouser: danlarkin: there's one on the wiki as well

21:52 Also: http://groups.google.com/group/clojure/browse_thread/thread/3c3a2ef16d2b0467/d9aed18eb65abdff?pli=1

21:55 danlarkin: Ah ha, I see what I was missing... proxy "Expands to code which creates a instance of a proxy class that implements the named class/interface(s)"

21:55 so it doesn't create a class, but an instance of a class

21:55 d'oh

21:56 Chouser: right. Actually, it creates a class behind the scenes the first time, and reuses it next time you call proxy on the same class/interace

21:56 but it returns the instance, not the class.

21:56 if you actually need a class, you have to use gen-class

21:58 danlarkin: mmhmm, so when the code in mmap.clj calls (proxy [InputStream] ...) as a function, that's because InputStream implements runnable, or callable?

21:59 Chouser: that seems unlikely.

21:59 * Chouser takes a look at mmap.clj

22:00 Chouser: hey, I wrote this. hmm...

22:00 ok, calling buffer-stream creates a new InputStream and returns it.

22:00 danlarkin: not knowing java definitely makes it harder to understand how to do some things in clojure :-[

22:01 Chouser: load-file passes that new InputStream to a new instance of InputStreamReader

22:01 heh, someone was just complaining to me today how not knowing lisp makes Clojure docs hard to understand.

22:01 danlarkin: haha

22:01 can't win!

22:03 ok so InputStreamReader takes an instance of InputStream in its constructor. And that's what buffer-stream returns

22:03 (an instance of InputStream)

22:03 Chouser: there you go.

22:05 danlarkin: so (. (buffer-stream (mmap f)) available) would be valid, for instance?

22:23 Chouser: danlarkin: right

22:29 danlarkin: Chouser: great! thanks

Logging service provided by n01se.net