#clojure log - Dec 23 2008

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

0:08 replaca: Q: Is there a way to call clojure functions from Java without :gen-class?

2:40 bOR_: 24th on the mud connector really isn't bad =)

2:41 geas, for example, is also a small mud.

2:41 with fanatical players :)

2:41 and that's 16th

2:41 we should be able to get to sub20's as well

2:46 eek.

2:46 wrong channel. sorry!

3:59 hml: does clojure have opengl bindings?

3:59 on ubuntu linux amd64

4:18 hoeck: hml: you would use the bindings from https://jogl.dev.java.net/

5:25 bOR_: downloaded the cvs version, but when i try to ant it, I run into the following error

5:25 [javac] Compliance level '1.4' is incompatible with target level '1.5'. A compliance level '1.5' or better is required

5:26 the internets are a bit vague about it. they suggest either to change some things in the build.xml (but that just generates a new error), or do something different with eclipse

5:26 which I'm not using.

5:26 any ideas? :)

5:33 hoeck: bOR_: an old java version??

5:34 bOR_: 1.6.0_11

5:34 not sure if that is old, actually.

5:35 ah. that seems to be the latest version

6:14 hoeck: bOR_: and ant -diagnostics points to the right java version??

6:16 bOR_: hah. thanks, will check.

6:16 (also busy with lunch)

6:16 leafw: bOR_: echo $JAVA_HOME ... may be set to somewhere else.

6:17 bOR_: that seems to be the problem indeed.

6:17 java.runtime.version : 1.4.2

6:17 it's pointing to that.

6:19 no explicit java_home set.

6:20 kogu: hi, is there a limit to memoize caching?

6:22 memoize does not seem to be working if argument is a list

6:24 dhaya: kogu: No restrictions as far as I can see. what does the error say?

6:24 kogu: there is no error, but there is no speed improvement

6:25 i have a function which accept a list argument, the list has 216 diffrent possibilites,

6:25 and that function will be called a lot, but with only with those 216 diffrent possibilites

6:25 ofcourse the list is created everytime

6:27 hoeck: kogu: can you paste your code to lisppaste?

6:27 kogu: sure thing

6:28 lisppaste8: kogu pasted "untitled" at http://paste.lisp.org/display/72562

6:28 dhaya: order is important for lists. if you try sets as arguments it might work like you expect.

6:29 kogu: in the code, im creating a new list with 3 items, each of them ranging from 0-5, so total possible combinations is 6*6*6

6:29 from (0 0 0) -> (5 5 5)

6:37 do the refs have to be same?

6:37 dhaya: Well, memoize does work on lists. I tried by adding a (Thread/sleep 2000) in one of the return values in the function. It could be that difference in memoized speed is not noticeable in your case?

6:39 kogu: hmmm, perhaps

6:40 ty for your time

6:40 dhaya: np

6:41 kogu: :)

6:47 hoeck: it seems that eval-roll just isn't expensive enough to be worth memoized

6:49 * hoeck wishes a clojure profiler for chrismas

6:54 kogu: yep, seems that way

6:54 i need to find something else then

6:54 dhaya: anybody has any experience using redshank? does it work with clojure-mode?

6:58 well, i am not even sure if i want that. seems too specific to CL.

7:19 bOR_: nice. got ant compiling the latest version of clojure, after adding a path and a java_home to my .cshrc

7:20 time to simulate :)

7:21 rhickey: bOR_: when you get a chance, could you run your original, repeatably failing code, with svn 1181?

7:22 bOR_: just about to do so.

7:23 rhickey: great - it sure looks like you were just hitting the 32-bit limit

7:23 bOR_: thanks for the help there indeed.

7:23 was there any way I could have avoided hitting that limit?

7:24 Timothy is after it.

7:24 reading his post now.

7:25 rhickey: It shouldn't have been AtomicInteger - all variables for timestamps are longs. It was left over from some old testing of Terracotta, which at the time supported AtomicInteger but not AtomicLong

7:25 bOR_: my atypical use of keeping track of a years.

7:28 nice to have contributed in some way to clojure :).

7:37 Chousuke: rhickey: did you notice Meikel's revised patch for the with-open binding issue?

7:38 rhickey: Chousuke: not yet

8:26 gnuvince: Good morning

8:29 rhickey: hi

8:29 gnuvince: Last day before vacations

8:29 I'm gonna need to find something to do

8:36 I was asking yesterday, is there a Java library to unpack binary data? Similar to Python's struct.unpack?

8:40 bOR_: http://code.google.com/p/javastruct/

8:40 that one?

8:42 gnuvince: Seems like it could work.

8:42 bOR_: no experience with it, just a google.

8:42 but it does have an unpack in it.

8:42 gnuvince: yeah

8:45 bOR_: good luck with it :)

8:53 leafw: rhickey: a few months back you added float/vmean etc for numeric primitives. Where are they now?

8:54 rhickey: leafw: in svn history, replaced by more generic primitive support, areduce/amap

8:55 leafw: rhickey: thanks.

8:58 rhickey: by the way, the clojure book by Stu is freakin' great. If there is currently an explosion of beginners, it's bound to get exacerbated.

9:27 Chouser: leafw: hopefully after reading the book, they'll be well-informed beginners

9:27 rhickey: where is clojurebot? relying on it to broadcast commits here

9:30 RSchulz: ,(println "Who, me worry?")

9:30 Chousuke: rhickey: hiredman said the computer hosting clojurebot had a HD crash

9:30 RSchulz: Ouch.

9:31 I guess we'll find out if he keeps good backups...

9:31 duck1123: didn't he say that was on slicehost?

9:35 RSchulz: I don't know what that is. A Java hosting service?

9:36 duck1123: I know he said clojurebot was running on his webserver, and I think he said he was using slicehost to host webpages.

9:37 I assume they would keep backups,

9:43 RSchulz: If it's running on a commercial hosting service, how did a drive failure bring it down? Surely they have redundancy as well as backups?

9:49 duck1123: I don't understand why, if memory is so cheap, that heap space for jvm application hosting should be so expensive.

9:52 Chouser: SVN 1182: with-open accepts multiple bindings, patch from Meikel Brandmeyer

9:53 nice.

10:04 Chousuke: it accepted them before too; it just never closed them :)

10:05 duck1123: Would that perform better than simply nesting with-open forms?

10:06 or is it just that it looks better?

10:07 Chouser: looking at the patch, it appears to expand to identical (or nearly) code as nested with-open forms.

10:07 lisppaste8: drewr pasted "i/o in a transaction" at http://paste.lisp.org/display/72568

10:08 drewr: This might be a stupid thing to do, but I don't understand this error.

10:09 Chouser: but as Chousuke said, it silently closing only the first.

10:09 drewr: "foo" gets written to the log, so w is obviously the right type when the macro is expanded.

10:09 Chouser: it WAS silently closing only the first. now it's all better.

10:09 drewr: But then (.close <String>) happens?

10:09 Chousuke: drewr: all bindings in with-open have to be closeable

10:09 drewr: use let for normal bindings.

10:09 drewr: Ah, the timestamp is the issue here?

10:09 Chousuke: yeah

10:10 drewr: Did that change with the patch you guys were just talking about?

10:10 Chouser: drewr: heh,yeah.

10:10 * drewr chuckles

10:11 Chouser: I really hadn't thought of it as a breaking change.

10:11 drewr: I updated clojure this morning, made a change to my code, then got the error. :-)

10:11 Wrong order there.

10:11 Chousuke: you're supposed to use with-open only to bind closeable stuff.

10:12 Chouser: and now that's enforced.

10:12 Chousuke: code like that worked just fine with the old version, but it still is a bug

10:13 rhickey: if you were calling with-open in the past with more than one name and init, your program had a bug

10:13 drewr: Good to know.

10:13 rhickey: this is not a breaking change

10:14 this might be a broken code revealing change :)

10:14 bOR_: Chouser - about send vs send-off. the latter is for potentially blocking events.. I guess that anyplace where I alter a ref needs a send-off then.

10:15 drewr: bOR_: How right you are. Learned that the hard way yesterday.

10:15 Chouser: bOR_: nope, altering a ref doesn't block

10:15 hm

10:15 drewr: I wasn't agreeing with the ref part necessarily, but the "potentially blocking" part, yes.

10:16 Chouser: oh, ok.

10:16 bOR_: I got different results when using send vs send-off where each agent was an event + location -> (send (agent nil) (birth 23))

10:16 drewr: I changed some sends to send-offs yesterday with my socket code, and poof, things started working.

10:16 bOR_: vs (send-off ...)

10:16 hmm.

10:16 fun thing about this is that I can change the whole mode of concurrency without touching 90% of my code. It's just the way I invoke it.

10:17 drewr: I still don't understand *why* they behave differently though.

10:17 bOR_: I'll put a note to myself to look into send vs send-off again.

10:17 Chousuke: drewr: that append-file in dosync looks suspicious. aren't transactions supposed to be side-effect free?

10:18 Chouser: drewr's case makes sense to me, because if all of the send-pools threads are busy blocked on IO, another 'send' will just queue up and may never exectue.

10:18 drewr: Chousuke: Good point.. they might be retried.

10:18 Chousuke: though I guess that particular transaction should never get restarted.

10:18 since all it does is read the value once.

10:19 drewr: It might be moot to put it in a transaction anyway since the file is opened, written, and closed in one function.

10:19 Chouser: didn't notice that -- yeah, there's no need for dosync in that log function at all.

10:19 oh!

10:19 gah, sorry.

10:19 drewr: I just didn't know how atomic that was and whether threads could ever block because of it.

10:20 Chouser: Yeah, that was the change I was playing with when the with-open semantics side-tracked me :-)

10:20 I couldn't figure out how adding dosync now messed up my bindings.

10:20 Chouser: ok, it would be fine with no dosync -- do a flying read on *logfile*, and you should be fine.

10:21 gnuvince: ~later tell *Gonzo* http://img116.imageshack.us/img116/6320/1229995264818rm4.png

10:21 oops

10:21 wrong channel, sorry

10:22 Chousuke: you might still have multiple threads calling log simultaneously though

10:22 Chouser: if you wanted to update the value of *logfile* to indicate what had been written, then you might need a dosync.

10:22 Chousuke: but a dosync wouldn't prevent that.

10:22 Chousuke: true

10:22 an agent could be useful

10:24 send all log requests to an agent and let it take care of opening and closing the file.

10:24 drewr: Interesting.

10:27 Chouser: Chousuke: that's perfect. I'd pondered a similar loggin problem before, and using an agent hadn't occured to me.

10:29 bOR_: ah. that's because a single agent just has a queue of tasks that it works through, right?

10:29 nice.

10:34 drewr: Sweet fancy moses, that works like a charm!

10:35 Nothing is blocking now. Ah, glory.

10:36 Chouser: drewr: are you opening the file each time you have something new to log?

10:37 drewr: Chouser: Yep. (defn log [s] ... (send-off (agent *logfile*) append-file s)), where append-file does (with-open ... (.write ...)).

10:38 Those threads could probably pile up on a busy server though.

10:39 But maybe not any worse than logging on a busy server anyways.

10:41 bOR_: is there any way from within the repl to see what version of clojure I am using?

10:41 Chouser: bOR_: no

10:42 drewr: that's not right -- you're creating multiple agents -- they could open the file at the same time, and then ... havoc. :-)

10:42 bOR_: either I by accident used the old version of clojure, or the AtomicLong didn't stop the problem.

10:42 drewr: Chouser: Hm.

10:43 Chouser: drewr: I think you want *logfile* to be an agent instead of a ref

10:43 drewr: (It's not a ref anymore, btw, just a string.)

10:43 It was only a ref while I played with dosync.

10:44 (def *logger* (agent *logfile*)) ... (defn log ... (send-off *logger* ...)) ?

10:45 rhickey: bOR_: what version did you think you were running?

10:46 bOR_: I've the last release and the svg installed.

10:46 svn

10:46 when the bug came back, I wanted to make sure that I am running the svn version

10:46 and not by accident the old version.

10:47 not sure if my run-lisp in emacs caught the new version, or called the old version.

10:47 rhickey: what was the old version?

10:47 bOR_: clojure_20081217.zip

10:48 rhickey: so, wouldn't have had condp - you can check for that at the repl

10:48 bOR_: 'k

10:48 good call

10:49 (doc condp) should work then?

10:49 rhickey: yup

10:49 bOR_: (it doesn't)

10:49 ok.

10:50 so then it's just me making a silly mistake.

10:50 next update in a few hours :)

10:51 drewr: Chouser: That doesn't work.

10:52 Multiple calls to log get hung somehow.

10:53 The new-agent-per-write method works great though. I'm not sure how they would clobber each other in that scenario.

10:53 Things get logged out of order sometimes, but that happens anyway.

10:55 Chouser: drewr: I'm afraid if two things try to log at the same time, one might get lost entirely.

10:55 rhickey: drewr: why don't you send-off an agent to read from a blocking queue?

10:56 drewr: rhickey: Yeah, I could mimic the way I'm interacting with the socket.

10:57 Makes sense too since it's all i/o.

10:57 Chouser: or use 'send' to append to the agent string, and 'send-off' on a timer to flush it do disk.

10:58 rhickey: wait, you just want async, in-order, non-overlapping logging?

10:58 just send-off agt log

10:58 drewr: rhickey: Essentially, yes. I want the stuff to show up in the file at some point and not block anything.

10:58 rhickey: to the same agt

10:59 drewr: That's what Chouser suggested, but I can only get it to work by creating a new agent each write.

10:59 rhickey: why?

10:59 drewr: I'm not sure. :-)

11:00 Option 1: (send-off (agent "/tmp/foo.log") append-file _str)

11:00 Option 2: (def *logger* (agent "/tmp/foo.log")) .. (send-off *logger* append-file _str)

11:01 For me, 1 writes, 2 doesn't.

11:01 rhickey: drewr: does append-file return "/tmp/foo.log"

11:02 drewr: Well, 2 writes, but only the first time.

11:02 rhickey: right, becuae your action trashes your agent state

11:02 must return new state

11:02 (can be same as old)

11:02 drewr: Ahhhh, yes. I had left the string as the return state.

11:02 Much better. :-)

11:05 rhickey: Chouser: svn 1184: ~x not in syntax-quote yields (clojure.core/unquote x)

11:05 clojure.core/unquote has no root binding

11:07 Chouser: rhickey: cool

11:07 now when someone gets around to writing a nice sql-query builder, they can have a tidy syntax for it.

11:09 rhickey: Chouser: did you ever need it for your xml stuff?

11:10 * danlarkin misses clojurebot announcing SVN commits

11:11 rhickey: http://code.google.com/p/clojure/source/list

11:11 Chouser: I haven't yet, no. zip-filter ended up not even needing any macros, much to my surprise.

11:14 duck1123: I wonder if unquote will prove to be useful in the SPARQL DSL that's being discussed.

11:15 Chouser: duck1123: I think it came up there.

11:15 RSchulz: duck1123: What's unquote?

11:16 rhickey: unquote is undefined

11:16 RSchulz: This is the stuff about "quasiquote"

11:16 rhickey: http://code.google.com/p/clojure/source/detail?r=1184

11:17 RSchulz: Sounds dangerously close to a read-time hook...

11:18 (I like it.)

11:18 duck1123: RSchulz: I still don't see why you think clojure keywords would work so badly in sparql. The sparql variable, afaik, is a fairly simple thing. Unless there are some edge cases I don't know about.

11:18 It's been a while since I read the spec

11:19 RSchulz: I think one aspect is that keywords should not be invented dynamically, but rather be defined in Clojure source code.

11:19 Also, I'm not sure what problem they solve for this particular use case.

11:28 Is the intention that the programmer supplies a definition of clojure.core/unquote to control what happens when unquoted forms appear outside of a syntax-quote?

11:30 duck1123: hmm... can you bind a fn to a var in a different namespace inside a let?

11:31 you would only want clojure.core/unquote to mean something inside your macro (or whatever)

11:34 RSchulz: I read the entire "A quasiquote for Clojure?" thread, but I don't think I get the utility of this change. In particular, I don't see how it achieves the results he suggests for his (then impossible) example from SQL and scsh.

11:36 Chouser: if you want your own meaning for ~ outside of ` you can either use binding or a macro.

11:38 the idea is that I could write a sql-building macro now that would be called like: (let [x 55] (select a, b (from tblc) (where (= a ~x))))

11:39 before 1184 there would be no way to make this work.

11:39 even better (where (= (+ a 1) ~(- x 1)))

11:40 ...clearly indicate which expressions should be translated to SQL and sent over, and which should be evaluated as Clojure code locally instead.

11:41 RSchulz: But the burden remains upon the macro writer to do something (eval, in these examples?) things wrapped in (clojure.core/unquote ...)?

11:42 duck1123: right

11:42 Chouser: RSchulz: yes, but now it's possible. previously it generated an error at read time, before the macro writer could do anything with it.

11:42 RSchulz: Right.

11:44 duck1123: It's a runtime error if ~ is used a c.c/unquote is not defined?

11:44 RSchulz: But the Scheme quasiquote that Meikel described would just eval those forms unconditionally in the global environment? Or did it preserve control of their dispensation, too?

11:45 Chouser: duck1123: yes, now it's a runtime error

11:46 it's interesting to me that rhickey bound c.c/unquote at all, allowing the use of 'binding' to define it.

11:46 not bound, but interned I guess.

11:47 RSchulz: It's just a (def unquote) in clojure/core.clj

11:47 (Plus minor changes in LispReader.java)

11:47 Chouser: without the (def unquote) it could still be used by macros, but would generate a compile-time error if used incorrectly

11:48 ...and 'binding' wouldn't be an option.

11:52 RSchulz: So if you wanted to support the Scheme behavior in one of your macros, you could wrap its expansion in (binding clojure.core/unquote #(eval %) ...) ???

11:52 Chouser: I don't know how Scheme behaves.

11:53 Chousuke: RSchulz: #(eval %) == eval :)

11:53 RSchulz: Let's say it does what I suggested / asked above: Evaluates in the global env.

11:53 Chousuke: Right (D'Oh!)

11:54 Chouser: (binding [unquote inc] ~5)

11:55 Chousuke: that's just evil

11:55 RSchulz: Let me guess... 6? ... OK. I cheated and evaluated it...

11:55 Chouser: yes. don't do it.

11:55 RSchulz: Ah, yes. And I see you have to use (binding ...) correctly. So many rules...

11:55 Chousuke: but at least it's explicitly evil

11:56 Chouser: hm, is it? as I said, I'm a bit surprised it's allowed.

11:56 RSchulz: You could use it composing inc and dec to ensure that you got a number. That would be implicitly evil, rigth?

11:56 Chouser: it may be a really pleasant way to write some non-evil functionality, but I'm not sure.

11:57 Chousuke: I mean, it requires teh (binding) form

11:57 Chouser: yeah, but 'binding' is not explicitly evil.

11:57 though I guess it does stand out a bit.

11:57 RSchulz: Consider the shell case (I wrote some stuff like that as an excersize and for its mild utility). In this context, they become like $foo shell variables.

11:57 Chousuke: though I suppose it's easy to hide all that inside a macro.

11:58 RSchulz: (given the (binding [unquote eval] ...) interpretation.

11:59 Chousuke: but clojure already gives more than enough abusable tools. I don't think being able to rebind unquote will make much of a difference.

11:59 rhickey: Chouser: being a var is irrelevant, if not, (let [unquote inc] ~5)

11:59 RSchulz: I'm sure people will find creative uses and abuses of it.

11:59 Chousuke: at least it'll always work as expected inside a ` form

11:59 Chouser: rhickey: ah! of course.

11:59 Chousuke: heh. yes.

12:00 rhickey: actually, not true, if I use clojure.core/unquote

12:00 Chouser: Chousuke: my point is that for a macro, 'binding' probably wouldn't be used at all.

12:00 rhickey: would get Can't let qualified name

12:02 It's certainly not my intention that binding be used, you just get unbound error instead of no var error, and would be harder for macros to get at unquote with namespaces, since no corresponding var

12:03 Chouser: you mean you'd need the whole symbol name since it wouldn't resolve the namespace for you?

12:03 rhickey: user=> clojure.core/bogus

12:03 java.lang.Exception: No such var: clojure.core/bogus (NO_SOURCE_FILE:0)

12:03 user=> clojure.core/unquote

12:03 java.lang.IllegalStateException: Var clojure.core/unquote is unbound. (NO_SOURCE_FILE:0)

12:03 user=> `bogus

12:03 user/bogus

12:03 user=> `unquote

12:03 clojure.core/unquote

12:04 Chousuke: couldn't you for example bind unquote to some custom function so that all forms passed to the macro with unquotes in them would become calls to that function.

12:06 rhickey: Chousuke: I'm interested to see if people could do that usefully, certainly easier than tree-walking for substitution, but either is possible right now

12:09 so, for now I'm not trying to disallow it, nor require it (binding)

12:17 duck1123: would it be possible to make mention of *compile-files* on the compilation page? I had a hard time trying to remember what it was called. (had to go to clj-doc then to the email thread)

12:23 rhickey: duck1123: http://code.google.com/p/clojure/issues/detail?id=9 - patch welcome

12:26 duck1123: does documentation enhancements require a CA? (bringing the form home tonight so I can finally send it in)

12:28 rhickey: duck1123: documentation for *vars* will go into the code

12:34 lisppaste8: Chouser pasted "example of using ~ in macro calls" at http://paste.lisp.org/display/72572

12:35 rhickey: neat

12:37 Chouser: you have to choose your test expressions very carefully to maintain the illusion that 'where' produces valid SQL. :-)

13:01 lisppaste8: RSchulz pasted "Broken use of "unquote"" at http://paste.lisp.org/display/72574

13:01 RSchulz: Howdy. What's wrong with this ^^^

13:02 The "shf" function to which these macros delegate works, as does the "sh" macro.

13:03 lisppaste8: RSchulz annotated #72574 with "Explanation" at http://paste.lisp.org/display/72574#1

13:13 hoeck: RSchulz: there is no unqote function

13:14 RSchulz: I'm running SVN 1184

13:17 hoeck: im on 1160 but i suspect that unquoting implementation has changed

13:17 RSchulz: This is about http://code.google.com/p/clojure/source/detail?r=1184

13:18 hoeck: ah, guess i have to update and look before making more noise

13:21 Chouser: RSchulz: http://localhost/proj/clojure-log/macro.html

13:21 RSchulz: Localhost??

13:21 Chouser: oh, sorry

13:21 RSchulz: hoeck: It started here: http://groups.google.com/group/clojure/browse_thread/thread/6d0c5f7e37909055

13:22 Chouser: RSchulz: http://clojure-log.n01se.net/macro.html

13:22 RSchulz: You can't tell my looking at the (defmacro ...) for shq I pasted? It's self-contained.

13:23 Chouser: RSchulz: did you try macroexpand?

13:23 RSchulz: Yes.

13:23 Shall I annotate my paste with the result?

13:24 lisppaste8: RSchulz annotated #72574 with "Example expansion" at http://paste.lisp.org/display/72574#2

13:24 Chouser: clojure.core/unquote appears within a (quote ...), so it gets passed literally to shf

13:24 RSchulz: What's that phrase? ... Oh, yeah: D'Oh!

13:25 Chouser: :-)

13:25 it's hardly proof, but may be an indication that 'binding' isn't a useful way to use unquote

13:26 bOR_: while we're on the topic of D'Ohs, there must be a hundred simpler ways to get the number of different letters between two strings than the one I made now.

13:26 (count (filter #(= (count (set %)) 1) (seq (zipmap (vec string1) (vec string2)))))

13:26 I sort of grabbed whatever function brought me closer to the end-goal.

13:27 but as I still only know a fraction of the functions that clojure has, I am probably missing something simple.

13:27 RSchulz: Chouser: Perhapsibly. I'll keep poking at it to see if I can come up with an elegant way to achieve that effect.

13:29 Chouser: (count (filter true? (map = string1 string2))) ?

13:30 hm, that's not quite the same

13:31 bOR_: well, at the very least I don't think 'vec' is buying you anything

13:32 bOR_: ah. right.

13:33 thanks :).

13:34 I tried to do something like #(= %1 %2), but that didnt work.

13:35 Chouser: do you really want different answers for ["abb" "abc"] than for ["abc" "abb"] ?

13:35 bOR_: hmm? no.

13:35 Chouser: I get 1 for the first, 2 for the second.

13:36 bOR_: I just want abcdefg aaadefg to report a difference of 2.

13:36 Chouser: oh, ok. then what I posted above should work.

13:36 bOR_: ah. great :). I'll go and learn to understand it.

13:36 Chouser: the problem is zipmap is not commutative

13:38 bOR_: the problem is that I think I know how map works, based on ruby, and then see it do marvellous things in clojure.

13:38 ;)

13:38 Chouser: yeah, clojure's map has this magical multiple-collection feature.

13:41 RSchulz: I don't think it'll ever work to try to get unquote to selectively add a level of evaluation in a syntax-quoted form in one-shot style, since the syntax quoting happens at the outside, and once you eval that outer syntax-quote away, you _then_ must get the unquote to act as eval, but that means everything around it will get eval'ed, too.

13:42 hoeck: RSchulz: thanks for the pointer to the unquote post, the list really too big to keep an eye on all posts

13:42 RSchulz: In other words, I think a tree-traversal with selective treatment of (unquote ...) -ed sub-forms will always be required.

13:42 Has someone concocted "tree-map" yet? Presumably it could be built upon the Zipper in a straightforward manner.

13:42 Chouser: RSchulz: excellent -- that's a useful position. Thanks for reaching it.

13:42 rhickey: :)

13:45 props to Chouser for his help on the docs: http://clojure.org/space/changes - hope everyone's been refreshing and reading

13:47 bOR_: noticed a lot of the changes :). Thanks Chouser!

13:48 Chouser: I'm getting mixed reviews on the no-longer-inline function docs.

13:48 rhickey: Chouser: they simply can't be maintained

13:49 bOR_: we can't get like world of warcraft - hovering descriptions?

13:49 rhickey: When I get time I'll add more prose and examples

13:49 Chouser: bOR_ suggests an option I'd considered.

13:49 bOR_: http://www.wowdb.com/search.aspx?search_text=sword#items

13:49 Chouser: I could probably cobble together some javascript to provide that.

13:50 rhickey: we also might want to find a way to deal with currently un-linkable function names.

13:50 rhickey: Chouser: as long as derived from API page, sure

13:51 as far as unlinkables, would just be mod to that wikigen script I pasted, with some munging convention right?

13:51 Chouser: script tags can be added to the wiki template or something? I wasn't sure.

13:52 yeah -- munging convention of the anchor itself, but I think there may still be problems with the visible text.

13:53 I guess this might be acceptible: [[api#not_EQUAL_|not]]=

13:54 rhickey: some is just wiki problems, for instance http://clojure.org/api#instance? works

13:54 but that link didn't in the wiki markup

13:54 danlarkin: what about the clojure naming scheme itself... not= can be not_EQ___

13:55 or something like that

13:55 swap! == swap_BANG

13:55 rhickey: user=> (clojure.lang.Compiler/munge "not=")

13:55 "not_EQ_"

13:56 user=> (clojure.lang.Compiler/munge "swap!")

13:56 "swap_BANG_"

13:56 user=> (clojure.lang.Compiler/munge "instance?")

13:56 "instance_QMARK_"

13:56 solved problem

13:56 danlarkin: there we go, that's got my vote

13:59 bOR_: rhickey 127000 living: 888 infected: 865

13:59 ok. sim now happily runs past 126600

13:59 rhickey: woo hoo

13:59 bOR_: you nicely spotted the problem from my description

14:00 * rhickey was afraid of it being anything else

14:00 rhickey: :)

14:05 RSchulz: http://clojure.org/other_functions page led me to (partial ...) ... So, how is partial application different from currying? Where might one learn such things? Google's not helping...

14:07 Lau_of_DK: Has anyone made a really easy script for updating clojure+clojure-mode+swank-mode all in one?

14:08 danlarkin: cd clojure-dir && svn up && cd clojure-mode-dir && svn up...

14:08 :-)

14:10 Chouser: RSchulz: my (weak) understanding of currying is such that 'partial' provides explicit currying.

14:15 RSchulz: Chouser: Thanks. Does that suggest that Clojure's (partial ...) is a misnomer? Or that Clojure as a language negates the distinction between the two concepts?

14:17 Chouser: are the concepts distinct?

14:17 RSchulz: Folks in the Haskell world seem to think so.

14:18 Chouser: ok, I think I'm my lack of knowledge about currying is showing.

14:18 RSchulz: http://lambda-the-ultimate.org/node/2266 for example.

14:19 But I doubt I know more than you about this stuff.

14:19 Chouser: with a bit of reading it looks like if you curry a function, you get a new one that can take some args but if it's not complete you get a new function instead of the final result.

14:21 gnuvince: From my understanding, currying is when *all* functions take just one argument and multi-arg functions are actually a function that returns a function that returns a function...

14:22 RSchulz: OK. I guess I can see the distinction there.

14:23 I was thinking, one is about function composition, the other about a kind of "placeholder" function that keeps and supplies a fixed set of arguments. I guess that's consistent.

14:23 Chouser: man. Python resolutely refuses to evaluate my clojure forms.

14:23 gnuvince: How surprising

14:25 Chouser: if my understanding of currying is correct (now), then for curry to work it has to know how many arguments the real function wants, while 'partial' doesn't.

14:25 gnuvince: Currying knows how many arguments a function wants: one.

14:26 take 3 [1,2,3] in Haskell is interpreted as (take 3) [1,2,3] where (take 3) returns a function that takes one argument

14:27 So if a Haskell function takes "4" arguments, it will accept to be passed none, one, two, three or four arguments.

14:27 rhickey: a curried function is one that, when called with fewer than ll of its args, returns a partially applied version of itself, i.e. if + were curried: ((+ 1) 2) == 3

14:28 partial is not currying, in that it doesn't curry a function

14:29 if Clojure had curry, then (((curry +) 1) 2) == 3

14:30 RSchulz: So currying applies to functions per se and in isolation, while partial application applies to functions and (some of) their arguments.

14:30 rhickey: but variadics mess with currying pretty bad

14:30 Chouser: and in that case, 'curry' would have to use knowledge of how many args + wants, in order to know when to return a partial function vs. when to call +

14:30 rhickey: the above presumes binary +

14:30 RSchulz: Do what prolog does, and tack on the arity as an implicit name suffix.

14:30 Chouser: gak

14:30 RSchulz: So there aren't any variadic functions.

14:30 In reality.

14:31 Just a punning scheme.

14:31 Chouser: RSchulz: probably doesn't handle infinite lazy args, though, eh?

14:31 RSchulz: Probably not...

14:32 OK. Well, thanks for the information. Some of the fog has cleared.

14:32 rhickey: svn 1185 - added release-pending-sends

14:33 (just call me clojurebot)

14:33 RSchulz: Has anyone heard from hiredman today?

14:34 duck1123: rhickey: botsnack

14:34 rhickey: crunch

16:14 duck1123: Does anyone know if that *compile-path* bug could also possibly cause classpath issues where a class is compiled, jarred, then moved to a different location?

16:15 I'm getting a class not found error on a class that's in another jar in the same directory as this jar. $CATALINA_BASE/lib

16:21 Lau_of_DK: I just upgraded to the latest REV of Clojure, and upon starting the Repl, I get this error, then the Repl proceeds

16:21 user=> Exception in thread "Call-on-write Stream" java.lang.RuntimeException: java.lang.IllegalArgumentException: No matching method found: sleep for class java.lang.Class

16:21 at clojure.lang.AFn.run(AFn.java:42)

16:21 at java.lang.Thread.run(Thread.java:619)

16:21 Caused by: java.lang.IllegalArgumentException: No matching method found: sleep for class java.lang.Class

16:32 karmazilla: Lau_of_DK: the repl started from clojure.main seems to work

16:32 hoeck: Lau_of_DK: your're using slime??

16:33 Lau_of_DK: Yes sir

16:33 hoeck: had the same error a few days ago, they are calling (.sleep Thread) instead of (Thread/sleep)

16:33 Lau_of_DK: oh ok

16:34 hoeck: don't worry, this happens upon startup, maybe to wait for slow emacsens

16:34 Lau_of_DK: Ok, I'll leave it then

16:34 hoeck: or pull a new swank clojure version

16:34 Lau_of_DK: I just did, its all brand new

16:36 hoeck: aha, well, i fixed it myself to ged rid of this errormessage

16:36 Lau_of_DK: I'll just leave it, it causes no trouble

17:04 lisppaste8: drewr pasted "str -> var" at http://paste.lisp.org/display/72589

17:05 drewr: How can I eliminate having to specify *this-ns* here?

17:06 Lau_of_DK: You're asking how to query the name of the currently used namespace ?

17:06 hiredman: *ns*

17:07 drewr: What if you call str->var from foo.quux?

17:08 Lau_of_DK: Yes, but the one the fn is bound in.

17:09 hiredman: I not 100% (no clojure repl running) but I think namespace stuff is included in the metadata

17:09 I am not

17:10 Lau_of_DK: drewr: Using a macro you can toggle it with ~

17:10 So using ~ it will also be bound in the namespace where first call, w/o it will be dynamic, if I understood that operator correctly

17:10 That is, if you call your macro from some defined function

17:11 hiredman: (def kludge)

17:11 (:namespace (meta #'kludge))

17:11 er

17:11 (:ns (meta #'kludge))

17:12 drewr: Is it really this obscure to call a function from a string?

17:13 hiredman: yes

17:13 drewr: Then why does every other dynamic language I've worked with make it trivial?

17:14 Lau_of_DK: Get Rich on the line, he'll have to explain himself

17:14 danlarkin: drewr: how is it any easier in python

17:15 getattr(module,'function_name')()

17:15 that's basically equivalent to what was pasted

17:15 drewr: danlarkin: I can dispatch getattr without having to know the name of the module or class.

17:17 danlarkin: how do you need to know that here?

17:17 drewr: That's my question. How do I do it otherwise?

17:17 hiredman: danlarkin: he wants the strings to call functions from a specific namespace

17:18 drewr: Why can't find-var search the enclosing ns first?

17:18 danlarkin: (defn getattr [ns, name] (find-var (symbol (format "%s/%s" ns name))))

17:18 oops ignore that comma, was thinking in python

17:18 drewr: danlarkin: How do I know what to pass in for ns?

17:18 Clojure doesn't care. :-)

17:19 (about the comma)

17:19 danlarkin: but in python how do you know what to pass for the first arg of getattr?

17:19 hiredman: I think you two are having a failure to communicate

17:20 drewr: danlarkin: I can pass in self, for example.

17:20 hiredman: it is kind if funny to watch

17:20 danlarkin: probably my fault, I will admit

17:20 drewr: I don't have to care that self is an instance of Foo.

17:21 danlarkin: drewr: so you would like a getter function that works on namespaces and java classes, is that it?

17:21 hiredman: he has a name space "foo" and would like his function to call functions in the namespace "foo" even if it is called in another namespace

17:22 drewr: does that sound correct?

17:22 drewr: hiredman: Yep.

17:23 hiredman: so you could just hard code the namespace part, bacause you hardcode the namespace in the top of the file anyway

17:23 or you could do the kludge thing I mentioned

17:23 danlarkin: ah, and *ns* will be user (for instance) and not org.drewr.foo

17:23 drewr: danlarkin: Yes.

17:24 hiredman: (def kludge) (:ns (meta #'kludge))

17:24 it maybe be more idiomatic these days to use something like (declare ...) for that

17:26 drewr: hiredman: OK, now I see what you mean.

17:26 Of course, now I have to duplicate the name of #'kludge :-)

17:27 hiredman: mazal tov

17:34 Lau_of_DK: hiredman: Are you planning to implement a seen? function in the bot? So I could say seen chouser? And I'd say Chouser was last active 5 hours ago

17:34 Or seen rhickey? and It'd say Rich was last online 2 hours ago, something like that?

17:34 hiredman: that would be nice

17:36 there are many features the bot needs

17:38 danlarkin: hiredman: have you made it a proper github project yet?

17:38 hiredman: no

17:38 lazy lazy man that I am

17:39 danlarkin: clojurebot: hiredman?

17:39 <clojurebot> hiredman has too much free time

17:41 hiredman: the machine that runs clojurebot is in pieces on the floor

17:41 a hard drive died so I need to rebuild it

17:41 Lau_of_DK: rebuild it = ?

17:42 hiredman: got the new drives last night

17:42 well the data drive is fine

17:42 the drive with the OS on it is toast

17:43 danlarkin: ah I was wondering where clojurebot ran from

17:44 Lau_of_DK: hiredman: I think keeping /home on a seperate partition/drive saves alot of headaches when having to 'rebuild', then it only takes ~10 minuz

17:46 hiredman: it runs on a webserver that I thought was in southern washington, but when it died I found it was here in seattle somewhere

17:48 danlarkin: but now is on your floor?

17:48 hiredman: at home :P

17:52 karmazilla: so... clojurebot is built on a solid foundation of wooden planks?

17:54 hiredman: cement covered some kind of padding with carpet on top, I believe

17:55 there are wooden planks around, but not in, on, or constrituting the floor

18:03 Chousuke: can't you use resolve to find a var?

18:05 you could use (resolve (symbol string)) and if the string is unqualified it'll find the var using the normal resolution rules; and same as find-var for qualified symbols

18:09 hiredman: yeah, but he wants his function (call it A) to call functions in the namepsace that A is defined in

18:09 not the namespace A is called from

18:09 well

18:10 wait

18:10 I dunno

18:10 and no repl

18:10 *sigh*

18:12 Chousuke: that happens by default, doesn't it.

18:13 I guess if you want to look up fns by strings you might get the wrong functions :/

18:13 hiredman: yes, but function A actually takes a string and creates a new symbol

18:16 danlarkin: I like the #'kludge method

18:16 it's a kludge for sure, but a pretty good one

18:16 hiredman: I need to start using the word "kludge" more often

18:17 yldop: hmm is jdbc an ORM?

18:17 hiredman: No.

18:17 Lau_of_DK: What is kludge?

18:17 yldop: but it abstracts away the specifics of the database you use...

18:17 hiredman: a navy term from what I hear

18:18 http://en.wikipedia.org/wiki/Kludge

18:18 danlarkin: http://www.ccil.org/jargon/jargon_26.html#TAG1000

18:18 yldop: if i write a wrapper for jdbc like: (defn make-table [name & vars]...), is that an orm?

18:18 hiredman: ugh

18:18 I was just going to say "I am sure it must be in the jargon file"

18:19 Lau_of_DK: Is it clojure-mode which handles highlighting in emacs or are there other modes infererring?

18:19 hiredman: yldop: ORM -> Objec Relational Mapping

18:20 unless you are mapping objects to a relational database, you are just muddying an already muddied term

18:20 yldop: lol

18:21 so is there some fancy term for wrapping sql-queries in a langauge

18:21 RSchulz: LINQ?

18:21 hiredman: database abstraction

18:22 Lau_of_DK: yldop: You and I are working on the same project essentially

18:22 hiredman: "glazing over shit"

18:22 yldop: Lau_of_DK: are you working on the contrib-sql?

18:22 hiredman: not that I would call sql shit mind you

18:23 Lau_of_DK: yldop: No, Kotarak and I started our own ClojureQL on Github, which is Sql queries as higher order functions, seamlessly integrated in your lisp code

18:23 yldop: i made/make my own simple wrapper over derby/jdbc

18:23 * hoeck works on relational data stuff too

18:23 Lau_of_DK: cool, got it posted anywhere public?

18:23 hiredman: Lau_of_DK: url?

18:23 yldop: lau: address?

18:23 Lau_of_DK: http://github.com/Lau-of-DK/clojureql/

18:23 yldop: no mine is very small, not that much to it yet

18:24 maybe i better contribute to yours

18:24 Lau_of_DK: We are also just booting, but we have basic functionality working now, like (sql (query [developer id] table_developers (= id 15)))

18:24 That will query as SELECT (developer, id) FROM table_developers WHERE id = 15

18:24 hiredman: cute

18:25 take that, read table griefers

18:26 RSchulz: Never forget http://xkcd.com/327/

18:26 hoeck: hey, i have (select (project table-developer '(id developer)) (= id 15))

18:29 danlarkin: I bet you can make jdbc handle escaping for you

18:29 you want to parameterize your SQL queries, makes them (much) faster and safer too!

18:30 Lau_of_DK: danlarkin: Can you give an example

18:31 RSchulz: Check out the XKCD!

18:31 Lau_of_DK: Alright already :)

18:31 RSchulz: "Little Bobby Tables" I still laugh every time I read that one.

18:31 Lau_of_DK: RSchulz: HAHAHAA

18:31 hoeck: xkcd rules :)

18:32 Lau_of_DK: Thats the funniest ever, naming your kid after an SQL injection

18:33 danlarkin: Lau_of_DK: well for instance in python I can do cursor.execute("select * from users where name = 'dan'") or cursor.execute("select * from users where name = %s", ('dan',))

18:34 Lau_of_DK: Oh ok, thats what were going for, ultimately to use dynamic statements including math/clojure code

18:34 RSchulz: Is the notion of a Prepared Statement a JDBC thing or an SQL thing?

18:34 danlarkin: the second is a parameterized query, the database can say "Oh, I am going to get a lot of queries where only the %s will change so I can make this faster" versus having to parse the whole statement each time it gets the query

18:35 RSchulz: it's an SQL thing

18:35 RSchulz: that is to say, it's not part of the SQL specification or anything, but it isn't limited to JDBC

18:36 RSchulz: OK. So it's available in any decent SQL access library. I would never consider constructing queries by string synthesis.

18:37 danlarkin: RSchulz: right... not only is it much harder to guard against SQL injections that way but it's also way slower for hot queries

18:37 RSchulz: Win/Win vs. Lose/Lose. Isn't that what's called a "no-brainer?"

18:37 danlarkin: Jeff Atwood (I'm not a huge fan, but when he's right he's right) has a good short explanation, http://www.codinghorror.com/blog/archives/000275.html

18:38 Chousuke: Lau_of_DK: I noticed one of the clojureql functions has a misspelled name. patch to fix: http://www.modeemi.fi/~oranenj/typo-fix.patch

18:38 * Chousuke is a perfectionist.

18:38 Lau_of_DK: Thanks Chousuke

18:38 My kinda guy

18:38 :)

18:38 * danlarkin loves git-format-patch

18:39 Chousuke: I kind of wanted to do my own fork of that thing and have you use git to merge my clone, but that would've been overkill :P

18:39 Lau_of_DK: hehe, yes it would :)

18:39 Chousuke: even though it would've taught me how to do such things with github

18:40 Lau_of_DK: Git has some great tutorials online

18:40 Chousuke: yeah, I've read through them

18:41 * karmazilla thinks the doc-string to the sql macro is rude :(

18:42 Lau_of_DK: hehe

18:42 I hope people can see the fun in all that truth

18:44 RSchulz: You mean the spelling error?

18:44 (OK. Typo.)

18:45 Lau_of_DK: Arent language-wars encouraged anymore?

18:45 karmazilla: RSchulz: you mean the I CAN HASMAP ;p

18:46 RSchulz: Yes. That's the one.

18:46 Lau_of_DK: Hehe

18:48 karmazilla: Lau_of_DK: I thought language war => mock the VB people. Also, DataSource > DriverManager.

18:49 Lau_of_DK: Language wars are usually incredibly boring, but somehow making fun of the python-crowd just never gets old

18:49 danlarkin: I really like python :-/

18:50 Lau_of_DK: The language itself has some pros, but it just draws an unfortunate crowd, hence the IQ joke in the docs

18:50 bOR_: I liked ruby, but I grew out of it, it seems.

18:50 Lau_of_DK: Ive seen sooo many posts on various code-forums like "How can I best design this OOP structure in C++" and the first 3 replies will be something like "Well, you should code it in Python bla bla", and it just gets old real quick

18:51 bOR_: eventually, you head for a lisp-thing :)

18:52 Chousuke: lisp people will just mutter something about OOP and chuckle.

18:52 Lau_of_DK: maybe...

18:52 bOR_: at one point in time, the model that now is also in clojure was in ruby.. and was full of objects.

18:52 dropping all the structure saved soo much time and code.

18:52 Lau_of_DK: I just see a real problem, when the #1 criteria for choosing a given language, is the fact that you cant figure out C and you think PHP is too complicated... But that might be a way too broad generalization :)

18:52 bOR_: the middle way was that I did leave the host class in there.

18:53 but could just as well have done it with a single array being the host object ;).

18:54 I don't think I want to figure out C anymore. Coded in it for my masters, partially ported the model to it during my phd before I lost the motivation to do so.

18:54 hooked onto arc for half a year or something.

18:54 didn't like the absent dictator thing,

18:55 and headed for clojure :).

18:55 it is sort of nice to work parttime by choice, so that you've time to muck around looking at other languages and things.

18:55 danlarkin: I feel bad for the poor programmers pg hooked on to arc with his lofty statements and failure to deliver

18:55 *BURN*

18:55 bOR_: nah.

18:55 everybody has a free will.

18:56 Lau_of_DK: danlarkin: What is really that bad?

18:56 bOR_: at least, I spend some time coding another pet project in arc.

18:56 Lau - this one was the bad thing for me.. lemme drag it up.

18:58 danlarkin: well it's just that if anyone else had "released" what he did they wouldn't have gained much attention at all

18:58 bOR_: can't find it.. don't want to read through the whole thing

18:58 danlarkin: but a lot of people respect and trust him so they tried to improve it

18:58 but then he kinda... gave up?

18:59 bOR_: sort of.. he just comments once every 2 months.

18:59 and is just putting almost no effort into it.

18:59 people try to improve on the language, but get no feedback.

18:59 Lau_of_DK: Sounds sad

18:59 What he planning to deliver a boat load of libs himself ?

18:59 bOR_: that's the post I'm trying to recover.

19:00 he's planning to have a decent language in about 10 years or so.

19:00 so he's not in a hurry.

19:00 danlarkin: his "100 year language" thing is what gets me

19:00 to me it's just an excuse to shrug off the difficult thing about building a new language

19:01 Chousuke: a language can and should be an evolving entity

19:02 Lau_of_DK: Im kinda glad I jumped from SBCL to Clojure :)

19:02 (taking the good advice of a Python guru)

19:02 bOR_: clojure pops up on a lot of forums as an interesting thing.

19:02 Chousuke: and I think gradual evolution is especially easy if you have something simple and flexible like a lisp. the only problem setting the initial direction.

19:02 danlarkin: Lau_of_DK: who?

19:03 Lau_of_DK: Davy Wybiral

19:03 Davvy

19:03 Quite a character, he actually wrote a Lisp wrapper for Python. Slow, but quite nice

19:04 Chousuke: because once you have momentum changes are going to take time; that's why it's pretty difficult to affect common lisp or scheme anymore

19:04 Lau_of_DK: Chousuke: Lisp is ever so simple in its construct, the deal-breaker is the libraries I think

19:05 Chousuke: in the short term, yeah

19:05 danlarkin: I think having a strong leader does a lot for a language, see Python/Ruby/C# versus Scheme/CL/C++

19:06 Chousuke: right.

19:07 danlarkin: and of course Rich

19:07 clojure, I mean

19:07 Lau_of_DK: netsplit?

19:08 karmazilla: only you

19:08 Lau_of_DK: bad enough

19:22 has try/catch been changed in the latest rev?

19:23 Chousuke: the SVN log doesn't say anything about that. so no?

19:23 Lau_of_DK: but my code broke

19:24 Chousuke: using with-open?

19:24 Lau_of_DK: yes

19:24 Chousuke: some broken code may have been further broken by a certain with-open change.

19:24 namely, it now works with multiple bindings.

19:25 earlier it accepted them, but didn't work right :/

19:25 Lau_of_DK: hmm

19:25 How do I need to rework my code?

19:25 Chousuke: well, my crystal ball is an old model, so it would help if you'd paste the code that breaks :)

19:28 Lau_of_DK: hehe, so nasty

19:29 (try

19:29 (with-open [con# (DriverManager/getConnection jdbc-url#

19:29 ~(:username @*connection*)

19:29 ~(:password @*connection*))]

19:29 ~@body

19:29 (catch SQLException exceptionSql#

19:29 (println exceptionSql#)))))))

19:29 Chousuke: use lisppaste, please

19:29 but hm

19:30 that looks like it should work

19:33 Lau_of_DK: I'd say so

19:33 But it crashes with "catch is uknown bla bla"

19:34 Chousuke: is that from clojureql?

19:34 Lau_of_DK: yes

19:35 Chousuke: is it in the github version?

19:36 Lau_of_DK: Im not sure

19:36 Chousuke: can't find it

19:36 Lau_of_DK: And Im not in a position to push atm, so we can have a look tomorrow, Ive got to get some shuteye

19:36 Then its a local thing, sorry

19:37 I got, syntax error on my part, appologies for the noise

21:29 joha1: what is the standard clojure way of doing a switch-case structure, something like (case ...) in CL?

21:32 Chouser: there's cond, condp (brand new), and clojure.contrib.fcase

21:34 joha1: thanks

21:39 * drewr reads about c.contrib.template

22:48 hiredman: so, if I want to deny access to a function, for example 'println', I can (binding [println nil] dowhatever) but what about for "primitives" or whatever like 'def'?

22:50 gnuvince_: (defmacro def [])

22:50 wait, that doesn't work

22:53 hiredman: def is not a macro

22:53 def is magic

22:53 :(

22:53 Chouser: yes

22:53 you're not going to get around it like that.

22:53 hiredman: *sigh*

22:54 Chouser: you do 'read' and then 'eval', right?

22:54 hiredman: any suggestions?

22:54 yes

22:54 well, this is entirely theoretical :P

22:54 Chouser: you could search the tree returned by 'read' and just disallow it if any list starts with a symbols whose name starts with 'def'

22:55 gnuvince_: hiredman: what are you working on? an eval IRC bot?

22:55 hiredman: hmm

22:55 yeah, for clojurebot

22:55 it has it

22:56 but it should be better

22:56 and someone was able to break it using try/catch so I need to disallow those

22:56 gnuvince_: I guess you'll have to check all the cars (sorry, firsts) and reject the expression if there is a special form, macro or function that you don't want to allow

22:58 hiredman: I disallowed try/catch by just filtering out strings that contained them, but he started trying stuff with (symbol (str "ca" "tch")) don't know if that would work though

22:58 of course I also blocked input from him by nick :P

22:58 but he TRIED it

23:01 if I disallow eval that doesn't seem to work

23:04 gnuvince_: Is it just me or is tree-seq really awkward to use?

23:12 danlarkin: hiredman: I'm not sure it's possible, you'd have to hook in at the compiler level or something...

23:13 because you can't just check firsts

23:14 Chouser: danlarkin: oh?

23:16 danlarkin: right? because of stuff like (symbol (str "ca" "tch"))?

23:16 and apply, map

23:26 Chouser: hm, that's a good point.

23:26 but macros and special forms can't be passed to apply or map

23:27 and after you've built a symbol named 'catch' what will you do with it? you'd have to define it as a macro or pass it through eval, I think.

23:27 danlarkin: but #(def % "foo") can be passed to map

23:27 Chouser: defmacro and eval would both have to go first

23:28 'def' is the first of a list there.

23:28 hiredman: whoops

23:28 sorry, stopped paying attentio

23:28 n

23:28 danlarkin: I don't think #() forms are iterable

23:28 er ISeq I mean

23:30 Chouser: it expands at read time to (fn [...] (def ...))

23:30 danlarkin: although '#(def % "foo") returns (fn* [p1__287] (def p1__287 "foo"))

23:30 hiredman: (-> "#(def % foo)" java.io.StringReader. java.io.PushbackReader. read)

23:30 danlarkin: so perhaps you can check firsts

23:30 hiredman: ^- very instructive

23:31 I can check the data structure returned by read

23:36 arbscht_: Chouser: do you mind if I publish your edition of snake.clj in place of the old one?

23:37 Chouser: arbscht_: go right ahead. I'm not sure it's better.

23:38 I replaced your nice readable :x and :y map with a vector -- sometimes that makes programs smaller, but it didn't really here

23:38 rather less readable with a vector

23:38 arbscht_: dropped by 1 line, by my count :)

23:39 Chouser: heh

23:41 hiredman: danlarkin: I can run tree-seq on the output of read before I send it to eval

23:46 Chouser: I bet this has been researched for other lisps

23:46 hiredman: of course it has

23:47 man, I wish just turning on java's sandbox stuff made it all ok

23:47 but people can still pee in the sandbox

Logging service provided by n01se.net