#clojure log - Jan 10 2009

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

0:12 durka: what do y'all use in clojure for http client things?

0:13 XMLHTTPRequest style

0:16 danlarkin: whatever framework you're using (assuming it is one) should deal with it I guess?

0:16 durka: well that's what i'm asking, like in CL you might use Drakma or something

0:18 Chouser: duck-streams will open a URL for you.

0:21 (line-seq (ds/reader "http://n01se.net/"))

0:22 durka: hmm, ok

0:22 Chouser: you need more control?

0:24 durka: maybe

0:24 Chouser: (line-seq (java.io.BufferedReader. (java.io.InputStreamReader. (.openStream (java.net.URL. "http://n01se.net/")))))

0:24 durka: i might need to issue specific HEAD/GET/POST requests

0:24 mmcgrana: you might want to check out Commons HttpClient

0:24 durka: oh, i was wondering if you were here

0:25 is clj-http-client ready for a user?

0:25 danlarkin: durka: ohh, you mean from the client side

0:25 durka: yeah

0:25 danlarkin: sorry :)

0:25 mmcgrana: yeah, feel free to give it a shot. no promises, but i'll try to fix any problems you run into.

0:28 durka: i'll see what happens

0:30 mmcgrana: OK, thanks for trying it out. I'm actually pushing a huge changeset (truly epic) to clj-garden right now, but it doesn't touch clj-http-client. BTW there is some example usage of it in the gitcred sub-project.

0:53 durka: bah

0:53 where the heck is the OS X classpath set

0:53 mmcgrana: hmm i set it at the command line using a shell script

0:54 are you having classpath problems?

0:56 durka: i'm just trying to find out where it comes from

0:57 i'll just append to it in .zshrc

0:58 mmcgrana: fwiw, try $ cat /System/Library/Java/JavaConfig.plist

1:00 durka: i did find that

1:00 mmcgrana: o ok

1:00 durka: but $CLASSPATH in the shell seems to not have the complete DefaultClasspath

1:00 hmm, clojure.core/use is converting - to _ and therefore not finding clj-http-client.jar

1:01 mmcgrana: you want to (use 'clj-http-client.core), not the jar itself

1:01 or (ns your.ns (:use clj-http-client.core))

1:01 danlarkin: durka: yes, clojure converts - and _ regarding namespaces

1:02 durka: but then what would i put on the classpath

1:02 => (use 'clj-http-client.core)

1:02 java.io.FileNotFoundException: Could not locate clj_http_client/core__init.class or clj_http_client/core.clj on classpath: (repl-1:12)

1:02 mmcgrana: o i c sorry this is my bad

1:03 one sec

1:04 durka: add-classpath'ing the jar fixes it

1:04 except i don't have Commons HttpClient...

1:05 mmcgrana: hmm yeah so i don't the lib is broken, i saw the same error you did because i also didn't have it in my classpath, but now its working for me, so i can help you get it working over there.

1:06 the httpclient jar i'm using http://www.java2s.com/Code/Jar/Apache-Common/commons-httpclient-3.1.jar.htm

1:07 also, you'll need the commons io 1.4 jar http://commons.apache.org/downloads/download_io.cgi

1:07 this will be a good chance for me to write a proper readme for the project. thanks for bearing with me durka

1:07 durka: no problem

1:07 you aren't using the 4.0 beta?

1:08 mmcgrana: no, its actually a totally different library i think - pretty much a complete rewrite. i'm not sure that its fully stable yet, 3.1 seemed fine.

1:09 i'll keep my eye on it though.

1:11 now that i look at again, 4.0 seems more mature than i previously thought. I'll have to look at that again when I get the chance.

1:12 um that didn't make much sense: basically I'll look into 4.0 at some point in the future

1:13 durka: also need the commons logging jar

1:14 http://commons.apache.org/downloads/download_logging.cgi

1:14 mmcgrana: ok thanks

1:15 yeah I don't like that a http library depends on a logging library and then goes off creating logs behind your back when you initialize clients, if thats fixed in the supposedly more modular 4.0 it alone would be a good reason to switched

1:15 * switch

1:17 durka: also commons codec

1:17 works!

1:17 mmcgrana: win!

1:17 durka: and with that, i believe it's past my bedtime

1:18 mmcgrana: well i'm glad you got that working. let me know if you have end up with any problems or suggestions. i'll try to get this readme out by tomorrow.

1:20 durka: so for the readme, what i needed to get it working were the commons io, logging, codec and httpclient jars (I put them in the java ext dir) and clj-http-client.jar (explicitly, not the directory containing it) on the classpath

1:21 mmcgrana: ok

3:57 danlei: join emacs

4:20 baggins: Hi.

4:26 Can I use clojure if I'm after code that is compiled optimally for speed?

4:27 the whole every-variable-is-final attitude seems to go against that as a priority.

5:02 rottcodd: baggins: there is overhead, but you can optimize bottlenecks to match the speed of java

5:02 blbrown: can I pass clojure sequences where a java array is required. e.g. an array of strings [ "a", "b" ]...

5:05 into-array I guess

5:08 baggins: i guess there's the question: does the compiler really optimize thanks to this?

5:10 blbrown: baggins, I just joined, but if you look at scala (another jvm language), in some cases it has better speed when matched up against pure java. Remember that some of the core java libraries are poorly designed. Some maybe clojure can end up with faster bytecode?

5:24 rottcodd: as Michael Abrash says, "the best optimizer is between your ears"

5:24 Raynes: Truefax

5:27 blbrown: is there a 'return', early exit function in clojure

5:28 danlarkin: "you're doing it wrong" if you need one

5:28 blbrown: cl has one, hehe

6:01 baggins: wait a minute�. i have to "do it [anything/everything] right" in clojure? could be in trouble

6:10 blbrown: baggins, hehe, that is what I was thinking. I have been doing it wrong in common lisp for 5 years too

6:17 baggins: heh

6:18 blbrown: baggins, it isn't a crime, I don't worry about it

6:18 baggins: it's weird though really. computers are state machines. surely an imperitive style suits them more.

6:19 when i write CL i write more in an imperetive style than i probably should i think.

6:20 * baggins spots the "delay" macro and goes s "oo"

6:21 kotarak: "stolen" from Scheme ;)

7:48 baggins: ok now i've been wrestling with this for like half an hour

7:48 how do i specify in gen-class' :methods vector that a method is of void return type

7:49 kotarak: Void/TYPE, IIRC.

7:49 baggins: uy

7:49 kotarak: Like Integer/TYPE for ints.

7:49 baggins: Hm. well I don't think that works either

7:49 i'm getting a weird error

7:49 kotarak: But I may be wrong. So you have to test.

7:49 baggins: java.lang.RuntimeException: java.lang.RuntimeException: java.lang.RuntimeException: java.lang.RuntimeException: java.lang.RuntimeException: java.lang.RuntimeException: java.lang.RuntimeException: java.lang.RuntimeException: java.lang.IllegalArgumentException: No matching field found: getSimpleName for class clojure.lang.Symbol (ClojureAppletTest2.clj:3)

7:50 kotarak: At least for integer it works.

7:50 Maybe I remember something wrong for the Void stuff...

7:50 1:1 user=> Integer/TYPE

7:50 int

7:51 baggins: hm

7:51 let me show you what i have

7:51 kotarak: 1:3 user=> java.lang.Void/TYPE

7:51 void

7:51 You have to qualify Void.

7:51 lisppaste8: url

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

7:52 baggins: still the same

7:52 kotarak: Paste your code to lisppaste. Then we can have a look.

7:54 lisppaste8: baggins pasted "when I add :methods, this fails." at http://paste.lisp.org/display/73383

7:54 baggins: some of that code i wrote ages ago

7:55 i realisei can do str function instead of concat now

7:55 kotarak: (. obj (method)) can be written as (.method obj) now.

7:55 baggins: ok

7:56 kotarak: The first is still ok, but the later is more convenient.

7:56 baggins: but anyway. the problem is that :methods key

7:56 kotarak: Eg. for (-> obj .getThing modifyIt .doStuff)

7:57 baggins: ok. i realise it could be written a lot more prettily

7:58 kotarak: No Problem. Just a remark...

7:58 Chousuke: baggins: also (. Color BLUE) = Color/BLUE

7:58 / is used to access static fields

8:00 baggins: but do you know why it fails in that cascading way when i try to put that method in there?

8:02 lisppaste8: kotarak annotated #73383 with "works for me :(" at http://paste.lisp.org/display/73383#1

8:03 Chousuke: I don't get any errors either.

8:04 kotarak: Ah. Ok.

8:04 Now I have the failure.

8:11 baggins: how are you compiling it?

8:11 i have it saved in a file ClojureAppletTest2.clj

8:11 and i am running

8:11 kotarak: (compile 'foo.ClojureAppletTest2)

8:11 baggins: cho "(compile 'ClojureAppletTest2)" | java -cp clojure.jar:`pwd` clojure.lang.Repl

8:11 echo that's supposed to say

8:12 kotarak: I just type it at the repl with src and classes in the Classpath and the file in src/foo.

8:14 baggins: hm

8:14 are you on the latest version?

8:15 kotarak: Not totally, but sufficiently bleeding edge. 1195.

8:15 baggins: oh hm.

8:16 the repository has changed?

8:16 kotarak: Clojure is now hosted on google code.

8:16 http://code.google.com/p/clojure

8:17 baggins: no wonder

8:18 maybe he should leave a note in the old repository with instructions for the new one

8:18 and remove all the code

8:19 * baggins cloning new repo

8:20 baggins: hm. could take a while. svn is slow.

8:20 kotarak: There are also mercurial and git mirrors...

8:20 Much faster.

8:22 baggins: http://github.com/kevinoneill/clojure/tree/master this one? looks about it

8:23 kotarak: Don't know. I use Shawn Hoover's mercurial mirror on bitbucket.

8:23 Chousuke: baggins: that's the git one, yes

8:24 it's not auto-updated though :/

8:24 so sometimes it lags behind a bit

8:24 baggins: oh

8:24 well

8:24 * baggins continues checkout out svn as well

8:25 baggins: greedy

8:25 Chousuke: I did a git svn clone :)

8:25 took about 30 minutes but that was one-time pain.

8:27 baggins: yeah that's what i'm doing

8:28 kotarak: Hmmm... The argument vector in the :methods section seems to be the problem.... At least that's the last thing printed, before the exception is thrown, when I add a (prn c) (flush) to escape-class-name...

8:29 But I can't really believe it...

8:32 baggins: yeah. when i remove the line it ... works-ish... or it fails in a different place

8:34 kotarak: btw, you can just specify void for void.

8:35 Hmmm... An empty argument vector also solves the problem.

8:44 Hmm.. it seems for method arg vector we get a Symbol instead of a Class.....

8:44 java.lang.Class

8:44 java.lang.Class

8:44 java.lang.Class

8:44 clojure.lang.Symbol

8:48 Adding this line in escape-class-name fixes the problem.

8:48 (let [c (if (class? c) c (Class/forName (name c)))]

8:49 Also I still believe I miss something.

8:49 Although...

9:06 rhickey: in line 137 in gen-class.clj the argument vector of a :methods spec is fed to overload-name with converting the symbols to classes via the-class. Is this a bug?

9:06 without converting....

9:12 * baggins wonders

9:22 Fib: Hm, svn relocate is telling me that the uuid for the new repo doesn't match - should I just do a clean checkout?

9:33 knapr: what profiler works best for clojure?

9:34 kotarak: baggins: I drilled it down to this:

9:34 (ns foo.Bar

9:34 (:gen-class

9:34 :methods [[toString [Object] String]]))

9:34 Compiling this fails.

9:40 baggins: hm

9:41 knapr: what profiler works best for clojure?

9:41 kotarak: knapr: any Java profiler will do, rhickey uses eg. YourKit.

9:43 rhickey: kotarak: :methods is only for adding methods, your class will have toString already because it is in Object

9:44 kotarak: rhickey: Ok.

9:46 baggins: java.applet.Applet already has a paint method from java.awt.Container. So just drop the :method clause.

9:48 baggins: oh

9:49 i added it because of another problem

9:49 but ok

9:49 :)

9:52 now i get a filenotfound exception

9:54 kotarak: try adding a baggins.ClojureAppletTest and put the file under src/baggins/ClojureAppletTest and make sure the classes directory exists and both, src and classes, are in the classpath.

9:55 I mean (ns baggins.ClojureAppletTest ...) instead of (ns ClojureAppletTest ...)

9:56 baggins: in the clojure src directories?

9:57 kotarak: No. In your project directory. You shouldn't work in Clojure's source tree.

9:58 The file containing the namespace has to follow certain naming conventions.

9:58 foo.bar-baz => foo/bar_baz.clj

9:58 baggins: well i was just trying to do it in the pwd

9:58 and i put . in the classpath

9:59 kotarak: It's good to put your sources in a src directory and create a classes directory, which holds the compiled class files.

9:59 baggins: but i just trashed my .bashrc file accidentally >_M

9:59 >_<

9:59 rhickey: kotarak: looks like a bug (overload-name + :methods), could you please create an issue?

9:59 kotarak: rhickey: ok

9:59 will do

10:00 baggins: then you have to do (binding [*compile-path* "."] (compile ...)) (out of my memory..)

10:00 baggins: ah. binding

10:00 i was just trying let

10:12 Chousuke: I wonder what the exact rules for symbol/keyword names are :/

10:14 StartsWithK: (symbol "with spaces and . and / ")

10:15 Chousuke: StartsWithK: that's the problem. 'symbol does no validation

10:15 you can create illegal symbols with it

10:16 StartsWithK: what do you mean by validate?

10:16 (symbol? (symbol "with spaces and . and / "))

10:16 returns true

10:17 kotarak: but "with spaces and . and /" is probably not a valid symbol.

10:18 Chousuke: it's unreadable

10:19 I thought about writing a validator since that's an open issue but I'm not sure I can catch all the corner cases

10:20 then there are other issues like being able to create a namespace named "foo/bar", but you can't actually access vars from that namespace

10:20 foo/bar=> foo/bar/x

10:20 java.lang.Exception: No such namespace: foo/bar (NO_SOURCE_FILE:0)

10:21 interesting, isn't it?

10:24 also, / is a valid symbol but /a is an invalid token :(

10:28 StartsWithK: excpetion made for / in clojure.core i guess

11:17 asbjxrn: What am I doing wrong? This takes 34 seconds:

11:17 (time (let [x (make-array Float/TYPE 10)] (dotimes [n 100000] (dotimes [f 10] (aset x f (float 0.1))))))

11:18 Chouser: use a number smaller than 100000, and it should go faster.

11:19 asbjxrn: Right. I just thought updating arrays would be faster.

11:19 Chouser: or insert #^floats after x

11:20 that is, between x and (make array ...

11:21 rhickey: name check: I have enhanced io! to establish an io context, and have a new fn, temp name io-scope, which takes a Closeable and ties its lifetime to the nearest dynamically enclosing io! block. so, (io! ... (io-scope afile) ...) afile will be automatically closed

11:22 io-scope throws exception if not in io! context

11:22 building blocks of enforced closing

11:22 Chouser: close-later

11:23 rhickey: ick

11:23 Chouser: hm

11:23 rhickey: should have io, was io-close, but that seems to close now

11:23 would like it to be short as well

11:23 but using scope as a verb is slightly icky too

11:25 io-register, io-bind, io-entail

11:25 Chouser: it does almost nothing at the moment it's called, so it's like a declaration

11:25 kotarak: io-closee

11:26 Chouser: io-closable

11:26 kotarak: io-to-close

11:26 asbjxrn: Chouser: Thanks. That worked.

11:26 Chouser: asbjxrn: great

11:27 rhickey: (io-scope x) returns x

11:27 I imagine a lot of (let [foo (io-scope bar)] ..)

11:27 also map io-scope

11:28 Chouser: ...in a context that consumes the whole seq, of course

11:28 rhickey: Chouser: nope

11:29 this is part of the solution for inside out lfe

11:29 the idea is that some (mostly io) soures will only give you a stream if they can succefully io-scope their resource

11:30 then you can use as much or little of the stream, knowing the io! block will clean

11:30 up

11:31 baggins: ok i give up on clojure for the day

11:31 thanks for the company and help.

11:32 kotarak: baggins: np

11:33 Chousuke: I like io-scope. instead of being an action on its argument (which should be a verb) it looks more like a declaration

11:34 rhickey: Chouser: but, yes, it must finish with the stream/seq in scope, if it leaks it, it will throw, but I can't prevent leaking

11:37 io-closes?

11:38 Chouser: I meant using up the (map io-scope ...) seq so that everything gets closed, but I guess if they're being opened lazily as well, that should be ok.

11:38 kotarak: io-will-close

11:39 rhickey: kotarak: a bit long

11:40 Chouser: the problem with io-scope is it doesn't even hint what it will do with the io scope.

11:40 io-closes is better. I like the sound of io-closable but i suppose that sounds more like a suggestion than a demand.

11:41 * baggins wonders what rhickey does during the weekdays.

11:42 rhickey: Chouser: the problem with closable is spelling, it's java.io.Closeable

11:49 Chouser: wow. why would they spell it like that? ..but ok, I can see that that nixes closable

11:49 knapr: YourKit is not free though, what's the best free profiler?

11:49 rhickey: another problem with close is it marries current capability, I'd like this to work if Java adds Disposable etc, in other words the scoping related cleanup might be polymorphic

11:50 for me, scope generically implies lifetime

11:50 Chouser: io-kills

11:50 rhickey: too violent

11:50 Chouser: heh

11:51 io-allows-to-pass-on

11:52 rhickey: oh boy

11:52 Chousuke: io-bound?

11:53 rhickey: Chousuke: the only problem with bind/bound is the other usages, also io-bound implies a perf characteristic

12:02 io-involve, io-enclose, io-collect

12:05 io-enlist

12:06 kotarak: io-disposes

12:07 rhickey: io-join, io-tie

12:14 io-frees

12:15 StartsWithK: io-attach io-relate io-fixate io-confine

12:15 Chouser: Somebody already said io-collect, right? I like how that suggests collecting them all into the 'io!' block, but also collecting a bit like garbage collect.

12:15 kotarak: io-cleaned

12:17 rhickey: Chouser: gc is collecting in a sense that close is not

12:17 io-limit

12:17 kotarak: io-closed

12:18 holmak: May I ask what you are trying to name?

12:18 lisppaste8: asbjxrn pasted "Why does the first let benefit from type declaration, but not the second?" at http://paste.lisp.org/display/73389

12:18 holmak: Is it some kind of macro to close a file after you do stuff with it?

12:19 rhickey: kotarak: it needs to be generic, not tied to close is better

12:19 asbjxrn: I can't spot what the difference between the two lets are... Can anyone help me out?

12:20 rhickey: it really is about the extent of the resource

12:20 kotarak: holmak: it registers a thing in an io! block, to be closed when the io! blocked is left. Throws when there is no enclosing io! block.

12:20 Chousuke: asbjxrn: give type hints to x and y too?

12:21 kotarak: io-resource

12:21 holmak: kotarak: Thanks. Reminds me of "with" in Python, though someone has probably brought that up already. "io-with"?

12:24 asbjxrn: Chousuke: You're on to something. But where to I add the hint in a dotimes?

12:25 (And should dotimes have added it itself, since it has to be an int.)

12:27 achim_p: asbjxrn: maybe try (aset diffused-grid (unchecked-add x (unchecked-multiply y 100)) (float 0.1))

12:28 lisppaste8: rhickey annotated #73389 with "faster" at http://paste.lisp.org/display/73389#1

12:29 asbjxrn: Ah!

12:35 aking: wow.. asbjxrn paste goes 200x faster by adding a single "int" coercion.. didn't think reflection was that slow.

12:36 Chouser: that's boxing, not just reflection

12:36 aking: so boxing and reflection? or just boxing?

12:37 rhickey: aking: primitive vs boxed math

12:38 all-primitive arithmetic is very fast

12:40 aking: I guess the skill is to figure out where and when to add the coercion tags. Turning on the reflection warning is showing lots of warnings in my code.. time to track down those in the more math intensive bits.

12:40 rhickey: io-frees and io-releases match the generic resource notion

12:40 Chousuke: io-autorelease?

12:41 too long?

12:43 asbjxrn: Any reason (+ 2 100) shouldn't be (int (+ 2 100)) ? Overhead in the wrong places?

12:43 vsthesquares: hiredman: why are there some methods in clojurebot_core that do not abide by lisp convention and use camel case instead? are they java overrides?

12:44 Chousuke: asbjxrn: in that case the addition will be done with boxed math, and then cast to primitive

12:45 asbjxrn: Sorry. My test was wrong.

12:45 lisppaste8: rhickey pasted "line-stream example of io-scope use" at http://paste.lisp.org/display/73390

12:45 Chousuke: vsthesquares: they have been there since the beginning

12:46 vsthesquares: no-one bothered to change them

12:46 asbjxrn: (What I actually meant was (+ (int 2) (int 100)) and (int (+ (int 2) (int 100))). But that is the case already.)

12:46 vsthesquares: oh, ok

12:49 Chousuke: I should've named the clojurebot things clojurebot.core etc instead ;( but I didn't realise I could have the namespace clojurebot AND subnamespaces at the same time.

12:49 I guess I could just break things a bit

12:49 :P

12:50 vsthesquares: well, I was just wondering, thanks for the info

13:35 Lau_of_DK: Good evening everyone

13:39 zargon_: Noob question: lisp's/clojure's development idiom is to change code/functions in your "running" environment on-the-fly and then rerun the code you're working on, right? How does this relate to the fact that a function as parameter comes in as the function itself (not its var), so that a change to the original function might not be seen if this function-reference is being cached? Is this a...

13:39 ...problem? How do you deal with that?

13:40 Lau_of_DK: It doesnt seemed like anything is cached, so all updates apply immediately

13:40 vsthesquares: it's just being evaluated every time you send it to the repl

13:42 zargon_: but if you do (def myfunc_handler myfunc) and then (otherfunc myfunc_handler), otherfunc will not see any changes to myfunc when called afterwards, right

13:42 ?

13:44 danlarkin: zargon_: why not test it out :)

13:45 zargon_: example scenario: in web-app development i would typically like to store such handlers in the session (buried in some component-graph), no consuming function will ever see changes to the underlying function

13:45 this is in contrast to the above mentioned "on-the-fly" change idiom , isn't it?

13:47 danlarkin: I tried, and i know that (def myfunc_handler #'myfunc) works like I want it to. The question is: should I always store the var if we want to propagate changes on-the-fly?

13:48 danlarkin: zargon_: no, if you redefine myfunc, any code calling myfunc will immediately use the new definition

13:48 no need to use myfunc_handler for that

13:50 zargon_: danlarkin: hmm, so storing handlers like in (def myfunc_handler myfunc) is not somethin you're confronted often? Is this an "anti-pattern"?

13:52 what about generator functions which internally cache a function-reference (e.g. via closure), this would be a typical scenario ...

13:54 danlarkin: zargon_: closures act the same as any other code

13:54 dynamic invocation

13:55 lisppaste8: achim_p pasted "on the fly" at http://paste.lisp.org/display/73394

13:56 danlarkin: Hm

13:56 achim_p: danlarkin: i think that's the problem (see paste)

13:57 zargon_: achim_p: thx for clarifying

13:57 danlarkin: but why would that behave that way when one layer of "indirection" does use the redefed definition?

13:58 oh

13:58 wait

13:58 nevermind

13:58 I know why

13:59 achim_p: you close over the value of the var, not the var itself

14:04 zargon_: achim_p: isn't that something that happens often in clojure programs?

14:07 achim_p: i'd say so, yes. the #' form seems to be rather rare. but i don't know how to best organize code for live patching, i've never really done that. i always thought it was a lisp myth ;)

14:10 zargon_: well, web-developing (e.g. via compojure) would qualify as "live-patching" as you call it. you have a serverside environment with "state" and between HTTP requests you change functions, so in this case if you close over values in the code you would be confrontend with that problem ...

14:11 Lau_of_DK: achim_p: You thought live patching was a myth? Its been done on a space shuttle by Nasa Im told :)

14:11 Chousuke: I think if you need to pass functions to some library and might want to live-update the function later, the right way to do that is to pass the var

14:12 zargon_: Chousuke: which means you change code semantics because of the way you develop your application?

14:13 Chousuke: assuming you have f, that takes a function as its parameter and setups a thread that calls teh parameter in some way repeatedly (on its own), then you need to give f the var as the parameter... otherwise you lose the ability to update it live.

14:13 zargon_: the fortunate thing here is that vars implement IFn and just pipe the call down to the value they hold

14:14 zargon_: if x holds a function, (#'x 1) and (x 1) have the same effect

14:14 hm, bad wording

14:14 zargon_: i know that, and its a clever decision, however ...

14:15 why isn't that the default?

14:15 Chousuke: default?

14:15 zargon_: I mean propagating "vars" to functions instead of the function itself

14:15 Chousuke: vars are not the same as their values

14:17 zargon_: Let it say that way, why doesn't the IFn act like a var so that on-the-fly updates are always seen ...

14:17 Chousuke: IFn is an interface for things that can be called.

14:17 the thing here is that data is immutable.

14:18 if you redefine a function, it results in a different function

14:18 that is, it doesn't change the old function

14:19 achim_p: i think the question behind this is: why are vars resolved at read time instead of eval time?

14:19 who knows the answer? ;)

14:19 zargon_: yes ...

14:20 Chousuke: um, what?

14:20 achim_p: aren't they?

14:21 Chousuke: I'm not sure what you mean by read-time resolution

14:21 (def a (def x 1)) (var-get a) = 1; (def x 2) (var-get a) = 2

14:22 lisppaste8: danlarkin pasted "dynamic invocation?" at http://paste.lisp.org/display/73395

14:22 Chousuke: however, when you do for example [x x] it results in [1 1]; that is, the value inside the var is taken instead of the var itself

14:22 achim_p: what i mean is: for (def x 3) (def y 4) (+ x y) is not (+ #'x #'y), for instance

14:23 zargon_: As I understand it the compiler goes from symbol => var => function-ref and stores the function-ref in the bytecode, this is the reason why live-updates can not be seen. I just wonder why this is the "default" instead of having a mechanism that works like storing a var and deferring function-ref lookup to runtime ...

14:23 Chousuke: achim_p: yeah, and that's makes sense.

14:23 achim_p: adding together two vars is not a sane operation :P

14:23 achim_p: so my guess was the symbol->var translation happens at read time

14:26 zargon_: but I guess it's all about Clojure's immutability promise which has been applied to function-definitions as well

14:29 Chousuke: lisppaste8: url

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

14:31 Chousuke pasted "live updates" at http://paste.lisp.org/display/73396

14:32 Chousuke: try that :P

14:34 well, adding the one missing paren of course.

14:35 eyeris: What do I need to load the MySQL JDBC driver besides "(class com.mysql.jdbc.Driver)"? I'm getting "java.lang.ClassNotFoundException: com.mysql.jdbc.Driver"

14:36 zargon_: Chousuke: thanks for clarification, my question was: do we have the need for "cangeable" very often in Clojure programs as I understand the answer is "no", however I think in webdevelopment the answer would be "yes"

14:36 triddell: question: if I have this data structure:

14:36 (def data '( ([1][2]) ([3][4]) ))

14:37 how can I get ([1][2][3][4]) ?

14:37 basically I want to flatten all the vectors to one list

14:38 Chousuke: zargon_: I think in webdevelopment most of your functions are used directly by others instead of indirectly like that. in those cases, you don't need to pass around vars.

14:38 Chouser: triddell: concat

14:39 zargon_: ok, thanks for listening guys ...

14:39 triddell: Chouser: thanks! I'll check that out.

14:39 lisppaste8: Chousuke annotated #73396 with "another example" at http://paste.lisp.org/display/73396#1

14:39 Chousuke: oh, damn, he left :p

14:42 achim_p: can anybody more knowledgeable than me confirm or deny the following statements?

14:42 1. at read-time, symbols are resolved to the *values* of the corresponding vars

14:42 2. at read-time, #'-forms are resolved to the vars

14:42 3. for updateable "higher order" functions passed to a function, we need the var

14:42 triddell: Chouser: the inner vectors are in lists though... concat doesn't seem to remove these

14:42 achim_p: 4. for updateable..., resolution (1) must not happen

14:42 5. this would mean, that the burden of var-resolving would lie with each function and must not happen automatically

14:42 6. nobody would want that ;)

14:44 Chousuke: achim_p: I'm not sure about that. you can see how redefining foo affects bar in my annotation

14:45 mmcgrana: Chousuke: are there any particular semantics around changing a bunch of definitions at the same time in a concurrent setting? If you have a graph of functions referring to each other and multiple using these functions, is there any sane way to change them all? I.e. is there a way to hot-swap an entire application?

14:45 *multiple threads using

14:46 Chousuke: mmcgrana: I think defs are atomic, but you'll have to ask rhickey for details.

14:47 Chouser: triddell: ah, try (apply concat my-list)

14:48 mmcgrana: Yeah I'm pretty sure that individual defs are atomic - i think the symbol table is implemented with the same persistent data structures used in user-level code - but I'm not sure that can gaurentee safty in swapping an entire lib w.r.t to the application logic. Perhpas one would just have to lock a region while everything gets sanely swapped out.

14:51 eyeris: What does (class do? I can't find it in the docs.

14:52 triddell: Chouser: thank you once again... I do try this stuff on my own for before asking here :-)

14:52 mmcgrana: (doc class)

14:52 clojurebot: Returns the Class of x; arglists ([x])

14:55 eyeris: Is there a way to get readline-style history support in the repl?

14:56 vsthesquares: eyeris: you can use jline

14:56 Fib: http://clojure.org/getting_started

14:56 eyeris: Ahh. I see it now.

14:56 Fib: Make sure to use ; rather than : in the classpath, that confused me the first time

14:58 danlarkin: if you're on windows, that is

15:09 eyeris: I am trying to load the MySQL JDBC driver. I'm a bit hopeless, having not used any other JVM language. My best attempt is: http://pastebin.com/m2fa17e42

15:10 AWizzArd: eyeris: have you downloaded the driver from the official mysql website?

15:11 eyeris: No, I installed it from a debian pacakge.

15:12 AWizzArd: Okay, fair enough. Have you added it to the classpath?

15:13 eyeris: I think so, I've set JAVA_HOME=/usr and I can find the driver in /usr/share/java/mysql.jar

15:13 AWizzArd: oh, btw, import is not the right thing to do

15:14 eyeris: Yeah? I've tried (class com.mysql.jdbc.Driver)

15:14 AWizzArd: eyeris: try: (Class/forName "com.mysql.jdbc.Driver") instead

15:14 eyeris: That also resulted in a classnotfound

15:15 http://pastebin.com/m4413b7a5

15:15 danlarkin: eyeris: the mysql.jar isn't on your classpath?

15:16 AWizzArd: you have the mysql-connector-java-5.1.7-bin.jar in your classpath, yes?

15:16 danlarkin: in these snippits your're pasting, it's not on your classpath

15:16 eyeris: How can I tell what my classpath is set to?

15:16 danlarkin: you're setting it with the -cp argument to java

15:16 eyeris: I've tried adding /usr/share/java/ to my -cp switch

15:17 Chousuke: eyeris: you need the full path to the jar

15:17 AWizzArd: but you should add /usr/share/java/mysql-connector.jar to the CP

15:17 eyeris: Oh, I thought -cp just appended values to your std classpath

15:17 I see.

15:17 AWizzArd: eyeris: I wished -cp would work like that.

15:17 eyeris: So there is no way to make the JVM auto load classes from the jars in a dir?

15:18 danlarkin: if you want that you need to do java -cp $CLASSPATH:etc:etc

15:18 Chousuke: there's the java.ext.dir property or something

15:18 I can't remember the exact name

15:19 eyeris: Yay! It works!

15:19 AWizzArd: grats

15:19 eyeris: Now I just need to figure out how to add it to the classpath used by Jetty/Webjure

15:21 Guest67527: I am having trouble getting doc strings to show up on multimethods

15:21 (defmulti multi "some-data" identity)

15:21 doesn't do it

15:26 eyeris: Does anyone here know how I can figure out what packages are available as dependencies in Maven2 pom.xml files?

15:29 Chouser: Guest67527: there's no special support for docstrings in defmulti

15:29 Guest67527: so instead, do: (defmulti #^{:doc "my docstring"} multi identity)

15:29 Guest67527: ah, the meta goes before the item name

15:30 I am not always sure where to put the meta description

15:32 AWizzArd: clojurebot: max people

15:32 clojurebot: max people is 127

15:32 AWizzArd: ah nice

16:02 rhickey: what for would you use java.util.Hashtable vs Clojures HashMaps {} ?

16:04 danlarkin: AWizzArd: within clojure?

16:05 AWizzArd: yes

16:05 Hashtables are much more ugly to use, but it seems that they are threadsafe and a good bit more efficient.

16:06 Thread safe, but no transaction safety.

16:07 rhickey: AWizzArd: how do you move something from one ht to another thread-safely?, or do a conditional add?, look for one of n keys etc etc?

16:07 atomic individual ops isn't much mt capability

16:07 AWizzArd: rhickey: only with locking I guess

16:08 rhickey: exactly

16:08 thus, Clojure

16:08 AWizzArd: yes

16:33 eyeris: Is (let) lazy?

16:33 I.e. is this correct? http://pastebin.ca/1305380

16:38 danlarkin: eyeris: no

16:38 the difference is in your second example you have (. rs (next))

16:38 Lau_of_DK: eyeris: The correct approach to SQL is: http://github.com/Lau-of-DK/clojureql/tree/master

16:39 Chousuke: eyeris: please don't use . that much, it hurts my eyes :(

16:39 eyeris: it's much better to use (.next rs) etc.

16:40 and instead of . you can use the more general -> operator :)

16:40 er

16:40 ..

16:40 instead of ..

16:42 eyeris: one reason for not using . is that the head of a list (where the operator goes) is an important place, and "." alone doesn't carry any information about what you're actually doing

16:43 eyeris: Okay

16:43 Chousuke: of course, there are times when . is better, but I can't think of any example right now

17:03 mmcgrana: is there any way to memoize a function such that logic that retrieves the value is run exactly once? I'd like to cache the result of slurping an IO stream into a string.

17:04 durka: there's the memoize function in core

17:04 rhickey: (doc delay)

17:04 clojurebot: Takes a body of expressions and yields a Delay object than will invoke the body only the first time it is forced (with force), and will cache the result and return it on all subsequent force calls; arglists ([& body])

17:06 mmcgrana: Right delay is simiilar to what I'm looking for, but I think the caller needs to have a handle on the delay to be able to prevent re-execution of the slurping. I'll make an example one sec.

17:12 Lau_of_DK: Does anyone here know of a good opensource (preferably) bug tracking software? (a little of topic, sorry)

17:12 ole3: bugzilla (good?), code.google.com

17:13 Lau_of_DK: Dont know if its good or not, but I'll look into it

17:21 mmcgrana: i guess delay is the way do do it, i just have to find a way to shuttle the Deley instance around.

17:22 durka: Lau_of_DK: trac has issue tracking as well

17:22 Lau_of_DK: k thx

17:30 blbrown: I get this error, http://paste.lisp.org/display/73404 I can't understand why though. What would cause the nullpointer exception

17:36 danlarkin: blbrown: is there a "setter" for event.styles?

17:36 seems like you should be using that

17:36 set! is definitely not what you want to use

17:37 blbrown: danlarkin, why not, I am converrting java code to clojure. This is the java code. event.styles = new StyleRange[styles.size()];

17:37 danlarkin, clojure version: event.styles = new StyleRange[styles.size()];

17:37 (set! (. event styles) (make-array StyleRange 1))))

17:37 danlarkin: no

17:37 forget about set!, pretend it doesn't exist

17:38 it's a special form, it is not for general purpose assignment operations

17:40 something like this makes sense, (.setStyles event (make-array StyleRange 1))

17:41 blbrown: danlarkin: does setStyles have to exist for that class LineStylEvent (swt api)

17:41 danlarkin: yes

17:42 blbrown: danlarking there is no setter for 'event.styles'

17:42 is a field with public access

17:43 danlarkin: oh...

17:44 http://clojure.org/java_interop#toc20

17:44 blbrown: hmm, is that exactly what I am doing

17:44 danlarkin: I apologize :-/

17:44 rhickey: blbrown: you are sure event is not null?

17:44 danlarkin: see this is why I should just be a lurker

17:44 and stop trying to help :)

17:45 blbrown: rhickey, event.styles is null ... (set! (. event styles) (make-array StyleRange 0))

17:45 rhickey, this doesn't generate an error the code above

17:46 rhickey, sorry, event is not null, but event.styles is null

17:47 LARefugee: are archives of these chats kept somewhere?

17:47 rhickey: blbrown: you are certain in the exact context where you get this error event is not null?

17:48 hiredman: clojurebot: logs?

17:48 clojurebot: logs is http://clojure-log.n01se.net/

17:48 LARefugee: Tanks!

17:50 blbrown: rhickey, it isn't pretty, but I am trying something like this. http://paste.lisp.org/display/73404#1

17:51 rhickey: this is your real cause: at org.eclipse.swt.custom.StyledTextRenderer.getTextLayout

17:53 what's at octane_main.clj:188

17:53 ?

17:54 blbrown: rhickey, sorry about that. I need to continue with the other required code for SWT. http://paste.lisp.org/display/73404#2

17:54 works not

17:54 now

17:55 ole3: Is it possible to give default initargs to a function?

17:56 something like keyword arguments in common lisp

17:57 AWizzArd: indirectly it's possible

17:57 ole3: ?

17:58 AWizzArd: you can specify multiple implementations of a function, which differ in the number of their parameters

17:58 ole3: ah, ok, but when i have many arguments...

17:59 maybe a 'arg-list' argument could help

17:59 hiredman: uh, I think you can do something like it by passing a hash and doing destructuring

17:59 AWizzArd: yes, for non-trivial things use a hashmap

17:59 this is a design pattern in Clojure

18:00 hiredman: ,((fn [& x] x) :a :b :c :d)

18:00 clojurebot: (:a :b :c :d)

18:00 ole3: i think i got it, thank you

18:00 Chousuke: there are no lisp style keyword args but with maps and destructuring you can have default values

18:00 CL style, even :p

18:02 ole3: ,((fn [{foo 123}] foo) {:foo 12})

18:02 clojurebot: nil

18:03 AWizzArd: ole3: for more trivial cases take a look at the implementation of drop-last for example: http://code.google.com/p/clojure/source/browse/trunk/src/clj/clojure/core.clj

18:03 ole3: I have to use rest arguments always

18:04 AWizzArd: drop-last has two implementations, where the first has only one parameter. If you call that it calls itself with two args.

18:05 Chousuke: the map destructuring stuff is somewhat complicated, I can never remember how it works.

18:06 AWizzArd: maybe defn can be improved to have an :optional in the argument vector, which automatically falls back to use a hashmap

18:08 hiredman: ,((fn [{:keys [a b c] :or {c 3}}] c) {:a 1 :b 2})

18:08 clojurebot: 3

18:08 hiredman: complicated

18:11 ole3: hiredman: perfect, thank you!

18:11 ((fn [{:keys [port address] :or {port 2500 address "0.0.0.0"}}]

18:11 (list port address))

18:11 {:port 80})

18:11 ,((fn [{:keys [port address] :or {port 2500 address "0.0.0.0"}}]

18:11 (list port address))

18:11 clojurebot: Eval-in-box threw an exception:EOF while reading

18:11 ole3: {:port 80})

18:11 ok, compilcated

18:12 ,((fn [{:keys [port address] :or {port 2500 address "0.0.0.0"}}] (list port address)) {:port 80})

18:12 clojurebot: (80 "0.0.0.0")

18:12 ole3: thanks

18:13 hiredman: ole3: the destructuring stuff is on http://clojure.org/special_forms in the section on let

18:17 ole3: hiredman: I can think of this like this: every key that is not supplied is nil and the result of the arguments are :ored with the keys of the parameter map.

18:18 nice

18:21 spooneybarger: Lau_of_DK: done

18:22 Lau_of_DK: Good to have you here :)

18:23 spooneybarger: We should probably continue our clojure conversation here instead of #emacs, more on topic here

18:23 at least until my food arrives

18:24 Lau_of_DK: We've just passed midnight here, so would you be okay, if I asked to continue this tomorrow - the bed is calling for me :)

18:25 But one of the outstanding features of Clojure is the community, you can get tons of help in here and people are always willing to lend a hand. The author of Clojure rhickey also hangs out in here, so there's always a fair chance of getting some good advice

18:26 spooneybarger: Lau_of_DK: sleep... my more clojure time isnt til a year from now. this year is all about smalltalk for me

18:26 Lau_of_DK: i pick a language every year or two years to rearrangge my brain, except haskell, i had to cu that short, that just hurt, i need to try that again when i get an intelligence transplant

18:27 Lau_of_DK: hehe - We're still early in January, you have an opportunity to make a smarter decision here than smalltalk :)

18:27 Although, I like the thought of trying to dive into a new language every year, maybe I'll take that on myself

18:28 spooneybarger: Lau_of_DK: i enjoy smalltalk and for the work I have for a while, it is the right tool for right now. I'm always pushing. always learning, always trying to use the right tool. clojure, great potential, for the stuff for right now, smalltalk is the right tool

18:29 Lau_of_DK: Cool, what are you working on ?

18:30 spooneybarger: Lau_of_DK: e-commerce web app stuff that seaside is just so much the obvious platform for... ok not obvious but i spent 6 months looking at what needs to be solved, what solves these issues and seaside on glass came out the winner across the board.

18:31 Lau_of_DK: being asked to develop e-commerce web apps that act like a desktop app for that, it was the winning platform

18:32 Lau_of_DK: Cool, will there be something online in Q1 where I can see your work ?

18:33 spooneybarger: its a port of a ton of code so, not til Q3, need to support existing systems and do the move at the same tim

18:33 foods here... talk more later... you can teach me clojure that i should look at

18:38 Lau_of_DK: spooneybarger: Alright, Im off to bed. Your first stop should probably be the Clojure source, get comfortable with core.clj, next up is Contrib, lots of interesting code there, and then finally you graduate to ClojureQL on Github :)

18:50 ole3: Where have i put the comments for defmulti?

18:54 there is no docstring for defmulti?

18:55 Chousuke: (doc defmulti)

18:55 clojurebot: Creates a new multimethod with the associated dispatch function. If default-dispatch-val is supplied it becomes the default dispatch value of the multimethod, otherwise the default dispatch value is :default.; arglists ([name dispatch-fn] [name dispatch-fn default-val])

18:55 Chousuke: apparently not

18:55 hoeck: ole3: <Chouser> Guest67527: there's no special support for docstrings in defmulti

18:55 <Chouser> Guest67527: so instead, do: (defmulti #^{:doc "my docstring"} multi

18:55 identity)

18:58 ReplRat: is anybody else having problems accessing github? what's the pastie for this channel?

19:00 hoeck: ReplRat: yeah, "down for maintenance" and showing a two gallants video

19:00 arohner: github is down

19:01 ReplRat: wow that sucks.

19:01 hoeck: (actually my favourite 2gallants song :)

19:01 arohner: really irritating, I want to download clj-backtrace

19:01 ole3: hoeck: thanks

19:01 ReplRat: is it acceptable for a site like this to be down for 'maintenance'?

19:01 hoeck: thanks to chouser for knowing the answer 4hrs ago

19:03 ReplRat: mhh, not really, but to be fair its 1am on sunday morning and git is distributed anyway

19:05 arohner: github is headquartered in san francisco, where it's 3pm on a saturday

19:57 dreish: github appears to be up for me. And I think it's actually 4:57 p.m. over there, not 3:57.

20:00 ReplRat: github is up again now. i just cloned compojure

20:14 arohner: dreish: yeah, you're right

20:25 in emacs, can I create a key binding that runs a command in slime?

20:32 Guest89243: (define-key slime-mode-map (kbd "C-c some-key") 'your-function)

20:33 Guest93269: or slime-repl-mode-map for the repl

20:35 arohner: Guest26309: thanks

20:35 now I just need to figure out how to send an arbitrary string to the repl via slime

20:59 rhickey: ok, more naming fun, need a term to unify sequences and streams - leading contender: series

20:59 zakwilson: I like series.

21:08 danlarkin: chain?

21:08 kinda lame though

21:08 series is better than chain

21:08 Chouser: not as lame as my first thought. "brook"

21:09 rhickey: many cases that now test for seq? will need series? instead

21:20 danlarkin: progression?

21:21 series leads

21:25 Chouser: that's 3 s-words to mean very related things. surely that's bound to confuse someone.

21:28 eyeris: Does anyone here use clojureql?

21:35 I'm trying to determine whether or not it has a function to transform select queries to select count(*) queries similar to sql/distinct

21:35 I don't think it does.

21:43 *symbol* being global is simply convention, right? There isn't any syntax support that makes *symbol* global?

21:43 Chouser: right

21:45 every 'def' is global

21:49 eyeris: Is there a function index? The search engine on the website seems to ignore my (type, returning every page that matches type.

21:50 danlarkin: http://clojure.org/api

21:51 mfredrickson: rhickey: about an "flow"

21:51 eyeris: How can I get the type of a variable as a string? Similar to python's type() function

21:52 Chouser: (class x) returns the Class object for x's type

21:53 (str ...) returns strings for things

21:53 ,(str (class 5))

21:53 clojurebot: "class java.lang.Integer"

21:53 eyeris: Do all types have a Class?

21:54 Chouser: well, there are primitive types

21:54 int, float, double ... but if you pass those to Clojure functions they get upgraded to Integer, Float, Double

21:55 eyeris: Okay

22:40 danlarkin: I should be able to swap! an atom from different threads and have changes show up in another thread, right? I'm pretty sure that's how it works but I'm confused as to why some code I have isn't working and I'm making sure my assumptions are correct :)

22:42 Chouser: danlarkin: yes, that's correct.

22:42 danlarkin: right, ok thanks

22:43 eyeris: How can I run a .clj file from the cmd line?

22:45 If I run the repl using the shell to redirect input from the file, the repl closes without giving me a prompt

22:45 Chouser: java -cp clojure.jar clojure.lang.Repl myscript.clj

22:48 eyeris: Is there a cmd to print the loaded namespaces?

22:48 danlarkin: (doc loaded-libs)

22:48 clojurebot: Returns a sorted set of symbols naming the currently loaded libs; arglists ([])

22:48 eyeris: Nice

22:49 I see (all-ns) now too.

22:52 java.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.IFn

22:52 How can I tell which line is throwing that exception?

22:54 hiredman: eyeris: it is the line when you are try to use a string as a function

22:55 eyeris: Ahh! I Fn not IF n :)

23:08 Is there something special I have to include in my source file in order to use the try form?

23:08 When I try I get this error: Caused by: java.lang.Exception: Unable to resolve symbol: catch in this context

23:09 hiredman: erm

23:10 eyeris: Oh, nvm

23:10 I had an extra ) before (catch

23:11 danlarkin: so I'm swap!ing *settings*, which contains an atom... then afterwards I print @*settings* and it has been correctly updated... but then from another thread I deref it and it's empty. I'm confused :(

23:16 lisppaste8: Chouser pasted "2 threads, 1 atom" at http://paste.lisp.org/display/73411

23:16 Chouser: danlarkin: couldn't tell ya -- works ok for me.

23:16 danlarkin: yeah I was just hoping you'd say, oh I totally had that problem, and it was because I forgot the magical incantation!

23:17 Chouser: heh

23:17 you're sure it's the same *settings*? No typo? No binding?

23:18 gnuvince: Chouser: *Really* bad paste title ;)

23:19 Chouser: Oh. Let pretend it's "1 atom, 2 threads", shall we?

23:19 hiredman: oooo

23:20 markov chains in clojure

23:20 just what clojurebot needs

23:22 LARefugee: clojurebot: book?

23:22 clojurebot: book is http://www.pragprog.com/titles/shcloj/programming-clojure

23:22 danlarkin: Chouser: yup, same *settings*, unfortunately it's gotten hard to debug because I'm doing ... WAIT! I figured it out!!!!

23:22 yessssss!

23:23 eyeris: I'm new to both the JVM and Lisp. Could someone explain to me why this clojureql code is throwing an exception? http://paste.lisp.org/display/73412

23:23 danlarkin: Chouser: thanks for the inspiration

23:24 Chouser: danlarkin: np. I never debug as well as when I'm explaining to someone else why it ought to be working.

23:25 danlarkin: I'm doing dynamic code reloading, and *settings* was getting redefed, *sigh*

23:25 Chouser: ah. defonce?

23:25 danlarkin: oh perfect, heh I was just about to write my own

23:26 hiredman: eyeris: is sql-stmt a string?

23:26 Chouser: eyeris: clojureql is expecting lisp-like code describing the query.

23:27 eyeris: Ahh! right!

23:29 hiredman: clojurebot: markov chain generator is http://groups.google.com/group/clojure-study-dc/browse_frm/thread/026ccdc8acb102f9?pli=1

23:29 clojurebot: Ack. Ack.

23:31 banisterfiend: danlarkin: walang kekek

23:32 danlarkin: banisterfiend: huh?

23:32 banisterfiend: danlarkin: grasshopper

Logging service provided by n01se.net