#clojure log - Feb 06 2009

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

0:01 hiredman: svn rev 1251

0:01 clojurebot: svn rev 1251; [lazy] removed loop from distinct

0:42 lisppaste8: metaperl pasted "trying to use apply..." at http://paste.lisp.org/display/74963

0:43 Cark: you forgot a map somewhere

0:44 err oops forget it

0:44 durka42: metaperl: can't treat java methods as first-class fns. use #(Integer/parseInt %)

0:45 metaperl: ouch

0:45 what does taht % sign do?

0:46 Is it still fn [x]

0:47 ayrnieu: #(f %) => (fn [x] (f x)), #(f %1 %2 %3) => (fn [x y z] (f x y z))

0:54 metaperl: thank you. I got it - (map (fn [x] apply #(Integer/parseInt %1 %2) x) number-and-base)

0:55 yangsx: When I try to use (compile 'mylib.example), it says "No such file or directiory: (example.clj:1)", though I have use add-classpath the relevant path. Any hint?

0:55 directory*

0:55 ayrnieu: hint: add the path to CLASSPATH before you start clojure. Don't use add-classpath

0:55 hiredman: clojurebot: add-classpath?

0:55 clojurebot: add-classpath is bad, avoid it. I mean it!

0:55 ayrnieu: also, you mean both paths, right?

0:55 yangsx: ayrnieu: I'm using slime.

0:57 ayrnieu:Do you mean if I want to use compile, I should not use slime?

0:57 metaperl: ,(. java.lang.String concat "a" "b")

0:57 clojurebot: java.lang.IllegalArgumentException: No matching method: concat

0:57 ayrnieu: not using slime is an option, as is adding the path to CLASSPATH before you start it.

0:58 but you've dropped a packet.

0:58 yangsx: also, you mean both paths, right?

0:58 yangsx: ayrnieu: sorry, what do you mean by both paths?

0:58 durka42: metaperl: sorry, had to run. did you get an answer?

0:59 metaperl: durka42: yes, but now I have another question

0:59 ,(. java.lang.String concat "a" "b")

0:59 clojurebot: java.lang.IllegalArgumentException: No matching method: concat

0:59 metaperl: how to concatenate string?

0:59 durka42: java.lang.String is a Class

0:59 instances of String have the methods

0:59 ,(.concat "a" "b")

0:59 clojurebot: "ab"

0:59 durka42: (. concat "a" "b")

0:59 ,(. concat "a" "b")

0:59 clojurebot: java.lang.IllegalArgumentException: Malformed member expression

0:59 durka42: just kidding

0:59 ,(. "a" concat "b")

0:59 clojurebot: "ab"

0:59 ayrnieu: yangsx - mylib and *compile-path*

1:00 metaperl: ,. ("a" concat "b" concat "c")

1:00 clojurebot: java.lang.Exception: Unable to resolve symbol: . in this context

1:00 metaperl: ,.(. "a" concat "b" concat "c")

1:00 clojurebot: java.lang.Exception: Unable to resolve symbol: . in this context

1:00 metaperl: ,.(. "a" concat "b")

1:00 clojurebot: java.lang.Exception: Unable to resolve symbol: . in this context

1:00 ayrnieu: ,(-> "a" (.concat "b") (.concat "c"))

1:00 clojurebot: "abc"

1:00 durka42: just ,

1:01 yangsx: ayrnieu: I didn't, *compile-path* is just classes.

1:01 metaperl: ,(. "a" concat "b")

1:01 clojurebot: "ab"

1:01 metaperl: ,(. "a" concat "b" concat "c")

1:01 clojurebot: java.lang.IllegalArgumentException: No matching method found: concat for class java.lang.String

1:01 ayrnieu: yangsx - OK. Does 'classes' exist, and is it in your classpath?

1:01 durka42: ,(.. "a" (concat "b") (concat "c"))

1:01 clojurebot: "abc"

1:02 metaperl: hmm

1:02 where can I learn about -> and ..

1:03 I kinda remember them from the Java tutorial part 1

1:03 hiredman: uh

1:03 ayrnieu: you can read their documentation, read their source, look for examples, ask questions about them, read about them in Programming Clojure

1:04 yangsx: ayrnieu: it seems not the case

1:04 ayrnieu: I think -> and doto are particularly useful. I think .. is hard to read.

1:04 hiredman: yes

1:04 ayrnieu: yangsx - I think that's probably your 'file not found' error, then.

1:05 yangsx: ayrnieu: thanks, I didn't notice *compile-path* thing before this. It's not convenient to order the book, though.

1:19 metaperl: what is 'Programm/join #java

1:25 wouldnt .quote be in java.lang.String even though discussed in java.regex.Pattern - http://java.sun.com/j2se/1.5.0/docs/api/java/util/regex/Pattern.html#quote(java.lang.String)

1:25 ,(. "afdafasdfadsf" quote)

1:25 clojurebot: java.lang.IllegalArgumentException: No matching field found: quote for class java.lang.String

1:27 yangsx: If I add my paths when starting clojure, compile works as expected. Use add-classpath later seems to not work properly. Just a bit inconvenience to me to use with slime, though.

1:29 durka42: metaperl: no. as it says on that javadoc page, quote is a static method of Pattern, that takes a String and returns a String.

1:29 ,(java.util.regex.Pattern/quote "asdfasdfasdf")

1:29 clojurebot: "\\Qasdfasdfasdf\\E"

1:29 metaperl: ah

1:30 durka42: are you learning java and clojure concurrently?

1:30 metaperl: ,(java.util.regex.Pattern/quote "hi\r\nthere")

1:30 clojurebot: "\\Qhi\r\nthere\\E"

1:30 metaperl: durka42: yes

1:30 since clojure is a concurrent language, seems like a good idea

1:30 durka42: :)

1:30 metaperl: i've fooled around with lisps for a long time

1:30 played with java in eclipse a few times

1:31 * durka42 watches the same question and the same answer occur in #clojure and #java at the same time

1:31 * metaperl blushes

1:32 durka42: i don't know how often learning clojure has been tried without prior knowledge of java

1:32 i wish you luck

1:32 metaperl: really, I was wondering if there were something like Perl --- where a single quoted string is literal and double-quoted string is not

1:32 java is hardly anything to learn... just knowing libraries

1:32 durka42: well, no, but there are regex literals

1:32 ,#"blah"

1:32 clojurebot: #"blah"

1:32 durka42: (class #"blah")

1:32 ,(class #"blah")

1:32 clojurebot: java.util.regex.Pattern

1:33 durka42: ,(print #"one\ntwo")

1:33 clojurebot: #"one\ntwo"

1:33 durka42: ,(print "one\ntwo")

1:33 clojurebot: one two

1:33 durka42: (clojurebot chopped the line break)

1:55 * metaperl wants to create a StringBuilder instance and pass it to the constructor of Formatter

1:55 metaperl: really I just want to create a string which has the result of (- 25 21) in it

1:56 printf "the result is %d", 25-21

1:57 hiredman: ,(str "the result is " (- 25 21))

1:57 clojurebot: "the result is 4"

1:57 metaperl: phew

1:57 that was much easier

1:59 durka42: yuck

1:59 ,(.toString (. (java.util.Formatter.) format "the result is %d" (into-array [(- 25 21)])))

1:59 clojurebot: "the result is 4"

1:59 yangsx: My program can run interactively with slime, but running the compiled program gives No matching ctor found for class java.io.FileWriter at clojure.lang.Reflector.invokeConstructor(Reflector.java:157), what's likey the reason?

2:00 Google gives two hits, but not exactly the same with mine. I suspect I missed something.

2:01 metaperl: ,(% 15 6)

2:01 clojurebot: Eval-in-box threw an exception:arg literal not in #()

2:01 durka42: mod, rem

2:01 % is the parameter in lambda fns

2:02 metaperl: yes, but it would never be at start of parentheses

2:02 hence could be overloaded

2:02 ,(mod 15 6)

2:02 clojurebot: 3

2:02 metaperl: ,(rem 15 6)

2:02 clojurebot: 3

2:05 te: hello ladies and gentlemen

2:06 metaperl: sup te

2:06 dont forget the androgynes

2:06 durka42: and the bots

2:06 metaperl: lol

2:07 is clojurebot written in clojure?

2:07 durka42: sometimes they talk to each other when they get bored

2:07 yes it is

2:07 clojurebot: paste?

2:07 clojurebot: lisppaste8, url

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

2:07 durka42: by hiredman and chousuke

2:07 metaperl: that's the lisppaste url

2:08 durka42: clojurebot: where are you?

2:08 clojurebot: http://github.com/hiredman/clojurebot/tree/master

2:08 metaperl: lol

2:09 well I will chat with you ladies, gentleman, androgynes, and bots later :)

2:09 sorry but I must be going!

2:13 te: I'm not /too/ far along in Clojure-- but I have been reading... I'm trying to visualize how haskell works (the anatomy of a simple program), as opposed to how say, perl works.

2:13 err s/haskell/clojure

2:13 sorry it's late

2:14 metaperl: te look at the screencasts

2:14 the ones for java programmers were useful to me

2:14 i'm converting Simon Cozen's "Beginning Perl to Clojure" - http://github.com/metaperl/begin-clojure/tree/master

2:15 http://en.wikibooks.org/wiki/Learning_Clojure#Reader_Macros

2:15 ttyl!!!!

2:15 durka42: unfortunately no user-defined reader macros :(

2:15 * durka42 should sleep

2:31 te: metaperl: thanks

2:59 boxbeat: can I only interact with the OS through Java?

3:00 ayrnieu: (println "hi") <-- interacting with the OS.

3:00 boxbeat: would anyone be interested in creating a C-version of clojure?

3:00 ayrnieu: yes but doing scripting like in python with subprocess etc

3:01 ayrnieu: (println "hi") <-- interacting with the OS, like with Python's print "hi"

3:09 cgrand: bosbeat: see clojure.contrib.shell-out to launch sub-processes

3:09 * cgrand should use completion

3:10 cgrand: beatbox: see clojure.contrib.shell-out to launch sub-processes

3:11 ayrnieu: oh, somehow I stopped reading before "with subprocess"

3:11 beatbox: why? explaining beats being an asshole

3:16 albino: There is also ProcessBuilder from java land

5:48 boxbeat: does clojure have partial application or currying?

5:50 rfgpfeiffer__: yes

5:50 ,((partial + 3) 4)

5:50 clojurebot: 7

5:52 Chousuke: it's a bit less common than in haskell though.

5:53 usually people prefer anonymous functions, like #(> 5 %) over (partial > 5)

5:55 boxbeat: is partial actually of much use?

5:55 ah i see

5:55 rfgpfeiffer__: I wrote a macro that lets you define curried functions

5:56 but losing dispatch on number of args is not worth it

6:01 karmazilla: I find my functions rarely have multiple arities. Might be a style thing

7:27 djpowell: I just needed a function that takes a sequence, and deals the sequence out to N sequences. Basically, so that I can process the sequence by N java threads. Does one already exist?

7:27 I've wrote one now, but wanted to check I wasn't reinventing the wheel.

7:28 Holcxjo: partition ?

7:28 ,(doc partition)

7:28 clojurebot: "([n coll] [n step coll]); Returns a lazy sequence of lists of n items each, at offsets step apart. If step is not supplied, defaults to n, i.e. the partitions do not overlap."

7:29 Holcxjo: ,(partition 3 (range 10))

7:29 clojurebot: ((0 1 2) (3 4 5) (6 7 8))

7:29 Holcxjo: ,(partition 3 (range 11))

7:29 clojurebot: ((0 1 2) (3 4 5) (6 7 8))

7:29 djpowell: No that won't do it

7:29 cause it is a lazy sequence

7:29 I want:

7:29 (deal (iterate inc 0) 3) to return:

7:29 ((0 3 6 9 12 ...) (1 4 7 10 13 ...) (2 5 8 11 14 ...))

7:30 Holcxjo: Ah! I see

7:32 lisppaste8: djpowell pasted "deal" at http://paste.lisp.org/display/74970

7:32 jdz: anything involving drop function won't work

7:32 i think

7:33 djpowell: oh really? why?

7:33 jdz: ok, nvm

7:37 Chousuke: ,(apply map list (partition 3 [1 2 3 4 5 6]))

7:37 clojurebot: ((1 4) (2 5) (3 6))

7:38 Chousuke: ,(take 4 (first (apply map list (partition 3 (iterate inc 0)))))

7:38 hmm.

7:38 list is not lazy I guess :(

7:39 clojurebot: Execution Timed Out

7:40 Chousuke: ah, good timing

7:41 ,(apply map list (partition 3 [1 2 3 4 5 6])) ; rhickey, any idea if it's possible to make this work if the sequence is infinite (producing a seq of infinite seqs). list doesn't seem to be lazy :/

7:41 clojurebot: ((1 4) (2 5) (3 6))

7:41 Holcxjo: (deal () 3) -> ((nil) (nil) (nil))

7:41 shouldn't that be (() () ()) ?

7:42 cads: hello. I was having a discussion about languages that use the same namespace for functions and variables, and was wondering if reasons for using lisp 2 that are commonly given, mainly that it's easy to shoot yourself in the foot, apply when we're dealing with languages where the variables are immutable or already thought of as functions (clojure/haskell).

7:44 Someone pointed out that the programming issues of mutable variables and immutable functions in the namespace can all be easily avoided, but what the real issue motivating lisp-2 was that macros in lisp-1 can be a royal pain

7:44 Chousuke: they aren't in clojure though :)

7:45 cads: I maintain that in a fully functional language like haskell it's perfectly natural for functions that take arguments to be in the same namespace as those defined identifiers that just contain values

7:45 djpowell: Holxcjo: yeah. where are the nils coming from I wonder?

7:45 Cark: i think that being functional or not is orthogonal to this issue

7:45 Chousuke: cads: I think there was some macro-hygiene problem that having two namespaces would solve.

7:46 Holcxjo: djpowell: There is a test for empty list missing -- you only do it on the recursion

7:46 cads: but yes, I remember from a talk where rhickey mentions that macros in clojure take a slightly nonconventional route compared to scheme

7:46 rhickey: Chousuke: you can get what you want, but you have to flip things around, and right, list makes a concrete, non-infinite, list

7:47 Cark: cads : if you get a parameter "list" and need to build a list in your function, the problem arises wether you're using a perfectly functional language or not

7:47 Holcxjo: djpowell: Wrap the whole (let [r...) in a (when xs ...)

7:47 Chousuke: djpowell already suggested http://paste.lisp.org/display/74970 but there has to be a nicer way :)

7:48 cads: Cark, are you talking about the macro issue, or the issue of getting functions confused with variables?

7:48 Cark: the later

7:49 that's the same problem anyways, only you don't control where your macro is being expanded

7:49 Chousuke: cads: I think clojure's namespace-qualifying syntax-quote is an even better solution. as far as I can tell it helps prevent even more hygiene problems, doesn't sacrifice the elegance of lisp-1, and is capable of everything the CL macro system does without the complex stuff you see in scheme.

7:50 Cark: chousuke : also clojure won't allow to use symbols as eay as in cl in a macro

7:50 Chousuke: Cark: symbols?

7:50 Cark: rmember the infamous ~'symbol thing =P

7:50 Chousuke: ah, that

7:50 well that's easy.

7:50 Cark: right, but you need to specifically say : i want to capture this symbol

7:50 Chousuke: easier than remembering to accidentally *avoid* capturing names :P

7:50 Holcxjo: djpowell: I am also worried that you basically evaluate every element of the input list n times -- if they are expensive to compute you are wasting a lot of computation

7:51 Chousuke: Cark: that's better than accidentally capturing it :)

7:51 Cark: sure thing =P

7:51 Holcxjo: (assuming Clojure isn't memoizing, which I assume as it would go againt the immutable objects)

7:51 cads: Cark: I don't completely understand what you mean. I'm referring to the normal everyday programming problem of accidentally trying to call a function when it's a variable, or overwrite a function. Are you talking about a problem in macro-programming?

7:51 Chousuke: Holcxjo: seqs are cached.

7:52 Holcxjo: each value is realised only once.

7:52 Cark: cads : nope

7:52 Chousuke: functions in clojure *are* values

7:52 so you shouldn't worry about confusing functions with values

7:52 cads: Cark: I'll ask for an example in a bit, right now my puppy needs to pee! bbiab

7:52 Cark: (do-something-to-a-list [list] (list (first list)) .... what does that mean ?

7:53 Chousuke: Cark: that's nonsensical.

7:53 list is a value (a parameter in this case) that's probably not a function.

7:53 Cark: that's an everyday problem, in a lisp one you need to (do-something-to-a-list [lst] (list (first lst))

7:53 now how is this related to being purely functional ?

7:53 Chousuke: or name your list a bit better.

7:53 Cark: not related at all

7:54 chousuke : right

7:54 we could make an example in c# ... that's a lisp hum 3 to 20 don't know =P

7:54 lisppaste8: djpowell annotated #74970 with "fix (nil) problem" at http://paste.lisp.org/display/74970#1

7:54 Chousuke: that's simple name shadowing... happens in all languages.

7:55 except those that make it a compilation error I suppose..

7:56 Cark: anyways, i feel that this whole lisp1 vs lisp2 thing is pretty unimportant

7:56 debating it won't make the program run any better

7:56 Chousuke: I'm not saying lisp-2 doesn't have its advantages, but I feel that those advantages are not worth the lost elegance of not being a lisp1 :)

7:57 Cark: that's only cosmetic, there are advantages in both camps ... clojure avoids most pitfalls with a couple simple things, so i guess it's ok

7:57 (as it is)

7:57 Chousuke: being lisp-2 makes functional code cumbersome though

7:58 since you need to be funcalling all the time if you want to use higher-order functions.

7:58 Cark: right

7:58 on the other hand, it's sometimes less readable

7:58 metaperl: well you have to recur here though right?

7:59 Cark: (((a b) b) ((z e) k))

7:59 =/

7:59 metaperl: clojure is a lisp-1 but you recurse by the word recur?

7:59 Cark: metaperl : unrelated

7:59 metaperl: oh

8:03 Chousuke: Cark: I don't like that kind of code :)

8:04 Cark: me neither

8:04 Chousuke: Cark: I prefer naming the functions first in a let

8:04 Cark: well then you have as much overhead as when using funcall

8:04 though it's still unreadable with funcal

8:05 Chousuke: Cark: not really.

8:05 for example, when implementing a higher-order function like map, the function you're calling is already named (it's a parameter)

8:06 in that case, you have a function returning a function so (let [foo (a b) bar (z e)] (foo b) (bar k)) is in my opinion more readable.

8:07 Cark: yes it is

8:08 Chousuke: I guess you can find examples where either approach looks ugly though :)

8:09 Cark: anyways, you pick a language, then adapt to it, wether it is a lisp1 or 2 is really not important to me

8:09 Holcxjo: djpowell: take-nth

8:09 ,(doc take-nth)

8:09 clojurebot: "([n coll]); Returns a lazy seq of every nth item in coll."

8:25 Holcxjo: What is the difference between (drop n xs) and (nthrest xs n) ?

8:27 Lazyness?

8:27 ,(doc nthrest)

8:27 clojurebot: "([coll n]); Returns the nth rest of coll, (seq coll) when n is 0."

8:27 Holcxjo: ,(doc drop)

8:27 clojurebot: "([n coll]); Returns a lazy seq of all but the first n items in coll."

8:31 cemerick: I think I *might* be overcomplicating things here, but it seems like import should attempt to load the lib corresponding to each class ahead of actually loading the class into the current namespace. Unless I'm missing something, without that, one needs to explicitly load or require each such lib before importing it in other clojure code so that AOT compilation can succeed.

8:33 lisppaste8: Holcxjo annotated #74970 with "Simplification using take-nth" at http://paste.lisp.org/display/74970#2

8:34 cemerick: I guess I'm saying that each import should imply a require, so that a given lib/classname doesn't have to be specified twice in the ns form.

8:37 rhickey: cemerick: the :load-impl-ns gen-class flag allows you to control whether the static initializer for a generated class loads the implementing namespace

8:39 cemerick: rhickey: if I understand :load-impl-ns properly, that's a runtime consideration -- I'm talking about AOT-compile-time, where no classfiles have been generated yet, but a given lib with a gen-class spec imports a classname of another lib with a gen-class spec

8:39 In order to resolve that import, it seems like a second reference to that lib/class must be made in a :require

9:01 djpowell: Holcxjo: ah, missed take-nth

9:02 it probably makes sense to wrap the input to deal with a seque, else slow consumers will cause the remainder of the seq to stay in memory

9:08 Holcxjo: I'm not sure of the difference between drop and nthrest either

9:10 is the multiple list version of map a clojure thing? does haskell have that? i spent ages looking for a zip function at first.

9:12 gnuvince: djpowell: it's Clojure specific

9:13 djpowell: unless you use type class black magic (as in Printf), you can't do that with Haskell

9:13 djpowell: ah, python has it

9:13 gnuvince: which is why they have zip, zip3, zip4,... zip8

9:13 djpowell: http://docs.python.org/library/functions.html

9:17 Holcxjo: djpowell: CL has it as well

9:19 cads: Hey, I'm back.

9:21 I read the conversation after I left and before I got disconnected, and especially your example about list, Cark. I agree that it's not to do with functional programming.

9:23 My main point about functional programming is that classically we consider everything to be a function, even what would be called variables in a imperative language.

9:24 ayrnieu: you can also take the prolog/erlang/mercury path of capitalizing variables. It's a bit odd, but then so are nam lst rst nxt

9:25 cads: hmm, I'll admit I've only played with haskell and pen and paper FP, plus my math

9:26 I feel most comfortable considering constants as functions which take no arguments

9:28 the "everything is a function" way of thinking means you won't collide names between a constant and a function

9:29 so if each thing is a function, it feels silly to put functions with parameters in one namespace, and constants in another

9:30 Chouser: that feels silly anyway. ;-)

9:30 ayrnieu: so how long have you thought this way, and how well do you think it has helped you not name your parameters 'name'?

9:33 cads: I never felt a need to name a variable the same name as a function, I don't think

9:33 ayrnieu: so you can't say that this interpretation has helped you.

9:33 Cark: =)

9:35 cemerick: so, given a lib with a gen-class spec, how is one supposed to type-hint using the gen-class' eventual classname (since it looks like the entire file needs to be loaded before classfiles are generated)

9:40 cads: well write in math, F = D^(-1)(f)... f can be a constant or f can be a polynomial, and god knows what D is, but I wouldn't call it f if f was defined elsewhere. I guess the question is if this way of thinking has helped me avoid accidentally naming new functions the same name as existing functions accidentally.

9:40 if I'm writing f(f), then f is a wierd ass operator

9:42 and yeah, I think it's help

9:43 cemerick: oh, actually my immediate issue is being able to refer to the gen-class' constructors in the various method impls in clojure...

9:43 Chousuke: cads: f could be identity :)

9:43 though no idea how you would express that mathematically.

9:45 cads: Id x = x forall x in X, where X is a set powerful enough to have Id in it :D

9:46 ayrnieu: cads, lisp-1 doesn't need a "really, see, variables and functions are both fungible slices of Chewbacca" defense. It's an obvious problem accompanied by obvious benefits and people adjust.

9:48 Chousuke: cads: I guess you could just validly say Id x = x forall x

9:49 ayrnieu: it's like saying that you can't have n-ary functions in Haskell, and you can't distinguish between the two functions 'foo 1 2' and 'foo 1', but you can't do these things because you get automatic currying. Oh, OK. No need to argue that this or those are fundamentally superior, or that someone used to one will not have to adjust to a language dominated by another.

9:51 Chousuke: I guess Haskell could have N-ary functions if you extended its metaprogramming capabilities somewhat; do not actually offer N-ary functions, but automatically generate one of specific arity when needed.

9:51 that might conflict with some other stuff though :/

9:53 LordOfTheNoobs: Chousuke:

9:54 rhickey: cemerick: sorry, had to run out before. How would import know which classes were Clojure-generated?

9:57 cemerick: rhickey: it doesn't, but it can (optionally?) *attempt* to require all of the libs corresponding to the named classes.

9:58 rhickey: hmm...

9:58 cemerick: My line of thought is: (a) the programmer knows far less than the machine as to which classes are clojure-generated (b) the machine can just do some extra work at load-time to make import imply require, and (c) the alternative of duplicating lib/classnames and otherwise doing the necessary associated bookkeeping is *really* painful

9:59 if you're worried about runtime impact of doing a fail-safe require for each lib corresponding to each class to be imported, a :require-imports key could be added to ns

9:59 (which I'd *always* set to true, but then I could care less about init runtime)

10:00 rhickey: cemerick: no, I'm just wondering if this is an actual problem. Right now import does classForName, so the class should be loaded by import and load-impl-ns should matter

10:01 cemerick: rhickey: that's true if you're actually using the code -- if you're just using c.l.Compile (for example), and you pass to it com.bar and com.foo, both of which have genclass specs, and bar imports com.foo, right now bar *must* require com.foo as well.

10:02 I should say, that's true when you're not compiling

10:03 rhickey: cemerick: but if foo were compiled first you wouldn't - this seems more like a make problem

10:04 cemerick: rhickey: it seems like resolving the import/lib dependencies of an arbitrary clojure codebase is not a problem that should be solved in ant et al.

10:05 rhickey: cemerick: I'm not saying it is, but just as javac must do a dependency analysis, so might compile, rather than trigger loads via side effects of imports

10:05 cemerick: what I'm trying to get to is a state where compiling a clojure codebase is as straightforward as compiling a java codebase (thus my comments yesterday about c.l.Compile taking a set of source root dirs, and walking the files in them in order to determine what libs needed to be loaded)

10:06 rhickey: oh, well, that's an implementation detail. Doing rigorous dependency analysis in-flight while loading/importing seems like a big chunk to bite off, compared to doing a fail-safe require of every lib corresponding to each class to be imported.

10:07 s/"loading/importing"/compiing

10:07 rhickey: cemerick: I wonder if anyone other than you is importing gen-classed files yet :), i.e. the vast majority of imports do not have Clojure dependencies

10:07 cemerick: lol

10:07 Hey, go big or go home, y'know?

10:08 :-)

10:08 interestingly, the vast majority of our imports *are* to clojure-generated classes

10:08 (outside of core java libs)

10:10 rhickey: cemerick: I think that's great, but I'm not sure you are going to get around dependency analysis, nor is it necessarily hard (volunteers welcome)

10:11 cemerick: well, you'd know better than I. I'd go do it, but I honestly wouldn't know where to start.

10:12 rhickey: would true dependency analysis solve any problems that wouldn't (functionally) be solved by being dumb about it and doing the fail-safe requires?

10:30 valebedev__: join #couchdb

10:49 Chouser: there's currently no way for a macro from a namespace X to refer to a var X/foo when used in namespace Y unless X/foo is fully public, right?

10:50 jbondeson: heh, i just ran into that this morning.

10:51 WizardofWestmarc: can you wrap the macro's code in an in-ns block?

10:51 jbondeson: you'd break user code like that

10:51 WizardofWestmarc: hm, good point

10:52 Chouser: I've run into it before, but the var I've got right now would be particularly bad for users to muck around with.

10:53 well, in-ns wouldn't work because the expression containing it has to be eval'ed before it take effect (on the following expression)

10:53 binding+eval would do it, but of course that's lousy

10:54 ayrnieu: depending on foo , you can embed it into your macroexpansion. (def x (ref 0)) (defmacro on-x [f] `(f @~x))

10:54 macroexpands to: (foo/f (clojure.core/deref #<Ref clojure.lang.Ref@9a6cd4>))

10:54 Chouser: ayrnieu: ooh.. hm...

10:55 oh, but that won't 'read'

10:55 jbondeson: you wouldn't be able to expand that if the ref were private though, right?

10:56 even multiple layers of macros all evaluate at read time of the "caller", right?

10:56 Chouser: you get "Can't embed object in code" because you can't print and then read an object reference like that

10:58 In this case I'd probably be content with a var that was public but not referred by default by 'use'.

11:08 cgrand: Chouser: @#'ns/private-var ?

11:12 Chouser: cgrand: ok! thanks.

11:24 cemerick: it would be *really* nice if some kind of 'friend'-level access were available.

11:24 Probably more trouble than it's worth, I guess.

11:25 Chouser: everyone that knows how to @#' is my friend.

11:26 jbondeson: heh

11:27 ayrnieu: (lib.chouser/THIS-CODE-WILL-BREAK a) ;;; it's just the lib author's 'scary' name. Stop coming to me about this! --ayr

11:28 Chouser: :-)

11:31 duck1123: @#' would allow you dereference a var that is named by the results of a form?

11:35 cemerick: Chouser: indeed, but something that would operate through refer and friends would be pleasant in some circumstances

11:37 e.g. right now, I'm making public a variety of fns that were being shared by two gen-classed libs, which are now in separate namespaces -- defining those fns' vars as friendly with just that other lib would be nifty (so I don't have to scatter the @#' line-noise all over the place)

11:42 jbondeson: ok, i'm going to ask a question that may be dumb, but what is the reason that Ref is not considered a Class for use in 'isa?', but you can identify one with (instance? clojure.lang.IRef reference)?

11:43 cgrand: cemerick: what about putting them in a third namespace and warn users to not use this lib?

11:44 cemerick: cgrand: yeah, I may do that. Right now, I just want to get all of our stuff ported to post-AOT clojure. Then I'll tidy shop. :-)

11:49 Chouser: (defn get-friends [] (doseq [s '[var1 var2 var3]] (.refer *ns* s (resolve s))))

11:50 I think that ought to work, but instead I get a busy infinite loop. :-/

11:50 jbondeson: Class is a final class -- no derived classes allowed.

11:51 ,(instance? Class clojure.lang.Ref)

11:51 clojurebot: true

11:51 jbondeson: ah-ha

11:51 see knew it was going to be a dumb question.

11:52 Chouser: not dumb. The Class class is meta in a direction that's frequently confusing.

11:56 hm, clojure's tiny amount of syntax is biting me

11:57 I want to write a macro foo that allows me to say: {:a 1 :b 2 (foo 3 4)}

11:57 hiredman: erm

11:58 I don't see how that could ever work

11:58 functions/macros result in one value

11:58 ayrnieu: ,(let [foo #(do {%1 %2})] (conj {1 2 3 4} (foo 3 5)))

11:58 clojurebot: {1 2, 3 5}

11:59 hiredman: a map needs pairs of key -> value mappings

11:59 Chouser: yeah, the user will have to wrap the whole {} in something, either conj or the macro call itself.

12:00 hiredman: oh, you're right. it wouldn't even work in a list because I want multiple return forms.

12:00 so its a weakness of macros, not anything to do with Clojure synatx.

12:01 hiredman: ...

12:03 ayrnieu: CL discards the second value in (defmacro x (a b) (values `(foo ,a) `(bar ,b))) , too. I wonder how robust the idea is.

12:07 LordOfTheNoobs: Chouser: what were you wanting the resulting form to look like?

12:08 hiredman: well, I assume he wanted a valid map

12:08 Chouser: {:a 1 :b 2 :fookey (+ 3 4)} for example

12:09 ayrnieu: (defmacro multiple-value-macro [x y] (atom [:fookey `(+ ~x ~y)])), {:a 1 :b 2 (multiple-value-macro 3 4)} => {:a 1 :b 2 :fookey (+ 3 4)} ;; doesn't work, of course.

12:12 Chouser: ayrnieu: if your mvm were made to work, though, *then* we'd have a syntax problem.

12:12 Clojure's reader wants an even number of things in {}

12:13 ayrnieu: that's an even number of things; (atom [a b]) => a b

12:14 Chouser: but not at the read time of {:a 1 :b 2 (multiple-value-macro 3 4)}

12:14 ayrnieu: in the hypothetical atoms-from-macros-are-treated-specially-world , which is compatible with ours in that macros can't return such things.

12:15 hm.

12:17 Chouser: heh, you can use 'binding' on private vars

12:19 hiredman: it's a feature!

12:21 Chouser: one of those unusual write-only constructs.

12:30 technomancy: it says here that set! only works on java fields, agents, and refs: http://clojure.org/java_interop#set

12:30 but I'm using it on a thread-local var

12:33 zakwilson: technomancy: Note - you cannot assign to function params or local bindings. Only Java fields, VARS, Refs and Agents are mutable in Clojure. (emphisis added)

12:34 technomancy: zakwilson: yes... my brain is not turned on.

12:34 I read that as "java field vars"

12:45 so does CL avoid the use of brackets because they wanted to reserve them for M-expressions? http://en.wikipedia.org/wiki/M-expression

12:48 it's really weird to read about how people used to think M-expressions were the future.

12:52 jbondeson: is there any easier way to deal with gen-class objects than having to do a compile every time you make a change?

12:52 gnuvince: technomancy: in a sense, every other language adopted M-expressions :)

12:52 hiredman: I think CL avoids using brackets for religious reasons

12:53 jbondeson: for changes like adding a method you have to recompile, but for changes to existing methods that don't change their signature, I don't think you need to recompile

12:53 Chouser: jbondeson: you should only have to recompile if you change the actual args of the gen-class macro

12:53 hiredman: a compiled class is just stubs that dispatch to clojure functions

12:54 jbondeson: sweet.

12:54 Chouser: you can even add new override fns and stuff to the namespace without recompile

12:54 zakwilson: I think CL avoids the use of brackets to make them available to the programmer for arbitrary purposes.

12:55 BigTom: Hi technomancy

12:55 technomancy: zakwilson: purposes including adopting m-expressions, no doubt. =)

12:55 BigTom: hello

12:55 BigTom: technomancy: I am afraid I didn't use your Slime script in the end

12:55 technomancy: o rly?

12:55 BigTom: technomancy: I have put Slime on the backburner until I am better at emacs

12:56 zakwilson: I doubt it, technomancy. I think by the time CL came out, hardly anybody was seriously considering using M-expressions.

12:56 technomancy: were you running into problems?

12:56 jbondeson: i suppose i could also test with a proxy if i want to play in the repl

12:57 technomancy: zakwilson: yeah, but they have this thing about leaving peoples' options open. I dunno; mostly joking though.

12:57 zakwilson: Lisps in general aim to leave options open - Clojure included.

12:57 BigTom: There is just friction everwhere (mostly me not knowing my way round)

12:58 so I'll stick with inferior lisp until I am comfortable with emacs

12:58 Then I'll have another go

12:58 just wanted to say thanks for the patient help over the last few days

12:58 zakwilson: I've seen brackets used in CL for delimiting sexps that were translated by a macro in to SQL statements (CLSQL), for array literals and for Arc-style function literal shorthand.

12:59 technomancy: BigTom: no problem. do you know about the Emacs PeepCode?

12:59 BigTom: nope

13:00 technomancy: it's a screencast you can buy for learning Emacs: http://peepcode.com/products/meet-emacs

13:00 BigTom: technomancy: Emacs is this vast uncharted continent of obscure functionality ;-)

13:00 technomancy: ah, I'll have a look

13:00 jbondeson: it's not obscure, it just wasn't *meant* for you! ;)

13:00 Kerris7: "It's not you, it's just Emacs"

13:01 technomancy: BigTom: people have told me they find it helpful. =)

13:01 BigTom: funny thing was that I had no trouble with Emacs and erlang, I think its a serious case of running before I can walk

13:01 technomancy: well Emacs and Erlang have had more time to get to know each other I suppose.

13:02 zakwilson: I think Emacs suffers from some dated conventions and could use a more modern replacement... but I'm not holding by breath for that. I expect to be using Emacs in ten years.

13:02 jbondeson: never used the erlang mode, but it could have to do with how much the mode alters emacs

13:02 technomancy: zakwilson: a lot of the cruft is going to be targeted in the next release: adding lexical scope and coroutines

13:02 jbondeson: most of the lisp-emacs modes embrace emacs

13:03 zakwilson: Lexical scope? Finally? Yay!

13:04 technomancy: zakwilson: optional lexical scope of course; can't go around breaking all extant code. but it's a step in the right direction.

13:04 and it makes threading possible

13:04 BigTom: I have to admit my Java side is very excited that the intellij guys are taking over the clojure plugin

13:04 Intellij is a very impressive piece of kit

13:04 duck1123: I hate doing something intensive in emacs, only to have it mess up my ERC buffers

13:04 zakwilson: Isn't somebody working on a Clojure IDE in Clojure?

13:05 hiredman: clojurebot: textjure?

13:05 clojurebot: No entiendo

13:05 zakwilson: Yes, that name sounds familiar.

13:05 jbondeson: beat the bot until it remembers.

13:06 technomancy: zakwilson: it's more than an IDE though, it's a structure editor

13:06 so you're operating directly on data structures rather than editing the textual representation of the code.

13:06 that's what they tell me anyway.

13:06 BigTom: If you like that sort of thing

13:06 Which I do

13:07 zakwilson: Now I have to go download the bloody thing and see what it's all about.

13:07 BigTom: What would be cool would be a clojure equivalent of Pythons IDLE

13:07 duck1123: I wonder if you could convert clojure code to xml, edit it in a xml structure editor, then transform it back into clj code

13:07 Chousuke: yes :P

13:08 the question is, how easily

13:08 jbondeson: not really, because technically with macros you can modify to be less s-exp-y

13:08 technomancy: you could compile it to X#: http://xsharp.org =)

13:08 duck1123: the trick would be to have enough structure to capture everything, without it getting in the way of the code editing

13:09 I haven't looked into X# too much, but XMLProc is a pretty cool spec, I used to work with it's precursor XPL quite a bit

13:10 technomancy: X# is hilarious

13:10 jbondeson: no, no it's not...

13:10 you shouldn't encourage them.

13:10 technomancy: it's like someone interpreted Greenspun's Tenth Law as Best Practices

13:11 duck1123: "hmm... implement half of lisp? sure, I'll give it a try"

13:11 danm__: I'm not sure why anyone would want something like X#

13:11 jbondeson: I can just see how the thought process went for those people

13:11 danm__: but I suppose differences between people make the world work

13:12 WizardofWestmarc: ungh, X#

13:12 I hoped it was a joke when I originally heard about it

13:12 jbondeson: "I don't understand XSL, so how do I make a different XML language that has all the downsides of being in XML, and non of the upsides of XSL?"

13:13 WizardofWestmarc: there are upsides to xslt besides not being compiled?

13:13 jbondeson: now now

13:13 duck1123: xslt is actually a quite powerful language. (if you're using XPath 2.0)

13:14 it's no lisp, but not far from it

13:14 jbondeson: XSL 2.0 is fine, but people, and by people I mean CRUD developers, couldn't understand it, so they came up with XQuery, and now this bastardization X#

13:14 technomancy: if only you could write xslt using M-expressions.

13:15 * jbondeson beats technomancy with a stale fish

13:17 cemerick: rhickey_: do you have any issues applying patches emitted by git-svn?

13:26 * zakwilson can't get textjure to compile. It refers to RT/ROOT_CLASSLOADER, which doesn't seem to exist.

13:27 hiredman: ah

13:27 this is also an issue with old swank and new clojure

13:27 basically the field became private

13:27 and the solution is somewhere in the irc logs

13:28 Chouser: cemerick: that's how i generate all my patches

13:28 cemerick: either "git diff" or "git show"

13:29 textjure's not set up to compile -- just run it as a script

13:29 and it's super pre-beta, but if you want to actually try to use it, you'll want karmazilla's version

13:31 cemerick: Chouser: OK, thanks. I was worried about the svn rev #'s.

13:32 Chouser: it's just a raw diff file, right? so git or svn rev numbers aren't really involved.

13:32 beatbox: if you want to do image analysis in clojure, which libs?

13:33 colt for linear algebra, jung for graphs, but what for manipulating and parsing images?

13:34 ayrnieu: I'm not an experienced java programmer, so I'd ask in ##java if I didn't like the hits from 'java image analysis' (ImageJ, etc.) You can easily use these in clojure.

13:36 albino: I thought the conclusion was jai

13:47 leafw: beatbox: Fiji at http://pacific.mpi-cbg.de

13:51 zakwilson: textjure has an interesting ability to recurse through every subdirectory and open every file when given a directory to switch to.

13:52 Fortunately, it seems to have the ability to handle hundreds of open files without complaint or slowdown.

14:26 Chousuke: zakwilson: I remember kotarak complaining about it lacking the ability to *close* files, but that may have been fixed.

14:36 zakwilson: Chousuke: It can close files, but the help doesn't mention a quit command (and Ctrl-Q doesn't do it)

14:37 hiredman: Alt-F4

14:37 zakwilson: Nor does closing the window terminate the JVM.

14:37 hiredman: Ctrl-C

14:38 zakwilson: Hmm... that time it did terminate.

14:39 Maybe it was taking its time due to my hundreds of open files.

14:39 Cark: mhh did i hear textjure ?

14:39 zakwilson: Yes. I was trying it out.

14:40 Cark: did they make any progress on it ?

14:40 zakwilson: I cannot answer your question; I do not have a reference point for defining what progress means.

14:41 Cark: i've been relentlessly pestering chouser with stupid java interop questions in order to prevent any progress on that front

14:42 gnuvince: hahaha

14:44 zakwilson: Cark: I can't tell you if it's worked. I have only used one version of textjure and have not followed its history. It appears to have a working editor and REPL, and it appears to be fairly unfinish.d

14:49 cemerick: rhickey_: do you have any AOT-related changes coming down the pike that would bring down the size on disk of the generated classfiles?

14:51 lpetit: Hello

14:53 danlarkin: lpetit: hi

14:53 lpetit: rhickey_: sorry for cross posting here what I've already done in the group, but I have a close window to work on clojuredev this weekend, and I would like to know if it is worth of me to create a patch for clojure.lang.Compiler.writeClassFile(), as explained in the e-mail

14:54 I wanted to say a short window, of course ... please excuse my english

15:08 gnuvince: To convert a signed byte to a short (so that I can have the unsigned value if Java supported that), do I use (bit-and x (short 0xff)) or is there a better way?

15:15 zakwilson: gnuvince: that appears to return a java.lang.Integer. I think what you want is (short (bit-and x 0xff))

15:15 gnuvince: ,(class (bit-and (byte 128) (short 0xff)))

15:15 clojurebot: java.lang.Integer

15:15 gnuvince: hmmm

15:15 zakwilson: The bitwise functions don't (currently) work with primitives.

15:16 gnuvince: ,(short (bit-and (byte 128) 0xff))

15:16 clojurebot: 128

15:16 gnuvince: cool

15:16 thanks zakwilson

15:16 zakwilson: No problem.

15:19 gnuvince: Too bad that Java doesn't have signed/unsigned though :-/

15:20 That would've saved me some trouble

15:42 jbondeson: ok, swing events are just dumb.

15:43 hiredman: eh?

15:44 jbondeson: just trying to do some watching of changes in a text field, and it took me way to long to figure that out. JTextField.getDocument().addDocumentListener(...)

15:44 * hiredman just read the GUI section in java concurrency in practice a few nights ago

15:44 jbondeson: addActionListener only fires when you press Enter, which is just crazy

15:44 hiredman: oh, well, that is just Java for you

15:45 jbondeson: makes it tough to make a uniform event listening library when you have to addActionListener isn't actually what you want

15:46 karmazilla: Swing is like an unwanted child

15:46 jbondeson: in what world does [Enter] triggering an event make sense? the only event anyone cares about with a text field is TEXT CHANGED!

15:46 WizardofWestmarc: that's mother drank heavily while carrying it to term

15:46 hiredman: and yet awt shows no love, so swing it is

15:47 WizardofWestmarc: whenever I get around to UI stuff I'm probably going to go down the QT road

15:47 ayrnieu: jbondeson, have you ever logged into a web page by typing 'username', hitting tab, typing 'password', and then hitting enter?

15:47 WizardofWestmarc: last time I used swing I thought I was going to lose my mind

15:47 mofmog: i'm writing a little program that does A* search and although not necessarily to do with clojure i was wondering you guys could help...

15:47 walters: ayrnieu: we should make the firefox patch to remove it from javascript for his computer and see if he changes his mind about an activation signal =)

15:47 jbondeson: ayrnieu: i would expect the [Enter] to trigger a button...

15:48 karmazilla: but input focus is on the textfield

15:48 technomancy: enter triggers on input elements. textareas are not inputs, but text fields are

15:48 jbondeson: yes but in most sane environments you have have forms that have key preview...

15:49 mofmog: it's a* for essentially the travelling salesman problem on a grid, and i had a heuristic that used the minimum spanning tree, but it turns out it's not a consistent heuristic. for some reason, replacing the manhattan distance function used to find the edge cost between edges with a function that calculates euclidean distance makes it consistent

15:49 i dont know if that's necessarily true.. hrm

15:50 it should be at least admissible since euclidean distances are less than or equal to the equivalent Manhattan distance

15:50 * karmazilla 's head explodes

15:53 jbondeson: mofmog: a quick look at manhattan distance looks like it's not monotonically decreasing.

15:53 mofmog: yeah exactly

15:53 jbondeson: that's one of the requirements for A*

15:54 mofmog: well for a graph search at least

15:54 that's exactly my problem, it isn't consistent, but euclidean distances makes it consistent, even though the search space is on a grid

15:54 not "makes" but "makes it seem"

15:55 jbondeson: What are you seeing with the A* algorithm with manhattan?

15:56 you said it isn't "consistent", what exactly do you mean by that?

15:56 mofmog: it's not monotonic

15:56 jbondeson: it's evaluating nodes that should be disqualified?

15:56 mofmog: going off of norvig's terminology

15:56 no i'm saying that f(n) = g(n) + h(n) is not monotonic

15:56 g(n) always grows by one, so essentially h(n')-h(n) is not <= 1

16:12 scottj: Should (rational? 0.5) return true?

16:13 ayrnieu: (rationalp 0.5) evaluates to nil in CL, too.

16:13 gnuvince: scottj: 0.5 is not a rational, it's a double. 1/2 is a rational

16:13 ,(rational? 1/2)

16:13 clojurebot: true

16:14 scottj: gnuvince: I think that's what ratio? is for

16:15 ayrnieu: ,[(ratio? 1/1) (rational? 1/1)]

16:15 clojurebot: [false true]

16:17 scottj: rational? "returns true if n is a rational number." 0.5 is a rational number.

16:17 jbondeson: ,(rationalize 0.5)

16:17 clojurebot: 1/2

16:18 ayrnieu: It is a rational number with one set of terms. It is not (or integer? ratio?), in the relevant set.

16:18 gnuvince: (doc ratio?)

16:18 clojurebot: Returns true if n is a Ratio; arglists ([n])

16:18 gnuvince: (doc rational?)

16:19 hiredman: huh

16:20 clojurebot NPE'ed on that

16:20 ,(doc rational?)

16:20 clojurebot: "([n]); "

16:20 hiredman: Nice

16:20 scottj: it's messed up in the repl also

16:20 durka42: it has no doc

16:21 scottj: it looks like it does in the source

16:22 durka42: yeah, it does

16:22 scottj: anyway, I think that doc string should be changed if it's going to test something other than what's normally meant by "rational number"

16:23 ayrnieu: ,(.setMeta #'rational? (assoc (meta #'rational? :doc "(or (integer? n) (ratio? n) (decimal? n))"))

16:23 clojurebot: Eval-in-box threw an exception:EOF while reading

16:23 ayrnieu: ,(.setMeta #'rational? (assoc (meta #'rational?) :doc "(or (integer? n) (ratio? n) (decimal? n))"))

16:23 clojurebot: nil

16:23 ayrnieu: it doesn't have documentation in the source. It has a string that is thrown away.

16:23 jbondeson: except for one problem scott, EVERY floating point number is a rational number.

16:23 ayrnieu: scottj, computer types are metaphorical.

16:23 durka42: oh, hey

16:24 yeah, what ayrnieu said

16:24 jbondeson: ,(double 1/3)

16:24 clojurebot: 0.3333333333333333

16:24 jbondeson: you can rationalize any floating point number, because by definition they terminate

16:24 durka42: that seems like it should be on the issues page

16:24 jbondeson: they are of fixed precision.

16:24 durka42: since it's such a trivial problem

16:24 ayrnieu: oh oh, that's a rational number. That's 3333333333333333/1000000000000000

16:24 jbondeson: yes, exactly the point

16:25 ayrnieu: (it's a rational number anyway, because it's repeating)

16:25 mofmog: ,(double 234213/2343)

16:25 clojurebot: 99.9628681177977

16:25 jbondeson: true, but you can also do it with irrational numbers

16:25 mofmog: ,pi

16:25 clojurebot: java.lang.Exception: Unable to resolve symbol: pi in this context

16:25 jbondeson: it's just impossible to show =P

16:26 durka42: ,Math/PI

16:26 clojurebot: 3.141592653589793

16:26 durka42: ,(rationalize Math/PI)

16:26 clojurebot: 3141592653589793/1000000000000000

16:26 mofmog: oh there it is

16:26 durka42: man we have been trying to do that for how many thousand years?

16:26 jbondeson: pythagoras would be proud

16:26 ayrnieu: scottj - there's some thought in http://www.lispworks.com/documentation/HyperSpec/Body/c_number.htm

16:26 durka42: clojurebot just one-upped everyone

16:27 mofmog: pythagoras didn't have thinking machines

16:27 hiredman: then he should have built some

16:27 mofmog: and jump start the inevitable war on thinking machines by >2000 years? I think not

16:29 jbondeson: does clojure bot have access to contrib?

16:30 hiredman: uh, yes

16:30 accidently

16:30 jbondeson: ,(clojure.contrib.math/sqrt 2)

16:30 clojurebot: java.lang.ClassNotFoundException: clojure.contrib.math

16:30 hiredman: hmmm

16:30 WizardofWestmarc: you probably need to import it first

16:30 Chouser: ,(use clojure.contrib.math)

16:30 clojurebot: java.lang.ClassNotFoundException: clojure.contrib.math

16:30 hiredman: I thought he did

16:30 ayrnieu: ,(use 'clojure.contrib.math)

16:30 clojurebot: java.io.FileNotFoundException: Could not locate clojure/contrib/math__init.class or clojure/contrib/math.clj on classpath:

16:31 jbondeson: clojurebot: you are a failure!

16:31 clojurebot: Excuse me?

16:31 ayrnieu: ,(Math/sqrt 2)

16:31 clojurebot: 1.4142135623730951

16:31 jbondeson: cheating

16:32 hiredman: /home/hiredman/.jars/clojure-contrib.jar <-- from clojurebot's classpath

16:32 I think that is just whatever clojure-contrib ships with ring

16:32 jbondeson: ,(rationalize (Math/sqrt 2))

16:32 clojurebot: 14142135623730951/10000000000000000

16:32 technomancy: clojurebot uses ring?

16:33 or that's just where you got your copy from?

16:33 hiredman: no

16:33 I dump jars in .jars

16:33 technomancy: right, sure

16:33 ayrnieu: ,(filter #(.contains % "clojure") (.split (System/getProperty "java.class.path") ":"))

16:33 clojurebot: java.security.AccessControlException: access denied (java.util.PropertyPermission java.class.path read)

16:33 hiredman: so I took all the jars that came with ring and dumped them in there

16:34 ("/home/hiredman/.jars/clojure.jar" "/home/hiredman/.jars/clojure-contrib.jar" "/home/hiredman/.jars/clojureql.jar" "/home/hiredman/.jars/clojure-json.jar" "./clojurebot/")

16:34 clojurebot does use clojure-json

16:34 well

16:35 the google search and translate modules/plugins/whathaveyou do

16:35 Raynes: Well. Don't you just hate it when you write a function only to look like an idiot 2 days later when someone throws the same (but improved) version in your face :|

16:35 danlarkin: Raynes: I love it!

16:36 Raynes: Right out of the standard library.

16:36 jbondeson: oh, heh, that's slightly different

16:36 Raynes: :|

16:36 jbondeson: i've rewritten my fair share of the core api

17:19 Lau_of_DK: Good evening all

17:21 WizardofWestmarc: heya Lau

17:22 danlarkin: Hi Lau!

17:41 Raynes: Good evening Lau_of_DK. Sorry for the extremely delayed reply.

17:42 gnuvince_: Hi all

17:42 c|p: hey

17:43 Raynes: hi gnuvince

17:43 Lau_of_DK: No worries Raynes, its late :) here...

17:43 So, anyone brewing something interesting in Clojure for the weekend ?

17:43 Raynes: It's 4:43, pm here. :D

17:44 Lau_of_DK: oh... its 17 minz to midnight here

17:46 Anyone using this streams branch regularily ?

17:47 Chouser: I think I'll have my condition/restart thing ready for people to try out tonight.

17:47 called error-kit for now, because I'm just flat out lousy with names

17:47 Lau_of_DK: Cool

17:47 Is it on Github yet ?

17:48 jbondeson: Chouser: that based off the main branch?

17:48 Chouser: no, it'll go straight into contrib

17:48 Lau_of_DK: Ok

17:48 Chouser: yes, I'm still using svn trunk HEAD.

17:48 I think its got nil punning in there, but I'm not sure. :-)

17:49 Lau_of_DK: Ive got to hit the sack, its been a looong day, but I'll look forward to seeing your code when I wake up Chris - Good night to you all

17:49 (oh and danlarkin, could you hurry and wrap 'barkin larkin' up soon?)

17:51 danlarkin: Aw he's gone

17:51 I'm working on it now, Lau!

17:51 jbondeson: wish there was a way to do multi-method despatches on available methods...

17:51 course that would be slow as dirt

17:52 durka42: eh?

17:53 jbondeson: The presense of a certain method signature to determine the defmethod to use.

17:53 swing does have an interface for addActionListener

17:53 unless i'm crazy (totally possible)

17:58 does -> doesn't

17:58 i have no idea why i love leaving off the end of contractions...

18:04 lpetit: Hi Chouser

18:04 Chouser: lpetit: hi

18:05 lpetit: Sorry for cross posting here what I've already done in the group, but I don't have a lot of time to spend (alas!) on clojuredev this weekend, and I would like to know if you think there is a chance that the patch for clojure.lang.Compiler.writeClassFile(), as explained in the e-mail, will be accepted

18:05 If yes, then I'll take time to work on it. If no, then I'll do something else :-(

18:06 Chouser: I'm afraid I'm no position to make such judgements, even on issues I'm pretty familiar with.

18:07 I understand that it can sometimes be frustrating when a project seems to be blocked waiting for a decision from Rich and no decision appears to be forthcoming.

18:07 All I can recommend is to adjust your project to allow you to move forward until a judgement has been made.

18:09 lpetit: Do you think there's something I could do better myself clearer ? Maybe my e-mails are too long, maybe the tone of my e-mails is not appropriate ... ?

18:10 Oh, the project is not blocked. I've currently hacked the embedded clojure in clojuredev. Works like a charm.

18:10 But it's not satisfying in the long run, of course.

18:16 Chouser: Mainly I'd recommend patience.

18:17 Give it a week or so, and if you still haven't heard anything, bring it up again.

18:21 lpetit: Chouser: Yeah, you're right. thanks

18:27 drewolson: anyone out there using gorilla>

18:28 durka42: i am

18:29 drewolson: durka42: i recently started getting an error where gorilla is looking for gatekeeper.vim

18:29 which i don't seem to have. any idea what this is?

18:30 durka42: really

18:30 i don't know

18:30 did you switch branches?

18:30 i know kotarak is working on some new stuff in the nails branch

18:31 drewolson: durka42: i don't believe so. i'm pulling from the standard bitbucked branch

18:31 i completely crashes vim for me at this point, can't use it

18:31 durka42: is this it?

18:31 http://www.mail-archive.com/vim_dev@googlegroups.com/msg02823.html

18:31 doesn't sound connected to gorilla, though

18:32 c|p: can anyone recommend a book in which the main point of focus is relative to functional programming styles/techniques/etc?

18:32 im heading up to new jersey tomorrow and could use something to read

18:32 drewolson: durka42: all i know is if i add gorilla.vim , vim crashes. if i run it with -V20, i see that the errors are related to attempting to use gatekeeper

18:32 not sure why

18:33 durka42: yeah, i'm not sure, sorry

18:33 i'm rather new to vim too

18:34 walters: c|p: perhaps http://www.pragprog.com/titles/shcloj/programming-clojure

18:35 technomancy: c|p: I don't know if there's anything that targets lisp. I'm sure you could find something on haskell or erlang, but you'd have to wade through a lot of unrelated content

18:35 c|p: walters is that mostly clojure specifically? i would like something more generalized...sort of just concept related

18:35 technomancy, yeah, im looking about on google

18:35 only found haskell related books so far

18:36 ah, thank you google http://books.google.com/books?ei=xciMSaquBIG4twf89uiGCw&ct=title&rview=1&q=functional+programming&btnG=Search+Books

18:36 BigTom: clp: Okasaki. Purely Functional Data Structures?

18:37 technomancy: c|p: this looks like fun: http://learnyouahaskell.com/ =)

18:37 BigTom: clp: Haskel I think

18:37 drewolson: clp: real world haskell was very good

18:37 c|p: BigTom im just more curious about concepts. i'll tell you right now i favor lisps over haskell ;)

18:37 im just not very used to functional programming

18:38 although, i might go with the book walters suggested

18:39 but im not too sure if its worth it, clojure seems to be "evolving" quite rapidly

18:39 BigTom: How about the ML family?

18:39 Chrononaut: On Lisp is good for understanding macros (the pdf is free as well)

18:39 BigTom: There is "The Little MLer"

18:39 technomancy: c|p: if you haven't read the book on clojure, that's the obvious place to start

18:39 it's quite good

18:39 c|p: righto

18:39 technomancy: c|p: also: reading code can be just as instructive as reading prose, so browse the contrib library

18:40 c|p: just wanted some recommendations

18:40 aye technomancy

18:40 BigTom: Stu Halloway's book is good and it has a functional chapter now

18:40 c|p: im going to drop by barne's and noble to check out what they have

18:40 (in the morning)

18:40 BigTom: oops, I see technomancy beat me to it

18:41 hiredman: ugh

18:41 technomancy: c|p: I doubt you'll find anything there

18:41 c|p: Pub. Date: April 28, 2009

18:41 heh, looks like they wont have it

18:41 technomancy: possibly erlang if you're lucky

18:41 c|p: technomancy: yeah, im not expecting much

18:42 hiredman: the local barnes and noble used have a "computer science" shelf, it was full of "excel for dummies" books

18:42 c|p: heh

18:42 well, mine is a bit better than that

18:42 hiredman: like the label on the top of the shelf was "Computer Science"

18:42 c|p: i might get lucky and they could have something useful

18:43 hiredman: the books where all MS-Office related

18:43 I saw real world haskell on the programming shelf at b&n the other day

18:43 they had three copies

18:43 technomancy: wow; nice

18:43 hiredman: technomancy: the one at the northgate mall

18:44 technomancy: hiredman: wonder how long before Programming Clojure shows up there. =)

18:44 hiredman: :)

18:44 c|p: right well

18:44 to all of you that gave me some info, thanks

18:44 back to idling

18:46 hiredman: I was surprised, java has one shelf

18:46 that is it

18:46 technomancy: Powell's Tech in Portland is phenomenal. They had like five copies of the Little Schemer

18:46 hiredman: out of four six foot (I guess) sets of bookshelves

18:46 technomancy: three shelves of ruby

18:47 hiredman: yeah

18:47 technomancy: and a little "History of Computing" museum in the back.

18:47 walters: well, the web is really dominant in computing now, and dynamic languages make more sense for web frontends. Java is probably going to drop more towards the C++ domain

18:49 hiredman: the goodwill has a number of (outdated) java books

18:50 BigTom: are there any in-date Java books?

18:51 c|p: head first java is 3rd edition now

18:51 technomancy: hiredman: it's hilarious what kind of stuff you can find at used bookstores... high-priced assembly manuals for 70s-era mainframes always give me a kick.

18:51 c|p: i tihkn

18:51 not sure

18:51 2nd edition was pretty much 5.0

18:52 BigTom: The problem with a lot of Java is that it isn't easy to knock out small stuff so the books are all about frameworks and big stuff

18:52 which doesn't sell in bookshops

18:53 technomancy: "Java in a Nutshell" is pretty huge.

18:53 start to wonder what kind of nuts they use as reference

18:53 hiredman: technomancy: I got a UNIX System V manual the other day

18:53 technomancy: nice

18:53 BigTom: Java in a coconut shell :=)

18:53 technomancy: hiredman: I'm holding out for a PDP manual

18:53 BigTom: I got Hoare's CSP book

18:54 lpetit: Concerning java, there's not a lot of book I would recommend. For quick starters, any book will do. For more in-depth, then I'd recommend "Effective Java 2d edition" from Josch Bloch

18:54 hiredman: and a bunch of intel ia32 instruction set books

18:54 c|p: i have a new-ish condition windows 98 manual, anyone want it :)

18:54 ill even throw in the disk!

18:54 Spreadsheet: me

18:54 * technomancy found an old Mosaic CD-ROM a few months ago

18:54 c|p: oh, that reminds me

18:54 i have an apple ii in the attic as well

18:54 technomancy: nice

18:54 Spreadsheet: Chousuke: hello!

18:55 c|p: can you IRC on it?

18:55 c|p: i dont know, it is my dads

18:55 i havent ever really used it

18:55 Spreadsheet: oh

18:55 c|p: he got one around the time it came out

18:55 lpetit: And concerning some higher level book on object orientation, not too tied to a language implementation, I would recommend trying to get the foundational book for Eiffel by Bertrand Meyer

18:56 hiredman: someone happened to paste a link to a webpage version of java concurrency in practice on some chinese or japanese website to the google group a while back :P

18:57 lpetit: Object-Oriented Software Construction ( http://en.wikipedia.org/wiki/Object-Oriented_Software_Construction ). Takes time to explain the reasons that lead to object orientation (we should really say class orientation, when we speak of java).

18:59 I found this book very interesting. Very easy to understand, not too deep in the technical aspects of a specific language.

18:59 I wonder if there is the same think for the "functional" approach. The Little Schemer was interesting, but very very "hands on" ...

19:00 candera: Is it possible to "rebind" a java method? I'd like to be able to either add methods to a class or redirect existing methods to my own code. I.e. make (. o foobar) wind up in my Clojure implementation of foobar, for an existing Java type.

19:01 I'm guessing the answer is "no", but Clojure often surprises...

19:02 Chouser: if you used genclass to create the Java class, you can swap in new method implementations

19:02 hiredman: maybe subclass the Java class?

19:03 ayrnieu: But you can't do this in general. You can't subclass String, for instance.

19:03 erohtar: does anyone know how i can find the filepath of a loaded clojure script?

19:04 candera: OK, so I guess I need to study genclass to understand that approach better (subclassing is not really an option), but really what I'm looking for is a way to implement something like Ruby's open classes, where I can rip off existing methods and replace them with my own, or add totally new ones. Obviously it wouldn't survive the trip across the interop barrier, but I'm fine with that.

19:05 technomancy: erohtar: should be *file*

19:05 ayrnieu: erohtar - a #! /usr/bin/env clj script will have the path in (first *command-lineargs*)

19:05 technomancy: ~*file*

19:05 clojurebot: Huh?

19:06 erohtar: thanks!

19:06 ayrnieu: relative in (first *command-line-args*), absolute (but not necessarily 'clean') in *file*

19:11 lpetit: bye folks

19:15 candera: So, having read the gen-class docs and a few other Google hits, it's not clear to me that I could use it to do what I'm asking about. As you say, it would work in the case where I've created the class, but I'm after being able to replace methods on (e.g) java.io.File.

19:50 bakkdoor: hi

19:51 is there any wrapper for swing in clojure? or something similar, like a library to do gui stuff "the clojure way"?

19:51 (whatever that even means)

19:54 or if not, is there any interest in something like this?

20:09 Chouser: bakkdoor: there's clojure.contrib.miglayout

20:10 bakkdoor: there are a couple mentions of swing on http://clojure.org/libraries

20:20 danlarkin: ,(keyword 1)

20:20 clojurebot: java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String

20:20 danlarkin: that seem silly to me

20:20 Chouser: ,(keyword "1")

20:20 clojurebot: :1

20:21 ayrnieu: ,(-> 1 str keyword)

20:21 clojurebot: :1

20:21 danlarkin: but then I have to call str on my input in addition to calling keyword on it

20:21 oh well, I guess it's not the end of the world

20:22 Chouser: yeah, it could call str on both args

20:22 ayrnieu: ,(keyword (ref 0))

20:22 clojurebot: java.lang.ClassCastException: clojure.lang.Ref cannot be cast to java.lang.String

20:22 Chouser: except that I'd like keyword to take a Symbol as well

20:22 ayrnieu: aw, more work?

20:23 Chouser: (keyword 'foo/bar) should produce :foo/bar

20:23 ayrnieu: well, (keyword (name sym)) helps by reminding you that 'name' was a poor choice of parameter.

20:23 bakkdoor: Chouser: hm miglayout isn't really what i want, but alright. thanks :)

20:23 danlarkin: it should take any Named I guess?

20:23 Chouser: bakkdoor: never used it, just mentioning what I'd heard of.

20:24 and I wish Vars were Named

20:24 ayrnieu: the language actually isn't a carpet that you can sweep complexity under without cost.

20:24 Chouser: ...while we're listing trivial changes...

20:28 ayrnieu: ,(-> #'+ meta :name name keyword)

20:28 clojurebot: :+

20:28 Chouser: ,(-> #'+ meta :ns str keyword)

20:28 clojurebot: :clojure.core

20:29 ayrnieu: ,(-> "+" symbol resolve meta :name name keyword)

20:29 clojurebot: :+

20:30 Chouser: ,((fn [v] (apply symbol (map #(str (% ^(resolve v))) [:ns :name]))) 'filter)

20:30 clojurebot: clojure.core/filter

20:31 Chouser: ,((fn [v] (apply keyword (map #(str (% ^(resolve v))) [:ns :name]))) 'filter)

20:31 clojurebot: :clojure.core/filter

20:34 ryszard_szopa: is there a way of recognizing through destructuring whether something has returned [something AString] or just AString?

20:34 If I do (let [[new new-context] (some-fn context)] ...) and some-fn

20:34 returns a string as the only value, then Clojure will destructurize

20:34 the string, and new will be equal to the first element of that string.

20:35 gnuvince_: ryszard_szopa: no, destrcuturing binding is not pattern matching.

20:35 ryszard_szopa: In Common Lisp I would just make some-fn return multiple values and use multiple-value-bind

20:36 do you think there's some clean way of achieving a similar effect?

20:37 gnuvince_: checking if you are returned a vector or not maybe?

20:37 ayrnieu: You could always return a vector with one or two strings. You could tag your results Erlang-style: [:ok s], [:multi s1 s2]

20:39 Chouser: (let [z (some-fn) [x y] (if (vector? z) z [z])] ...)

20:39 :-/

20:40 ryszard_szopa: Chouser: hm, that seems quite clean... but I cannot say it is *very* clean :/

20:40 some-fun should get some context and return a string and the changed context

20:41 ayrnieu: (let [ret1 (ref nil) ret2 (ref nil)] (some-fn ret1 ret2) ...)

20:41 * ayrnieu explodes.

20:41 ryszard_szopa: I wanted some-fun to be able return just the string if it doesn't change the context... This would allow me to pass :keywords as some-funs...

20:42 Chouser: there's a snippet of code somewhere that implements CL-style multiple-value return

20:43 ayrnieu: ryszard, if you have a number of possible mutations of the context, write a macro to string the context through the calls.

20:43 ryszard_szopa: ayrnieu: string the context through the calls? what do you mean by that?

20:44 SimonAdameit: Good evening

20:45 Why is -> a macro and not a function?

20:45 ayrnieu: function arguments get evaluated before their results can be passed to the function.

20:45 ,(-> "hi" (.contains "i"))

20:45 clojurebot: true

20:45 ayrnieu: ,(.contains "i") ;; can't evaluate this ahead of time

20:45 clojurebot: java.lang.IllegalArgumentException: No matching field found: contains for class java.lang.String

20:45 SimonAdameit: It means (-> #(take 2 %) .....) does not work

20:46 ayrnieu: I'd rather have -> be a function and use currying for shortness :)

20:46 ayrnieu: there are trade-offs. Some has gone to the trouble of extending -> so that (-> (take 2 _) ...) will do that.

20:46 simon - you're a haskell-addled fool.

20:47 SimonAdameit: haha :)

20:47 no, I dont know Haskell, but I'm interested in it.

20:47 ayrnieu: actually I come from Common Lisp

20:48 ayrnieu: then you should know better! >:(

20:50 Chouser: ,((-> [a] #(* 2 a)) 3)

20:50 clojurebot: 6

20:52 Chouser: ,(-> [x [1 2 3]] (for (+ x 2)))

20:52 clojurebot: (3 4 5)

20:53 ayrnieu: ryszard, you could have something like -> that also destructures your meaningful results and has a bit of flow-control. How useful this would be depends on what you're doing.

20:54 SimonAdameit: ,(-> 3 repeat #(take 2 %))

20:54 clojurebot: java.lang.ClassCastException: clojure.lang.Symbol cannot be cast to clojure.lang.IPersistentVector

21:03 ryszard_szopa: ayrnieu: this was a one time thing... and I wanted the keywords mostly for debug purposes. I think I should just accept that destructuring =/= pattern matching and I won't be able to write my clj functions the way I would write eg Prolog predicates.

21:03 ;)

21:09 humanzee: ping

21:11 Chouser: clojure.contrib.error-kit is up: http://groups.google.com/group/clojure/browse_thread/thread/2d1d91693887a45b

21:14 feedback very welcome.

21:15 ryszard_szopa: Chouser: I like the general idea... Thanks...

21:16 however, it is not very clear for me how the intermediate continues work

21:16 durka42: Chouser: did you just post error-kit?

21:16 Chouser: durka42: yeah

21:17 durka42: can i see?

21:18 it's not in the log yet

21:18 Chouser: durka42: description posted to the group, linnk above

21:19 ryszard_szopa: Chouser: and if you are in Santa Klaus mood, then you could also consider implementing something like Ruby's `retry'

21:19 Chouser: durka42: http://code.google.com/p/clojure-contrib/source/browse/trunk/src/clojure/contrib/error_kit.clj

21:20 durka42: thanks

21:21 Chouser: ryszard_szopa: continues are a little tricky. I guess they need a more complete doc.

21:22 ryszard_szopa: I guess they don't work like restarts, allowing the operator to choose what to do?

21:23 with-handler is something like CL's handler-case... What about handler-bind?

21:24 Chouser: with-handler can have handle forms, which is like handler-case, and bind-continue which is like handler-bind

21:26 I have no clue how to even begin trying to implement ruby's retry. :-)

21:30 ryszard_szopa: Chouser: this may be naive, but you could try putting all the forms in with-handler into a lambda... and retry would just call it.

21:31 *lambda -> fn

21:31 Chouser: ruby's retry starts a loop over from the beginning, doesn't it?

21:31 maybe I misread that

21:31 ryszard_szopa: I don't know, I just heard of it and was always jealous ;-)

21:32 Chouser: "The redo statement causes a loop to repeat the current iteration. Sometimes, though, you need to wind the loop right back to the very beginning. The retry statement is just the ticket."

21:38 ryszard_szopa: Chouser: yeah, that's right. And "If retry appears in the iterator, the block, or the body of the for expression, restarts the invocation of the iterator call.". But I've always thought it would be really useful in handler-{case|bind} situations.

21:41 In CL it was quite common for me to wrap everything I wanted to be handled in a 0-argument function, which I would just call in handler-*. Then in some situations I would call it once again in the handling code. If I had a name to refer to that function my life would probably be a bit easier

21:59 danlarkin: Chouser: I'm liking how error-kit looks

21:59 Chouser: danlarkin: great!

22:00 ryszard_szopa: I think I'd have to see an example.

22:07 ryszard_szopa: Chouser: http://common-lisp.net/cgi-bin/darcsweb/darcsweb.cgi?r=submarine-submarine;a=headblob;f=/db.lisp#l122

22:11 gnuvince_: Chouser: nice work

22:12 ryszard_szopa: Chouser: hm, now that I think about it this is not the best example... I don't retry it in the handling code, but leave it for later treatment... Maybe I should stop bugging you and just write a macro when I need it :-)

22:14 Chouser: ryszard_szopa: you do that. :-) ...and then show me your macro, maybe it'll fit right in.

22:28 Raynes: Rich quits a lot doesn't he :o.

22:33 ryszard_szopa: gah! is there something like `break' in Clojure?

22:33 ayrnieu: ,(java.util.Date. (long (* 1000 1234567890)))

22:33 clojurebot: #<Date Fri Feb 13 15:31:30 PST 2009>

22:33 ryszard_szopa: or, to rephrase my question: what is your debugging strategy?

22:33 ayrnieu: ryszard - throw

22:34 Chouser: ryszard_szopa: rpn

22:34 um, prn

22:34 ayrnieu: oh, you mean *break*.

22:34 ryszard_szopa: break like in CL

22:35 (I forgot that in Java break is something completely different)

22:35 Chouser: You can use the java debugger if you want

22:35 ryszard_szopa: ayrnieu: as for throw, it doesn't allow me to continue the execution of the function

22:36 Chouser: hm... do you maybe know how to configure it to work with Slime and Emacs?

22:36 Chouser: sorry, i don't use either.

22:37 I try to use small functional functions, and sprinkle with prn.

22:37 ayrnieu: ryszard, the most advanced debugging I've done has been to set Refs from within agents.

22:39 ryszard_szopa: ayrnieu: sounds scary

22:39 * ryszard_szopa misses SBCL's debugger :(

22:51 gnuvince_: *sigh*

22:51 Man, I can't believe how slow my program has gotten to make it right

23:12 Is it possible to use a local with the . macro? Something like: (let [meth 'indexOf] (. "hello" (meth (int \e))))

23:15 drewr: (let [meth #(.indexOf %)] ... )

23:16 or

23:16 (let [meth #(.indexOf %1 %2)] ... )

23:16 (-> "hello" (meth ... ))

23:17 Chouser: gnuvince_: you can either do it with a macro or via reflection

23:17 gnuvince_: Chouser: the macro, that's what I'm looking for.

23:18 `(let [meth# indexOf] (. "hello" (meth# (int \e)))) ?

23:20 drewr: this works with no macro: (let [meth #(.indexOf %1 %2)] (-> "hello" (meth (int \e))))

23:20 Chouser: but gnuvince_ wants to pass in the name of the method?

23:21 oh, a macro won't do it if the name is being given at runtime

23:21 drewr: I've been down this road before

23:21 clojure makes this unreasonably difficult

23:22 needs something like ruby's send or python's getattr

23:22 Chouser: there was a thread on the group recently that included a macro that used eval to do it.

23:22 gnuvince_: drewr: I have about 80 million calls

23:22 drewr: when I used memfn, it took so long that I wouldn't let the program finish running

23:24 I think I want to do something for which Clojure is absolutely not suited.

23:24 * drewr covers his eyes

23:24 Chouser: ,(clojure.lang.Reflector/invokeInstanceMember "indexOf" "hello" (to-array ["l"]))

23:24 clojurebot: 2

23:24 Chouser: (clojure.lang.Reflector/invokeInstanceMember "indexOf" "hello" (to-array ["l"]))

23:25 gnuvince_: you're calling lots of different methods on the same object?

23:25 lots of different object/methodname pairs?

23:25 gnuvince_: Chouser: the same three

23:25 Byte calls get, Short calls getShort and Integer calls getInt

23:26 Chouser: can you use three closures?

23:26 gnuvince_: Too slow

23:26 Chouser: what!?

23:26 gnuvince_: I had three memfns before

23:26 They didn't cut it.

23:26 drewr: doesn't sound like raw Java would be any better either

23:27 Chouser: were they using reflection?

23:27 if you're having performance issues, the very first thing to do is turn on *warn-on-reflection*

23:28 once you've removed all reflection your inner loops, then you can look into boxing issues, primitive math and stuff.

23:36 replaca: Chouser: that error-kit stuff looks super-cool!

23:36 gnuvince_: I have no inner loop really

23:37 It's all byte reading stuff

23:37 Trying to get a profile

23:37 But it takes over 10 minutes

23:37 Chouser: :-(

23:37 gnuvince_: So progress is ultra slow

23:37 And I did what drewr suggested

23:37 I am *very* surprised that it actually increased performance

23:38 I distinctly recall switching away from functions to macros

23:38 In any case, all the better, I prefer functions to macros

23:38 drewr: any way to break up your problem into smaller sets of calls?

23:38 for quicker feedback

23:39 gnuvince_: drewr: If I run code in slime, it takes about 4-5 seconds to decode a file

23:39 But because I expect to need to decode hundreds if not thousands of files, I really need to find why I cannot get the same performance as my Python version

23:40 Chouser: gnuvince_: is it small enough code to paste?

23:40 gnuvince_: No

23:40 I have a git repos

23:40 I'll link in a few seconds

23:40 Just need to push some changes

23:40 Chouser: replaca: ah, thanks! I hope someone actually uses it -- I'm afraid I don't have much need.

23:42 replaca: Chouser: I think it's good if it just starts discussion about better errors/conditions for clojure. It feels like java exceptions (by themselves) don't really fit

23:43 Chouser: cause of the checked exceptions

23:43 Chouser: someone was in here recently wishing for checked exceptions in Clojure.

23:44 drewr: wow

23:45 gnuvince_: Chouser: http://github.com/gnuvince/clj-starcraft/tree/master

23:46 Chouser: if you wish to try it, you'll need to download a Starcraft replay file (you can go to http://teamliquid.net to get one)

23:46 Chouser: which .clj file is the main culprit?

23:47 drewr: Chouser: http://github.com/gnuvince/clj-starcraft/commit/926bf7211c497478b609def912a579646bd186b4

23:48 gnuvince_: Chouser: in starcraft.replay.unpack, decode-commands and decode-command-block are the big ones

23:48 decoding the headers is fast because it's so tiny.

23:48 (the actions are in actions.clj)

23:53 Chouser: yeah, I think a few more type hints will help you

23:53 gnuvince_: I agree

23:54 After 17 minutes, -Xrunhprof finally finished

23:54 Here are the first three lines:

23:54 1 8.43% 8.43% 13163743 304691 java.lang.reflect.Method.copy

23:54 2 8.18% 16.61% 13163743 304690 java.lang.reflect.Method.<init>

23:54 3 8.16% 24.77% 13163743 304692 java.lang.reflect.ReflectAccess.copyMethod

23:54 the next two are also about reflection

23:55 Chouser: yup, they hurt.

23:55 gnuvince_: that's like 40% in reflection.

23:55 Now, I need to find it :-/

23:55 Chouser: and the three lines that *warn-* mentions are the three you were already touching with the macro/fn switch

23:57 gnuvince_: Do I need to use defn to use type hints?

23:57 Cause I changed it to (fn [#^ByteBuffer buf] (...)) and I still get a warning

23:58 ...

23:58 It looks faster when there are no type hints?

23:58 That's abnormal...

23:58 Chouser: that's not trickling through to the %

23:59 you need something like Integer #(long (bit-and (.getInt #^ByteBuffer %) 0xffffffff))} type)

23:59 but that's not sufficient for the two previous lines. I can't quite figure them out.

Logging service provided by n01se.net