2008-06-19
| 07:12 | asbjxrn | yrb, I don't think so. That is what rhickey suggested I use. |
| 07:23 | yrb | asbjxrn: I am divided if I like it or not, on onehand it makes it explict that I am using a nested class |
| 07:50 | asbjxrn | I guess there have to be some sort of separator anyway as clojure need to find thr class |
| 08:37 | cemerick | Chouser: Yesterday you wrote "(Math/pow 2 10)" -- which I assume is treating the Math class as a namespace, and all of its static functions as functions in that namespace. How is that set up (just evaling that sexp on my end yields an exception)? |
| 08:37 | blackdog | it's new in svn |
| 08:38 | cemerick | ah-ha |
| 08:38 | cemerick | blackdog: thanks |
| 08:38 | blackdog | there's no setup it just works :) |
| 08:41 | cemerick | Yeah -- Rich's checkin comment for r910 indicates that that feature is "experimental". Is there a discussion of it somewhere? |
| 08:42 | blackdog | yes http://groups.google.com/group/clojure/browse_thread/thread/bc005da4989468c7# |
| 08:56 | cemerick | feh, I don't know how I missed that. |
| 09:34 | cgrand | hmmm, good to know: sets can't be used to implement canonicalizing mappings |
| 09:34 | rhickey | cgrand: ? |
| 09:35 | cgrand | (meta (#{#^{:id "in set"} []} #^{:id "not in set"} [])) returns {:id "not in set"} |
| 09:35 | cgrand | (contrived one liner) |
| 09:37 | cgrand | I expectied taht a set would return the key and not the arg if found |
| 09:42 | rhickey | that's what I get for enabling get on sets, eh? |
| 09:43 | cgrand | ? |
| 09:44 | rhickey | sets as functions of their keys |
| 09:44 | cgrand | yup |
| 09:49 | Chouser_ | aren't you passing two args to a hash-set? |
| 09:51 | rhickey | cgrand: fixed |
| 09:53 | drewr | In general, does a NPE signify a bug in Clojure, or could I be doing something wrong to cause it? |
| 09:54 | rhickey | the only thing that is certainly a bug in Clojure is a verify error, for all else check your code first :) |
| 09:55 | drewr | Let me rephrase the question. Even if my code isn't correct, should Clojure be handing out NPEs? |
| 09:56 | drewr | Isn't that akin to my writing something in Python and getting a segfault? |
| 09:56 | rhickey | Chouser: that's a set with a metadata-tagged empty vector member being used as a function of another metadata-tagged vector, yielded arg (broken) rather than set member (fixed) |
| 09:57 | drewr | I'm willing to spend the time writing bug reports if clojure could handle the situation more gracefully. |
| 09:57 | rhickey | drewr: no, NPEs are often user bugs, and they are catchable by user code - what should Clojure do with them? |
| 09:59 | Chouser_ | drewr: python libs don't hand out segfault. Java libs often throw NPEs. |
| 10:00 | drewr | Chouser_: Ah, I didn't know that was a common failure for Java libs. |
| 10:01 | cgrand1 | rhickey: thanks for the fix |
| 10:01 | Chouser_ | Well, that's my impression anyone. Someone that actually knows Java may correct me. :-) |
| 10:01 | Chouser_ | s/anyone/anyway/ |
| 10:02 | rhickey | So in Python you get a TypeError thrown - what's the real difference? |
| 10:03 | Chouser_ | don't we get type errors in clojure too? |
| 10:03 | Chouser_ | ok, thanks for the set explanation. I get it now. :-) |
| 10:03 | rhickey | you can get all sorts of errors, my point is they throw exceptions, you get stack traces etc, there's no magic to Python here |
| 10:04 | rhickey | neither dumps core |
| 10:11 | yrb | rhickey: have you got any plans to implement nested class access along the lines of the recent static member access? |
| 10:17 | yrb | and do you think it would be a good idea for import to load the nested classes into the namespace automatically? |
| 10:33 | rhickey | yrb: no, nested classes have composite names - why, don't like $ ? |
| 10:37 | cemerick | Train of consciousness: I've got an interface with methods foo and bar. My impulse is to use a map (or structmap) so I can do stuff like (:foo obj) rather than (. obj (foo)), and so that changes are easy and efficient. However, I then need a function that will pop off proxied instances that implement that interface so as to interoperate, and a function that will unpack instances coming in from Java into a map (or structmap). This basically sucks -- I a |
| 10:37 | cemerick | I guess this is getting back to the data-design topic. I'm probably making this harder on myself than it needs to be. |
| 10:39 | rhickey | cemerick: you can say (.foo obj) |
| 10:39 | rhickey | both Clojure and Java code create instances of this interface? |
| 10:39 | cemerick | Yeah, potentially. |
| 10:40 | cemerick | The nice thing about using simple maps is that changes are so efficient. Copying on changes is not something I want to do (although I guess that'd be required if I subclassed PStructMap). |
| 10:42 | cemerick | A bunch of multimethods would essentially give me everything I want, except it'd require more code than what seems reasonable for this case. |
| 10:44 | yrb | rhickey: it isn't the $, (I actually like the distinction) it is more not having to explictly import the nested classes of an class already imported |
| 10:45 | yrb | thought I am not sure if I would want that now... |
| 10:47 | yrb | I have mostly finished my awt/scene graph wrapper, and I don't think that style of java is very common outside the gui libs |
| 10:48 | rhickey | cemerick: so you want to use this interface functionally? |
| 10:49 | rhickey | Java implementations of the interface are unlikely to be functional |
| 10:49 | cemerick | rhickey: well, this particular interface is read-only, so that's something |
| 10:49 | rhickey | but you can implement an imperative interface with a ref to a map as its state |
| 10:50 | cemerick | Further, the interface is ours, so that helps, too :-) |
| 10:51 | rhickey | that's good, I guess my 2 cents is, don't hide/avoid/wrap the interface, use Clojure goodness in your implementation of it |
| 10:51 | cemerick | rhickey: Sure, and considering the general case, where we implement the interface and use a ref and map as a backing store -- it's obviously preferable to touch that ref and map when you're on the clojure side of things. |
| 10:52 | cemerick | The tricky part is being able to route and process instances that are implemented differently -- which brings me back to multimethods, I guess. |
| 10:52 | rhickey | caring about how they are implemented is a warning sign |
| 10:53 | cemerick | I know -- that's why I'm floundering a bit here :-) |
| 10:54 | cemerick | I could just not care how anything is implemented, and always copy on every mutation. Of course, that sucks -- perhaps an eager optimization, but perhaps not. |
| 11:00 | rhickey | ah, I see, your interface is read only and you'd like to treat instances persistently? |
| 11:00 | cemerick | indeed |
| 11:01 | rhickey | I'm running now, perhaps can follow up later... |
| 11:01 | cemerick | Yeah, we'll see how the rest of the morning goes. :-) |
| 11:17 | cemerick | This is (mostly) spurious, but shouldn't reduce take the initial value first, then the function and sequence? The way it is now, the (typically concise) initial val is in between two (potentially) verbose sexps. |
| 11:22 | cgrand1 | cemerick: the current args order is mnemonic (at least for me :-) ) |
| 11:23 | cemerick | cgrand1: it's just the opposite for me, but it's all moot now :-) |
| 11:24 | cemerick | does the literature generally use [fn, val, seq] order, or is that ordering typical from other lisps, or...? |
| 11:24 | Chouser_ | the initial value is immediately before the seq that forms the rest of the values. it does make a kind of sense. |
| 11:25 | Chouser_ | (reduce list 0 [1 2 3]) |
| 11:25 | cemerick | Chouser: Yeah, I can see that. I always think of seed values as binding more to the fns that they travel with. A totally personal mental model sort of thing. |
| 11:26 | Chouser_ | I admit I generally have to look it up. |
| 11:27 | cemerick | From a totally practical standpoint, if you've got a fn of any complexity, finding that lonely initial value that follows it requires a little squinting. |
| 11:27 | cemerick | At what point does a hash map tip over into a tree map? |
| 11:27 | Chouser_ | never, I think. |
| 11:28 | Chouser_ | PTreeMap is sorted, PHashMap is not, and I don't think there's any automatic conversion from one to the other. |
| 11:29 | cemerick | My apologies -- I forgot that PHashMap is a tree, internally. |
| 11:31 | Chouser_ | I thought that might be it. I don't know how quickly it grows to what kinds of depths. |
| 11:34 | Chouser_ | it'd be interesting to ask a particular hash what it's shape and depth is. |
| 11:35 | cemerick | One of Rich's screencasts goes into a couple of details about height and big-O guarantees. |
| 11:39 | cgrand | max depth: 6 (or 7, not sure of the details), 32 chlidren per node |
| 11:40 | Chouser_ | but surely being a hash means the first node won't have a full 32 before it starts getting sub-nodes, right? |
| 12:56 | Chouser_ | (double 2) is not equal to 4 |
| 12:57 | drewr | Heh. |
| 13:15 | Chouser_ | and so far I've had friends guess that it returns: 22, (2 2), and T |
| 13:16 | abrooks | 2.0? |
| 13:16 | abrooks | :) |
| 13:16 | Chouser_ | cheater. |
| 13:17 | abrooks | Not at all. I hadn't been in #noise yet. I just started here. |
| 13:18 | Chouser_ | well, I guess I have to take your word for it, don't I? ;-) |
| 13:18 | abrooks | Indeed you do, unless you're snooping my gnu screen sessions. |
| 13:19 | abrooks | I did know that the unboxed numbers made their recent debut and you eliminated several alternatives above. |
| 14:01 | Chouser_ | If I want to refer generically to a sequential collection, including things like Java array, Clojure vectors, Clojure lists, etc. what's the best word to use? |
| 14:02 | Chouser_ | I would use "list" but that has specific meaning in Clojure. |
| 14:03 | rhickey | Chouser: 'sequential collection' ? |
| 14:04 | Chouser_ | and so my variables can be named seqCollA, seqCollB. ;-) |
| 14:04 | rhickey | these are Java variables? |
| 14:04 | Chouser_ | well, I was trying to use the same name in both. Maybe I shouldn't bother. |
| 14:05 | rhickey | fred/ethel/ricky/lucy works for me :) |
| 14:05 | Chouser_ | yeah. |
| 14:06 | abrooks | littlericky gets a bit long though. |
| 14:06 | jmbr | hi |
| 14:06 | Chouser_ | hi |
| 14:22 | cgrand | chouser_: about hashmap depth, I remembered I had a heap dump somewhere, so I ran some queries on it: hashmaps of ~400 elements seems to have nearly no (ie 1-3 per map) node of depth 4 |
| 14:22 | Chouser_ | cgrand: cool, thanks. |
| 14:23 | rhickey | if hashes are good, depth should be roughly log32N |
| 14:23 | rhickey | never more than 6 |
| 14:26 | Chouser_ | if two things hash the same, is there a linear bucket at the bottom of the tree? |
| 14:26 | rhickey | yes |
| 14:26 | Chouser_ | I'm looking at the code and still can't tell. :-) |
| 14:27 | Chouser_ | ok, thanks. |
| 14:27 | rhickey | sorry the persistent data structure code is lean and, well, mean |
| 14:28 | Chouser_ | hm, but probably only if the hash is fully identical, right? You get more depth in the tree before you get the linear bucket? |
| 14:28 | rhickey | right, that's the 'trie' aspect |
| 14:41 | abrooks | This has bugged me since I came across JudyArrays long ago. Unfortunately, I'm not getting any traction. :-) |
| 14:41 | rhickey | yes, it's very annoying |
| 14:42 | Chouser_ | can we also rename map or map, and perhaps double? |
| 14:43 | Chouser_ | other sciences go and invent new latin-like words, don't they? |
| 14:56 | Lau_of_DK | Everything needs to stay exactly the way it is |
| 14:57 | Lau_of_DK | Ive had enough trouble learning Clojure, coming from Lisp |
| 14:57 | abrooks | :) |
| 14:58 | abrooks | Lau_of_DK: Perhaps we could use Danish terms instead of Latin? |
| 15:07 | Lau_of_DK | haha - you obviously dont know Danish |
| 15:07 | Lau_of_DK | Speaking 100% objectively: Its one of the most disgusting languages on earth |
| 15:10 | abrooks | Lau_of_DK: You are correct. My Danish vocabulary is (). :) |
| 15:11 | Lau_of_DK | user> (. Integer (toString 11121231230000)) |
| 15:11 | Lau_of_DK | "1560900656" |
| 15:11 | Lau_of_DK | This is not what I expected... |
| 15:12 | Lau_of_DK | rhickey, is this your doing? Something is broke in the BigInt module? |
| 15:15 | Chouser_ | Lau_of_DK: I think your BigInteger is being converted to an Integer in order to be passed to Integer/toString |
| 15:15 | Chouser_ | Perhaps you wanted (.toString 11121231230000) |
| 15:16 | abrooks | Lau_of_DK: I thought English held the record for "Most Disgusting Language on Earth" (or maybe it was Klingon...). |
| 15:16 | Lau_of_DK | Chouser, ... Sure - so .toString is related to what.. if not Integer? |
| 15:16 | Lau_of_DK | abrooks, I think it might actually be Perl, then Danish :) |
| 15:17 | Chouser_ | .toString is being called on whatever the actual type of its argument is -- in your example, BigInteger |
| 15:17 | rhickey | user=> (int 11121231230000) |
| 15:17 | rhickey | 1560900656 |
| 15:17 | Lau_of_DK | Aah I see |
| 15:17 | Lau_of_DK | So as I was just about to complain about Dynamic typing, its just because I dont really understand it, Clojure is a bit more clever than I had anticipated |
| 15:19 | rhickey | user=> (str 11121231230000) |
| 15:19 | rhickey | "11121231230000" |
| 15:20 | Lau_of_DK | thanks rhickey |
| 15:41 | Lau_of_DK | rhickey, would it be possible to compare the speeds of C, Python and Clojure for some computations? Have anything along those lines been done? |
| 15:50 | rsynnott | Lau_of_DK: there was a python/clojure one on reddit recently,I think |
| 15:52 | Lau_of_DK | Thanks rsynnott , I'll go look |
| 15:57 | cemerick | I *think* the data-design issues I was going on about earlier *might* be more general than I thought -- similar issues arise if one were to implement (for example) a tree data structure in Clojure whose interface is defined in Java, but should ideally have a richer interface in Clojure. This might just be the cost of doing business with Java callers and callees, I suppose. |
| 16:00 | lisppaste8 | Lau_of_DK pasted "Java Heap...?" at http://paste.lisp.org/display/62507 |
| 16:00 | Lau_of_DK | Gents- Simple task. Euler style. Find the first x that produces an x! that has 7^20 trailing zeroes... My code fries the Java Heap in about 5 - 7 minutes, so I assume Im doing something wrong ? |
| 16:11 | Lau_of_DK | (14 minutes actually) |
| 16:13 | Chouser_ | thats a lot of zeros |
| 16:13 | Lau_of_DK | Yes ma'am |
| 16:15 | rhickey | cemerick: one option is to offer persistent 'mutation' in the interface, e.g. like IPersistentMap does |
| 16:15 | Lau_of_DK | Maybe its not supposed to be bruted though - There's a pretty clear pattern showing in the number of trailing zeroes |
| 16:17 | cemerick | rhickey: Yeah. Over time, we'll be doing exactly that for those interfaces we control and we can change in that way without freaking out our users. |
| 16:20 | cemerick | In the general case though (or simply when you don't have that option), it feels like there should be a relatively direct way to pass around proxied maps (for example), and when you get such an object back, be able to dereference the proxy to get a hold of the underlying map again. Totally doable with a couple of macros and multimethods (and probably an interface to allow the dereferencing bit). We'll see how motivated I get as I go along. |
| 16:20 | cemerick | rhickey: Any further suggestions you have are certainly welcome. :-) |
| 16:21 | rhickey | define and implement another interface for access to that implementation stuff |
| 16:23 | rhickey | (ah, you got that already, nevermind) |
| 16:26 | cemerick | rhickey: times like these, I wish clojure had a gen-and-save-interface ;-) |
| 16:27 | rhickey | I might consider that |
| 16:28 | cemerick | In a year or so, clojure will be the best interface to asm around. |
| 16:36 | Lau_of_DK | (gen-and-save) = (save-lisp-and-die) ? |
| 16:38 | drewr | Lau_of_DK: No. It's for created a (non-proxy) Java class. |
| 16:39 | Lau_of_DK | Ah ok |
| 16:40 | drewr | It's actually GEN-AND-SAVE-CLASS now. |
| 16:41 | drewr | The -SAVE part refers to the fact it actually writes the bytecode to a .class file. |
| 16:41 | drewr | Pretty cool. Check out genclass.clj. |
| 16:42 | drewr | The world would be a different place. |
| 16:42 | Lau_of_DK | drewr, did you know that rhickey is an alias for Skynet ver. 1.0 ? |
| 16:44 | drewr | Lau_of_DK: Surely he's at least r2 or r3. |
| 16:55 | cemerick | Is there a way to install a method by referring to an existing fn that I'm missing somewhere? |
| 16:56 | rhickey | cemerick: a proxy method? |
| 16:57 | cemerick | hrm, no -- for multimethods. So as to say (defmethod foo :bar some-fn) |
| 16:58 | cemerick | Just if I happen to have an appropriate fn floating around that is independent as well as useful as a multimethod. |
| 16:58 | rhickey | not right now, you'll have to forward to it |
| 17:39 | meredydd | Hey |
| 17:39 | meredydd | Who's responsible for the 'set namespace? |
| 17:40 | Chouser_ | rhickey himself |
| 17:40 | meredydd | I just discovered it today, and it's The Shit. |
| 17:40 | meredydd | Ah. |
| 17:40 | meredydd | That...doesn't surprise me at all. |
| 17:41 | meredydd | It's that beautiful :) |
| 17:41 | Chouser_ | :-) Gotta run. |
| 17:42 | meredydd | In any case, I'd like to *beg* rhickey to make more noise about that feature. It's really something. |
| 18:55 | shizzy0 | I have a weird idea, that I'm trying to do. Can I make an anonymous macro? (mac [x] ...) |
| 18:56 | rhickey | shizzy0: no, how would it be called? |
| 18:57 | shizzy0 | (let [m (mac [x] ...)] (m stuff...)) |
| 18:57 | shizzy0 | ? |
| 18:58 | rhickey | ah, local macros like CL macrolet, and symbol-macrolet - nope, don't have those yet |
| 18:59 | shizzy0 | (defmacro mac [parameters & body] |
| 18:59 | shizzy0 | `(let [f# #^{:macro true}(fn ~parameters ~@body)] |
| 18:59 | shizzy0 | (. (var f#) setMacro) |
| 18:59 | shizzy0 | f#)) |
| 18:59 | rhickey | it's not that simple |
| 19:00 | shizzy0 | That's what I was playing with, but it doesn't like (var f#). |
| 19:00 | shizzy0 | Right, it seems like a good opportunity to understand more of how things work. |
| 19:01 | rhickey | the compiler needs to participate in macroexpansion, right now there are no local macros |
| 19:02 | shizzy0 | [nods] ok. |
| 19:02 | shizzy0 | I'm just trying to stretch out in clojure, and see what I bump into. |
| 19:02 | rhickey | global vars can be tagged as macros, and their global definitions treated as macroexpanders, but local functions are not available to the compiler as macroexpanders |
| 19:03 | rhickey | It's something I would have to add, not something you can do with macros |
| 19:04 | rhickey | the concept is sound - I particularly miss symbol-macrolet |
| 19:06 | shizzy0 | good to hear. |
| 19:09 | shizzy0 | that the concept is sound. I hadn't used it in CL. :) |
| 19:13 | shizzy0 | btw, rhickey, I really like what you've done. I haven't done anything with Java for a long time now, but I could see myself actually working in the JVM now. |
| 19:14 | rhickey | great!, thanks |
| 19:22 | meredydd | rhickey: By the way, I just discovered the 'set namespace, and am very impressed. |
| 19:22 | meredydd | Although I am somewhat confused by the (->) macro. The docstring is a bit, um, opaque. |
| 19:22 | rhickey | cool, I don't think anyone else has looked at it |
| 19:23 | meredydd | Yeah...I'm really hoping you'll change that - write it up as one of the pages in the sidebar, perhaps? |
| 19:23 | rhickey | -> threads the argument and successive returns as the first arg of subsequent forms |
| 19:23 | meredydd | I really think that having the relational algebra expressible natively is a really powerful thing |
| 19:23 | rhickey | yeah, I hope to do more with it |
| 19:24 | meredydd | (plus, it provides something I can point to and say - "Look! Native sets and maps in a Lisp is a beautiful thing" |
| 19:25 | rhickey | personally I think it is a shame that Lisp has been tied to lists for so long |
| 19:26 | shizzy0 | ok, I don't know if this was intended, but I think this is pretty neat. |
| 19:26 | shizzy0 | (map eval (map and '(true false) '(true true))) |
| 19:26 | meredydd | rhickey: right...so if I did (-> 1 (- 2) (+ 1)) it comes out as 3 |
| 19:27 | shizzy0 | The fact you can apply and map macros, and you'll get something weird out of them, but if you eval them, you get the actual results you'd naively expect. |
| 19:27 | meredydd | Oh, yeah...actually, that was something I wanted to say, too. |
| 19:27 | meredydd | I tried to do (map) with (and), and got some *mighty* funny results. |
| 19:27 | rhickey | meredydd: 0, no? |
| 19:28 | meredydd | Took me quite a while to figure out what went wrong. Any chance we could have a warning when some stupid programmer tries to do that kind of thing? |
| 19:29 | shizzy0 | I got 0 for meredydd's expression. |
| 19:29 | meredydd | It's not always obvious which ops are macros and which are fns, and I could conceive of certain calls changing from one to another, say, between library releases |
| 19:29 | meredydd | (Yes, sorry. I meant 0, which is what the interp gave me) |
| 19:29 | rhickey | and is a macro, so can't be mapped, but you can do (map #(and %1 %2) ...) |
| 19:29 | rhickey | (map #(and %1 %2) [true true] [true false]) |
| 19:29 | meredydd | I know - that's what I did. Trivial change, once I figured it out. |
| 19:30 | meredydd | But as it stands, if you try to use a macro as a fn value, it lets you |
| 19:30 | rhickey | I might be able to catch attempted use of macros as values... |
| 19:30 | meredydd | It just uses the macro's code-munging function instead |
| 19:30 | rhickey | right |
| 19:31 | meredydd | which caught me somewhat by surprise. |
| 19:31 | shizzy0 | rhickey: but if you eval the expression you get from using a macro as a function, you get the right value it seems like. I actually kind of like that unification of macros and functions. |
| 19:31 | meredydd | Any chance of a molly-guard for the rest of us? I agree with shizzy0 that it might be cool to be able to throw macros around and do interesting things with them |
| 19:32 | rhickey | something being a macro or function is part of its interface |
| 19:32 | rhickey | in practice things don't toggle between |
| 19:32 | shizzy0 | For instance, (apply and '(true false)) doesn't work but, (eval (apply and '(true false))) does. |
| 19:32 | rhickey | yes, as I said above, I might be able to flag it |
| 19:32 | meredydd | Perhaps like the reflection warnings - some explicit flag to say "I know what I'm doing, don't warn me about the fact that I'm taking this macro" |
| 19:32 | meredydd | That'd be great AFAIC. |
| 19:33 | meredydd | Oh, and one more, while I have you here. Looking at the doc for (->), I understand why I was so confused. |
| 19:34 | meredydd | ...oh, no, scrub that. The doc's right, my brain's wrong. Ignore. |