#clojure log - Aug 04 2008

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

4:15 rhickey: cemerick: saw your message about inheriting the 'same' method from 2 interfaces. I've always thought Java got that wrong by merging on signature, even if the semantics were different. C# allows one to disambiguate, but Java doesn't... not sure what is right here - I'd want an error

4:17 cemerick: rhickey: Yes, in an ideal world, java wouldn't suck on this point, but clojure has to fold into java here. Otherwise, genclass starts to fail in various edge cases.

4:18 (or, has failed, in my edge case :-) )

4:18 rhickey: Do you have a legitimate case of where the same method satisfies the semantics of both interfaces?

4:18 esoehnel: rhickey: still need someone to do the multimethodizing of print?

4:19 rhickey: esoehnel: yes, if you have sent in a CA, or will do so, sure

4:20 cemerick: rhickey: yes -- I have a data structure interface that used to have a size method, but the default impl of it will also implement IPersistentCollection, so I'd like to collapse the old size method to align with IPersistentCollection's count

4:20 otherwise, the impl has size and count defined, which is *really* bad IMO

4:21 rhickey: cemerick: so you have 2 counts?

4:22 cemerick: rhickey: no, one count, and I want just one method for obtaining that count. IPC has a count method, and the data structure interface should have a matching method.

4:22 rhickey: cemerick: still confused - what method are you inheriting from 2 different interfaces?

4:23 cemerick: rhickey: int count (), defined in my interface as well as in IPersistentCollection

4:24 rhickey: cemerick: your interface wouldn't derive from IPC?

4:24 cemerick: rhickey: No, it's for public consumption by non-clojure-aware users.

4:27 I don't think this is so strange in general, regardless of my particular requirement of not exposing clojure interfaces. I'm sure someone down the road will be implementing multiple interfaces via genclass that just happen to have the "same" method.

4:27 rhickey: cemerick: the flip side is when 2 interfaces define a method with the same sig and different semantics, and a single implementation is used for both. Users often don't realize this is happening. Many times the only solution is to restructure the hierarchy. I'd rather know earlier than later that I needed to do that

4:29 cemerick: I agree entirely, but w.r.t. Java, that ship has sailed. Given genclass' exclusive role as providing a Java face to clojure implementations, I'm not sure how it could reasonably deviate from Java's behaviour (at least w.r.t. static stuff like this).

4:29 rhickey: I understand genclass is about Java, and following Java's bad behavior her is easy to justify...

4:29 here

4:30 cemerick: I'd be perfectly happy with a compiler warning being emitted, if that's something that seems worthwhile.

4:30 rhickey: yeah, just thinking about not have a good warning system in place...

4:31 cemerick: If you're disinclined to change this, that's fine by me at the moment, but I'm sure it'll come back sooner or later.

4:32 rhickey: no, I agree there's no alternative to following Java in this case

4:32 cemerick: we're in the happy position of hardly ever implementing third-party interfaces, so it's no big trick to make my interface define 'size' here, and just live with the duplicate definition on the internal impl

4:32 Stuff like this makes me wonder why you chose java as clojure's platform, rather than .NET (although I'm *very* glad you did!)

4:34 esoehnel: rhickey: of course I will do so, i'm currently at removing the reflection warnings

4:34 rhickey: .Net has plenty of problems of its own, starting with class library anemia

4:34 cemerick: rhickey: BTW, on a related note -- genclass class <clinit> methods currently load /com/foo/MyClass.clj -- shouldn't it be loading /com/foo/foo.clj instead/also?

4:34 rhickey: Java collections and concurrency stuff is much better

4:35 cemerick: I guess the tradeoffs are endless.

4:35 rhickey: cemerick: no, I haven't decided to do that (yet, if at all) because multiple classes from same package will cause multiple loads

4:37 cemerick: Yeah, that's what I figured you'd say. Hopefully issues like that will go away once lib is part of clojure.

4:38 In case you're wondering why I mentioned that: I've got about 12 genbean usages, and was hoping to have them all in a /com/foo/foo.clj file, rather than scattered about.

4:39 rhickey: cemerick: I definitely want to support that

4:40 maybe a :use option once lib is integrated?

4:41 cemerick: you mean as part of the genclass usage?

4:41 rhickey: right

4:42 cemerick: why not have the genclass clinit hook into lib directly, and require the necessary namespace -- make it up to the dev to hook their multiple-file namespace together using lib as well (if they want /com/foo/MyClass.clj files in addition to /com/foo/foo.clj)?

4:43 that seems like ideal default behaviour to me

4:44 rhickey: cemerick: for a default, sure, but leave you in the same position as today, just one level up, with a granularity dictated by a 1:1 default, now with class, then with immediate parent package

4:45 cemerick: oh, right, yes...didn't catch what you meant before

4:46 also BTW, I'm slowing coming to appreciate the new multimethods ("slowly" because I've got types wired into my head). Haven't written any code to utilize them fully yet, but I definitely have a use-case for them coming up.

4:47 rhickey: cemerick: they should work better now with existing type hierarchies too

4:48 cemerick: yeah, I followed the isa? discussion from afar :-)

5:05 lisppaste8: rhickey pasted "dupe interface sig patch" at http://paste.lisp.org/display/64672

5:06 rhickey: cemerick: untested, if you could test and resubmit as a patch I'll incorporate it, thanks

5:24 cemerick: rhickey: +1 on that patch -- our test suite now passes with the "int count();" method overlap. You want that posted to the group?

5:25 rhickey: if it works as written, no, I'll just paste it in

5:25 it was off the top of my head, I didn't run it

5:26 cemerick: well, good on you, then, it works as-is (I just copy-pasted it).

5:26 Of course, stuff like this scares the hell out of me (no proper regression tests). Patches welcome, I suppose. :-)

5:38 rhickey: cemerick: yes, I would love to see a test suite come together. OTOH, Clojure is a testament to the lack of necessity of such suites, and examples of the insufficiency of test suites abound :)

5:39 cemerick: patch is up, thanks

5:41 cemerick: rhickey: well, in some areas (genclass may be one of them), clojure is changing to rapidly to make having tests reasonable to begin with. Regardless of efficacy though, they certainly help give one a warm and fuzzy feeling prior to doing svn commit. :-)

5:41 thanks

5:43 rhickey: cemerick: agreed, I'd run a test suite if I had one. I just find the current test-obsessed culture amusing, as no one questions the relentlessly mutable spaghetti mess they are testing in the first place

5:47 cemerick: the TDD police would definitely sneer at our test approach, which only tests external API points and results. If we did "proper" unit testing, our test suites would outweigh our "real" code 10:1.

5:49 rhickey: TDD people working in imperative languages have missed the big picture

5:52 TDD and unit tests also focus on too fine a granularity. Real systems have problems in the large, not in the small - e.g. correctly defined functions being passed the wrong data, or being called at the wrong time or in the wrong order, or not being called when required etc etc, none caught by unit tests

6:01 cemerick: Right, which is why we only test those user-visible results. If there's an actual problem, we trace things back. Putting together suitable mocks to do real function-level testing would be essentially impossible.

6:01 rhickey: that seems totally reasonable

6:02 cemerick: rhickey: it would be handy to have a "boolean isStrict ();" method on Delay, so instances can be unpacked safely; does this sound reasonable?

6:03 rhickey: cemerick: what doe isStrict mean?

6:03 does

6:06 cemerick: rhickey: a delay is "made strict" if it's evaluated -- so its fn is null, and the val != null (perhaps my terminology here is off); this allows the value to be unpacked from the delay, and passed around as a regular value. The upside is being able to minimize the locking on each get() call.

6:09 fwiw, the unpacking likely wouldn't happen in userland code -- I'd like to use an isStrict method in genbean, so provided properties can be values or delayed fn's, and the delayed values can be unpacked when the map is "updated"

6:09 rhickey: cemerick: there won't be a way to answer isStrict correctly without a memory barrier like synchronized. However, your presumption that that involves a lock is incorrect. Non-contended synchronized blocks are extremely fast, on par with volatile now, and nothing you should worry about.

6:11 cemerick: Interesting. That is true in JDK 1.5+, I presume...

6:12 * cemerick really needs to get his head out of 1.4, etc

6:12 rhickey: right, and gets better all the time

6:59 lisppaste8: cemerick pasted "is there something like this in clojure or contrib already?" at http://paste.lisp.org/display/64677

7:01 cemerick: I didn't see anything like that floating around already -- seems like a useful addition to some namespace in contrib, though I don't know which one.

7:16 blackdog: is it possible to get a full stack trace from (agent-errors) right now i just see an error message no line #s?

7:36 rhickey: cemerick: as is, I see problems with that as fns are perfectly fine values

7:37 cemerick: rhickey: oh, sure. But sometimes you know that a slot in a map (or whatever) can be a non-fn value or a fn that returns such a value, so that's a clean shorthand for that.

7:43 rhickey: blackdog: those are exceptions on which you can call printStackTrace etc

7:45 cemerick: I think that might be an ok function on IRefs (I know I recently took out IRef as Delay base, not knowing what yet to do with validators there), but not on fns

7:47 cemerick: rhickey: I wasn't suggesting it as an addition to a Java interface or class, fwiw

7:47 it seems thoroughly useful just as a clojure fn

7:55 rhickey: cemerick: I understand, as a Clojure fn, but I disagree about its generality, since it rules out fns as values

7:59 cemerick: rhickey: yeah, if you wanted to use that function with a collection that contains fns as values, then you'd be disappointed. I'm using it to support providing delays as values to genbean class constructors, where the corresponding accessors simply will never be IFn or any derivative, so it's safe.

7:59 In that context, if you *did* want to have a property return a fn, you'd have to wrap your fn with another thunk.

8:05 rhickey: cemerick: begs the question of what function? does

8:06 cemerick: but if Delay was once again IRef, you could test for that, much more generally

8:06 cemerick: rhickey: Oh, sorry, function? is from contrib/pred

8:07 it's true only for IFn's

8:07 rhickey: That's going to catch a lot of types, including keywords and symbols

8:08 jcrites: what happens when you invoke() keywords and symbols?

8:09 cemerick: ...and non-zero-arg fn's, for that matter.

8:09 jcrites: keywords and symbols are functions of maps -- return the value they're mapped to.

8:09 rhickey: jcrites: they presume the next arg is associative and look themselves up in it

8:09 blackdog: rhickey, ah thanks

8:11 cemerick: rhickey: I guess I would ask: what should I be doing, given collections of *potentially* lazy values that need to be resolved to strict values at some point?

8:22 dkf: hello

8:23 I need to study up on syntax conventions for clojure/lisp, like indentation and when to use new lines, etc. Anyone have any links?

8:25 back

8:26 blackdog: dfk best study boot.clj, or the contrib library

8:26 dfk http://clojure-contrib.svn.sourceforge.net/viewvc/clojure-contrib/trunk/

8:32 rhickey: cemerick: the resolving is the tricky part - usually they would either be uniformly wrapped or not. Here you are saying some are wrapped/delayed, and some not. You could test for Delay, I guess.

8:33 dkf: blackdog: thanks

9:16 cemerick: rhickey: interesting, I would actually say the opposite -- usually only a couple of values are delayed. I'll have to think about whether or not requiring the thunks to be delays would satisfy all of the use cases we have.

9:50 StartsWithK: hi

9:50 after another day of trying myself, I faild again at trying to make clojure work with osgi

9:51 so is there any example how this should work

9:51 or explanation why it can't

9:51 rhickey: StartsWithK: why is it different from any other Java library?

9:52 StartsWithK: i think it has to do with RT class

9:53 in knopflerfish implentation there are some errors with class loader

9:53 in equinox RT class can't be initialized

9:54 at this point i have clojure.jar as bundle registered, clojure.jar included inside my bunde and clojure.jar merged with my bundle

9:54 non of them will give me any way initialize RT class

10:03 rhickey: I don't know anything about OSGi, but when I do this search I see it is a common problem, solved in Equinox by something called buddy classsloaders? http://www.google.com/search?hl=en&q=equinox+osgi+static+initializers&btnG=Search

10:17 StartsWithK: hmm.. i don't think i have knowledge to understand osgi, java or clojure in that deepth.

12:55 ericthorsen: rich: I'm loading files with fully qualified namespaces in them but I still just see the file name with no path prefix. I was expecting to see the same as what I see for the clojure files. Do I need to compile/load them differently?

12:55 rich:clojure/boot.clj

12:57 rhickey: eric: are you saying you are loading with (load-file "a/full/path/foo.clj")?

12:57 ericthorsen: yes

13:01 rhickey: is that wrong?

13:01 rhickey: no, just looking to see what might be different - where are you saying you are seeing something different?

13:03 ericthorsen: rhickey: when i load a fully pathed file with a honker namespace org.enclojure.platform.utils.utils.clj I expected to see org/enclojure/platform/utils/utils.clj as the file name. I just see utils.clj

13:03 rhickey: as the file name where? there are 2 names in the smap

13:03 one is always the simple name, the other the path

13:04 ericthorsen: rhickey: I' calling into the jdi functions so I do not see that. I just noticed the file names on the clojure meta data were different in this way and that the jdi function calls seem to work when I follow the meta data named files

13:05 rhickey: so calling for line locations using clojure/boot.clj works, boot.clj does not (matching what the meta data has)

13:06 rhickey: ok, I see the boot.clj etc incorrectly have clojure/ before the file name in the simple name, should only be in the path part

13:06 ericthorsen: ok

13:07 rhickey: ok...just looking for consistency

13:07 thanks

13:07 rhickey: I'll fix, one minute

13:08 ericthorsen: np

13:19 rhickey: eric: fix is up

13:26 cemerick: I'd like to run a clj script that resides in a jar -- at the moment, I'm piping forms to Repl to load the file using RT.loadResourceScript -- any other suggestions short of offering up a ClasspathScript class, etc?

13:27 ericthorsen: rhickey: thanks!

13:31 rhickey: cemerick: app that needs to do this is started how?

13:31 cemerick: rhickey: command line or ant

13:32 rhickey: Oh, this script in the jar is the app you want to run?

13:32 cemerick: yup

13:34 rhickey: I guess to make it transparently like Java to users you could genclass a class with a main

13:35 If you want to put a bunch of cljs and pick from command-line arg, then something like ClasspathScript

13:37 cemerick: this isn't for external consumption, but the former may very well be easiest; though the latter will be necessary eventually.

13:39 rhickey: cemerick: you could write the latter with the former

13:39 cemerick: very true. This isn't something you'd want alongside clojure.lang.Script?

13:40 (i.e. a java impl, not a gen-class classfile)

13:40 rhickey: cemerick: It really should be a variant of clojure.lang.Script, or an enhancement to it

18:04 * slava is studying clojure

18:04 slava: err

18:04 clojure's persistent hashes

18:09 wybiral: slava, clojure is really cool in that sense

18:44 slava: i find java code hard to understand sometimes

18:51 wybiral: slava, yes, me too :)

19:19 arohner: I really wish there were a good replacement to SQL...

19:19 I'm writing an app in clojure, and I really wish I could write queries in clojure

Logging service provided by n01se.net