#clojure log - Jul 04 2008

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

0:16 arbscht: I have to chime in as well, I think you're on to a winner, rhickey_ :)

0:16 I've had a really fun week hacking in clojure

0:17 rhickey_: great!

1:08 abrooks: When I have the form: (apply and '(true false true))

1:09 It evaluates to the expanded macro form: (clojure/let [and__160 false] (if and__160 (clojure/and true false) and__160))

1:09 Not the expected value: false

1:09 Of course I can get this by evaling the resultant form: (eval (apply and '(true false true)))

1:09 But that's not what I was expecting. Are my expectations wrong? Is something broken?

1:09 slava: well, apply is generally not supported for macros

1:10 clojure should raise an error there

1:11 abrooks: It seems reasonable to want to apply to (and ) as an operator. Should apply really be a macro so it can take macros?

1:11 slava: the problem with passing macros to apply is that you'd have to invoke the evaluator at runtime

1:11 if you have a list, and you want to test if all elements are true, you should use another function

1:12 instead of applying and

1:13 abrooks: Hm. True.

1:14 arohner: (every? identity '(true true true))

1:16 abrooks: Or, perhaps more clear expression: (every? true? '(true true true))

1:16 slava, arohner: Thanks for your help. I really wasn't thinking there.

1:17 arohner: I do like true? better. I didn't know it was there

1:17 abrooks: It's more computation I think but I am given to favor the human over the CPU. :)

1:18 slava: i would think the compiler would produce equivalent code for both

1:18 arohner: hah. There aren't too many premature optimizers in a lisp forum :-)

1:18 abrooks: :-D

1:18 * slava is a premature optimizer

1:18 slava: but i develop compilers, so that i don't have to prematurely optimize the application itself ;)

1:19 0.5% improvements to the code generator add up over time

1:19 arohner: definitely

1:19 abrooks: Yep. And you're not making your code harder to maintain to do so.

1:20 slava: well, you want to keep the compiler maintainable too :)

1:20 (see: gcc)

1:20 abrooks: True enough.

1:20 slava: i've found the best way to do that is to structure it into as many passes as possible, keeping each pass simple and independently testable

1:21 abrooks: Ian Lance Taylor presented a plan for gcc to be written in C++.

1:21 slava: i'm hoping something based on llvm replaces gcc eventually

1:21 i've found so many bugs in gcc :(

1:22 abrooks: slava: Shark is based on LLVM IIRC.

1:22 slava: the profiler?

1:22 there's something called clang, but its not ready yet

1:22 abrooks: Shark the icedtea JIT.

1:22 slava: ah

1:23 abrooks: Yeah, here it is: http://gbenson.net/?p=83

1:23 arohner: so shark is based on LLVM, but it outputs JVM bytecode?

1:23 slava: it consumes JVM bytecode

1:23 and outputs x86/ppc/whatever

1:23 arohner: oh, interesting

1:23 slava: llvm is not really a vm in any sense of the word

1:23 abrooks: It's JITing ... yeah, bytecode to native.

1:24 slava: its a compiler where the input is an AST for a low level language that you construct directly using the llvm api

1:24 so its sort of like generating C then compiling with gcc, except its simpler/saner than C, and there's no text printing/parsing involved

1:24 arohner: cool

1:25 it's always irritated me that Java is not self hosting

1:25 and now my new favorite lisp (clojure) basically never will be self hosting

1:25 slava: javac is self hosting

1:26 arohner: sun's JVM is not

1:27 IIRC, there's a lot more code in the JVM than javac

1:28 even excluding libraries

1:28 slava: i understand that

8:24 cgrand: Hi rhickey. I noticed that (drop 0 x) returns x and not (seq x)

8:24 rhickey: I'll look at that

8:26 cgrand: thanks, drop-while behaves similarly (when the predicate is false on the first element)

8:30 rhickey: cgrand: fixed - thanks for the report

8:31 cgrand: thanks, yw

11:18 icey: cgrand: sorry for giving you crap on reddit :D

11:24 cgrand: icey: I promise I'll never check reddit just before going to bed again

11:25 icey: cgrand: if it's worth anything at all, it gave me a good laugh - i recognized your name from either here... or news.yc or google groups or something ;)

11:27 cgrand: and my answer to the original question is IBM RPG :-)

11:31 icey: so, for an actual Clojure question; have any of you guys deployed a Clojure app out into the wild yet?

11:31 as in, a production release

11:35 Chouser: I haven't really, although the clojure-log.n01se.net is produced by a clojure app.

11:37 icey: it's a terribly cool language; i'd love to use it for some stuff, but most of the code i write anymore ends up in a production system and i'd rather wait until a few people have experienced some loads with it ;)

11:38 Chouser: are you using Java currently?

11:58 icey: if you're already using Java, you could introduce a little clojure at the edges and see how it does for you.

11:58 icey: unfortunately, i'm not a java guy at all

11:59 Chouser: yeah, me either.

11:59 icey: but you're right, and that's what i'll end up doing - I'll find some tiny throwaway project that needs to get written and use Clojure for it

12:01 we're in the process of moving away from the microsoft stack at my office right now; once we get settled into apache land, it will be easier

12:01 Chouser: interesting.

12:02 we're so deeply into C++ at work, that I don't see how to bring in any significant Clojure there.

12:05 icey: Ahh that's too bad... I'm very fortunate - our main application is written in vb.net 1.1, which I took over last year. It's half a million lines of code, 90% of which is boilerplate. So we're getting ready to move it one chunk at a time to a newer framework that has better abstractions.

12:06 I would have loved to use a Lisp, but I would far prefer Clojure to SBCL for example... The ability to use the Java stack for serving and the java toolchain is too attractive to pass up

12:06 instead, we'll probably end up using seaside or something in python for now

13:25 rhickey: Anyone going to try ICFP in Clojure? Unfortunately, it's not yet a supported language, but they say they are open to others. I'll be traveling so can't participate: http://www.icfpcontest.org/rules.html

13:30 Chouser: hm, I might be able to join a team. anyone else?

16:25 kotarak: Hmm.. Will metadata be extended to arbitrary types?

16:25 rhickey: not likely

16:27 I don't 'own' the other types, so I can't add it; don't want to wrap everything; and associating metadata with identity maps has different semantics

16:27 kotarak: I'm looking for a way to attach some tag (for multimethod invokation) to an arbitrary value. But I don't see a way to do it. Metadata would work perfectly.

16:29 Maybe that's a sign, that I should do it differently in clojure.

16:56 Chouser: Would it be a bad idea to take strings produced by prn-str and save them into a relational database?

16:56 rhickey: what's in the strings?

16:56 Chouser: maps. hashes of strings and vectors

16:57 rhickey: opaque to the db?

16:57 Chouser: stuff that, if I were to normalize my database, would require a half-dozen tables.

16:57 yeah, it'd have to be opaque -- no useful way to query for things I didn't pull out into their own columns ahead of time.

16:57 kotarak: When there are fn's somewhere in the structures there is a problem, I presume.

16:58 Chouser: yeah, I don't need fn's in there.

16:58 rhickey: I think it's the normal db story - it's technically wrong schema-wise, but you can pull anything out into a column or related table if you needed

16:59 I really like Clojure read/print format as an interop/wire format

16:59 jcrites: Chouser: practically speaking that kind of stuff is useful to do.... you might want to skip the DB though

16:59 just go for something like a BDB

16:59 Chouser: I'm still just flailing with disk-storage. I don't like having to unpack all my nice data structures into piles of loosly-connected tables, but I also don't like realtional/object models.

16:59 jcrites: you'd get a lot better performance from a key-value pair oriented DB

17:00 Chouser: check out BerkeleyDB

17:00 Chouser: jcrites: yeah, good point.

17:01 when reading these kinds of data structures, is it more efficient to do just (read) than something that also evals, like load-file?

17:01 rhickey: you should only need read

17:01 jcrites: you could also explore an online solution.... like Google Bigtable or Amazon SDB

17:01 rhickey: an advantage of read/print vs json eval

17:02 Chouser: so just read would be faster?

17:03 rhickey: definitely - read is the first phase of load, but then there's a whole analysis phase, then eval

17:03 Chouser: I've dabbled with using a triple-db (RDF) as another way to avoid both object/relational and pure relational tables.

17:03 rhickey: ok, thanks. I think when I've done this before I did (load-file).

17:04 hm.. (read) would be safe too, from a tainted-data point of view. No Java calls or re-defining root vars.

17:05 rhickey: that's what I meant re: json eval

17:05 Chouser: jcrites: would feel a little silly to have transactions in memory but not in my database. ;-)

17:06 rhickey: read yields data and you're done

17:06 jcrites: hmmm, how will you need them?

17:06 BDBs do support transactions luckily :)

17:06 well

17:06 not exactly transactions. I forget exactly what

17:07 Chouser: maybe having STM means I wouldn't need transactions in the db.

17:11 rhickey: in ants.clj at the top of render you "rip through" the board to copy the state into a vector. You'd still get correct results if your transaction encompassed the whole of render instead, right?

17:12 But I'm guessing other threads would block or have more restarts if you did it that way?

17:13 jcrites: hard to say ... have to know what your usage pattern is like

17:14 rhickey: Chouser: it's reading, so it won't impede anyone else. But _it_ would have more retries itself, as it would have a longer isolation window

17:14 Chouser: could it starve complete? no, because you have "barging" or something, right?

17:15 rhickey: It's a reader, so it doesn't lock, so it doesn't barge...

17:16 the way longer running readers get covered is, each time they have to retry, they increase the history window for the ref for which the transaction aborted...

17:16 eventually history windows will adapt to become long enough for he read patterns...

17:17 that's the idea anyway - that's the multiversion part of MVCC

17:17 each ref can keep multiple old values to satisfy readers

17:18 Chouser: man. ok.

17:18 rhickey: it's pretty neat

17:19 but no reason to stress it when you know what's going on - get in, get out

17:20 Chouser: sure, just trying to understand.

17:20 * Chouser continues to chalk it up to "magic" for now.

17:20 rhickey: :)

17:38 Chouser: A ref has a linked list of values it's had, each timestamped?

17:38 rhickey: sort of

17:39 just as many values as dynamically called for, normally only one

17:40 Chouser: ok. gotta run. thanks!

17:41 rhickey: sure

Logging service provided by n01se.net