10:36 drewr: I added a lazy fibonacci function to http://
10:39 MarkJP: how do I do the equivalent of MyClass.class in clojure?
10:40 rhickey: MyClass is a Class?
10:40 MarkJP: yes
10:40 like String
10:40 String.class gets me the Class instance
10:40 in Java
10:40 rhickey: (class String)
10:40 like all objects
10:41 but the result for any Class will always be Class
10:42 MarkJP: yeah, when I do (seq (. (class String) (getMethods)))
10:42 I don't get the String methods?
10:42 rhickey: because the class of the class String is Class
10:42 MarkJP: I get the Class and Object methods
10:42 rhickey: you want the String class itself
10:43 which is just String
10:43 but the first position to . is not normally evaluated
10:43 so to get the String class object (instead of String class scope for static call) use identity
10:44 (seq (. (identity String) (getMethods)))
10:44 MarkJP: awesome
10:44 that's the trickl
10:44 thanks
10:44 didn't know about identity
10:45 rhickey: it just returns it's argument, but it's prevents the compiler from seeing String as a scope
10:45 its
10:51 Chouser: hm.. subtle.
10:52 rhickey: Well, I didn't make classes scopes and objects with the same name, Java did :)
10:54 MarkJP: hmm
10:54 so this should work:
10:54 (map #(. (identity %) (getMethods)) '(FileWriter String))
10:54 Chouser: rhickey: wasn't critisizing, just a good detail to know.
10:55 rhickey: Chouser: I acknowledge the subtlety, and this comes up often, might be a good wiki tip
10:56 MarkJP: No matching method found: getMethods
10:56 drewr: How do you know to apply SEQ to "[Ljava.lang.reflect.Method;@6b340a"?
10:56 rhickey: Mark: no, . is a special op, it looks to see if the first arg designates a class, and treats it as a static call
10:56 cgrand: Mark: (map #(. % (getMethods)) [FileWriter String])
10:57 rhickey: (list FileWriter String) is a list of classes, '(FileWriter String) is a list of Symbols
10:57 MarkJP: cgrand: sameproblem
10:57 rhickey: identity trick is only when you want to use a class _object_ by name directly after .
10:58 (let [x String] (. x getMethods))
10:59 cgrand: markjp: strange, I get ([Ljava.lang.reflect.Method;@ec436 [Ljava.lang.reflect.Method;@173eca6)
10:59 rhickey: Mark: cgrand's is right, (map #(. % (getMethods)) [java.io.FileWriter String])
11:00 returns seq of arrays of Methods
11:00 MarkJP: yep sorry, cgrand was right
11:00 thx
11:02 rhickey: drewr: "[..." is the way Java arrays print toString, and Method[] is the documented return type of GetMethods, and seq works on Java arrays
11:03 when I do readable Java objects, I'll change prn to print arrays readably
11:05 drewr: rhickey: OK, thanks.
11:12 rhickey: drewr: re: fib, if you want to end up with a seq, that people use with take, nth etc, then you might want to consider using a seq directly, rather than have them call a fn:
11:12 (def fib
11:12 (concat
11:12 [0 1]
11:12 ((fn rfib [a b]
11:12 (lazy-cons (+ a b) (rfib b (+ a b)))) 0 1)))
11:13 user=> (time (nth fib 1000))
11:13 "Elapsed time: 3.732 msecs"
11:13 second time:
11:13 user=> (time (nth fib 1000))
11:13 "Elapsed time: 0.671 msecs"
11:15 If you stick with a fib function, it will be recalculated every time. In any case I think you need to hide the 2-arg helper fn, as no-one will know what to do with it
11:29 drewr: Yeah, that's much cleaner. My concat didn't feel right.
11:34 rhickey_: I understand why yours is cleaner (and I was wondering how to make a lexical function like that), but why is mine so much slower? Should the original (fib 0 1) only get called once and return the lazy-cons?
11:35 rhickey_: your's isn't slower the first time, but every time someone calls (fib) they start over, mine is essentially a cached infinite seq, lazily extended
11:36 drewr: Ahhh. That's wicked cool.
11:37 I do get an error with yours though:
11:37 user> (take 20 (fib-rich))
11:37 java.lang.ClassCastException: clojure.lang.FnSeq
11:37 rhickey_: mine is not a function, no parens needed
11:38 (take 20 fib-rich)
11:39 drewr: OK, you're just wrapping the real function with a [0 1] seed. That's what I was essentially trying to do but didn't know how.
11:39 In Scheme, you'd just (define fib... (define rfib... )) and I couldn't figure out how to replicate that.
11:40 rhickey_: it's not exactly like that - that's the lexical part, but the expression (concat ...) that initializes fib returns an infinite seq, fib just holds the seq
11:40 fib is not a function
11:41 drewr: I understand. It's just giving a name to a sequence that starts with [0 1] and ends with an infinite one.
11:41 rhickey_: right
14:51 drewr: Can I specify a default value for a function arg?
14:51 ...like Python, def foo(bar=None): pass.
14:53 Chouser: nope, but you can specify multiple arities for your function, like this...
14:53 drewr: I need basically the same code for each arity though.
14:53 I don't want to repeat it.
14:53 Chouser: (defn foo ([] (foo nil)) ([bar] (...)))
14:54 drewr: I could use (defn [& bar] (if bar ...)) I guess.
14:54 Chouser: oh! right, if you want them to all default to nil.
14:54 drewr: Yeah, I just want to optionally pass it.
14:55 Chouser: in fact, then you could do: (defn foo [& [bar]] ...)
14:56 drewr: Why not [& bar] ?
14:56 Chouser: bar would then be a seq
14:57 there can only be one thing after &, and it gets a seq of all remaining actual parameters.
14:58 ...unless that one thing is a list (like [& [bar]]) in which case it too gets deconstructed.
14:58 If you have multiple optional args that you want to each default to nil, you can use this pattern: [& [x & [y & z]]]
14:58 oops, I mean: [& [x & [y & [z]]]]
15:00 drewr: Or [& [x y z]] ?
15:02 Chouser: no, that throws an exception if you dont have at least 3 items
15:02 just like [x y z]
15:02 Using & and wrapping the next level in [] all the way down keeps each next level optiona.
15:02 optional.
15:04 drewr: Ah.
15:14 Chouser: I guess I should say the & keeps the next level optional, and the [] deconstructs that next level.
15:18 abrooks: Does this ask for a: (defmacro varargs ...) // (defn foo [(varargs x y z)] ...)
15:18 varargs may be too specific but I can't think of other places that you'd use that construct.
15:19 Chouser: I was thinking about that. Have you tried it? Will a macro be evaluated inside a binding construct like that?
15:19 my guess is no.
15:23 The binding forms are walked by the clojure/destructure function, not evaluated, so it looks like a macro there won't be called.
15:24 You'd have to put the macro on the outside of the defn.
15:35 abrooks: Chouser: You're right, of course. Since the application is mostly specific you could create the few fnvar/defnvar or whatever macro wrappers for fn/defn.
15:36 ^mostly specific^specific to functions
15:51 Chouser: abrooks: it still seems like it'd be pretty tricky. Wouldn't you have to define your whole own destructering system?
15:56 rhickey_: (defn foo [& [a b c]]
15:56 [a b c])
15:56 user=> (foo)
15:56 [nil nil nil]
15:56 user=> (foo 1)
15:56 [1 nil nil]
15:56 user=> (foo 1 2)
15:56 [1 2 nil]
15:56 user=> (foo 1 2 3)
15:56 [1 2 3]
15:58 Chouser: ack!
15:59 drewr: I lied to you.
16:00 Man, I really thought I had tried that.
16:04 jgracin: yay! When I press Super-a with cursor (point, that is) over some Clojure var in Emacs, I get its arglists printed in the minibuffer.
16:04 * abrooks is filled with emacs envy.
16:05 rhickey_: jgracin: with what clojure-mode version?
16:05 * abrooks really needs to get viper/vimpact setup.
16:05 abrooks: Er. Not vimpact, vimpulse.
16:06 jgracin: with your socket-repl code and a couple of funcs written by me. not touched(integrated into) clojure-mode.
16:08 rhickey_: anyone try swank-clojure from: http://
16:12 jgracin: rhickey_: oh, I didn't know about that. that looks cool.
16:16 drewr: rhickey_: Yes, I've been using it for a few days and it's really good.
16:17 rhickey_: drewr: what does it add over clojure-mode?
16:18 drewr: All the goodness that SLIME/swank gives you... ad hoc function prototypes, more tightly integrated REPL & code buffer, and soon dynamic introspection.
16:18 * rhickey_ never used slime
16:19 drewr: I remember you saying you were a LW guy.
16:19 rhickey_: right
16:23 Chouser: swank-clojure doesn't support debugging yet, does it? breakpoints, stepping, etc?
16:26 drewr: Chouser: No, and I'm not sure what's involved with that. I asked rhickey_ about conditions/restarts in Clojure because I wondered if it's required.
16:27 Chouser: ah
16:27 drewr: Making the stacktrace/debugging process more CL-like would help a lot.
16:28 I'm not sure if the onus is on Clojure or SLIME for the bulk of that.
16:32 rhickey_: it's hard for me to imagine that approach bettering JVM debuggers - Clojure is all wired for that
16:32 * rhickey_ needs to try cgrand's Eclipse debugger plugin
16:35 drewr: Do you forsee an exception abstraction between Clojure and Java for things that only make sense to Clojure?
16:36 rhickey_: like what?
16:38 drewr: Take my earlier problem for example. `(def a (seq (1 2 3))) (take 10 (a))' yields a ClassCastException with FnSeq because A isn't a function.
16:39 That seems counterintuitive, and a little orthogonal to the problem at hand.
16:39 Can't Clojure tell me that A can't be used in a callable context or something?
16:39 rhickey_: hmmm... wrap every call in a try/catch?
16:40 drewr: I know that the objective isn't to hide Java from the end user, but it seems like some things could be wrapped.
16:40 Oh, so that's what it would take? Wrapping every eval?
16:40 rhickey_: I just wish the CastClass message said both the type you had and the type required
16:40 drewr: Heh. That would help a lot.
16:41 rhickey_: wrapping eval wouldn't give you the granularity to know what was wrong
16:42 fn calls are fast because they are cast and call, there is no conditional aspect to them
16:43 drewr: Ah. So does the JVM not give you the information to really make it worthwhile anyway.
16:43 ./?
16:44 rhickey_: I could instead do instanceof IFn and conditional branch, but at a perf cost
16:45 fn call speed is pretty imprtant
16:45 to me
16:45 drewr: I'll just learn how to interpret the Java stacktraces (I'm getting better).
16:45 I don't want Clojure to be such a thick layer on top of Java that it's counterproductive.
16:47 rhickey_: There is definite room for improvement in error messages, the one you chose though is a critical area, I think the onus is on Java to improve that message, it seems obviously deficient - maybe it is a security thing?
16:49 drewr: Perhaps, though that would seem ridiculous. Why lay out the entire call stack and then the one piece of evidence you need?
16:49 I don't have enough experience with Java to know if they make decisions like that.
16:50 rhickey_: caster could be casting to a class private to it, reported castee type is known to the caller
17:38 cgrand: having trouble getting breakpoints set with the Eclipse plugin...
17:38 anything special one needs to do? I just dropped the jar in plugins/ and restarted
17:39 made a remote debug connection to a Clojure instance
17:39 open boot.clj in Eclipse, refuses to let me set breakpoints
19:05 ericthor: #thortech
19:06 opps...wrong window