#clojure logs

2008-07-23

02:13ChouserI can't think of how to use any of the existing persistent structures as a queue efficiently.
02:14Chousera subvec keeps a reference to the original vector, right? Otherwise it'd be perfect.
02:17ChouserYep, SubVector has the original vector, a start index, and an end index.
02:19ChouserSo how can I let dequeued items be GC'ed without mutating or copying the whole queue?
10:02meredyddOut of interest, is there a Clojure-idiomatic HTTP client library about the place, for playing with RESTish stuff?
10:22cemerickit seems that in-ns doesn't have any effect within a do block, i.e. (do (in-ns 'blah) (def name 5)) throws: java.lang.Exception: Name conflict, can't def name because namespace: user refers to:#'clojure/name
10:23cemerickThe same thing happens if I use binding to set *ns* for the scope that the def is in. What am I missing here?
10:35Chousercemerick: I wonder if the name is resolved compile time, such that you need to drop back up to the top level before any changes to *ns* take effect?
10:36ChouserIt's not clear to me why you can't use fully-qualified names in def.
10:36cemerickChouser: Yeah, that's what I figured.
10:37cemerickThat would be nice.
10:40cemerickThe big fallout from the way those names are resolved is that you can't fiddle with any other namespace, short of evaling defs, etc.
10:41Chousermaybe that's the point. still, it doesn't really protect much since any file can drop into any namespace and start def'ing
10:43cemerickyeah, it only limits certain macros
10:43Chouseroh, I see. yeah, good point.
10:45cemerickallowing fully-qualified names in def is the maximally-effective solution. There may well be an implementation detail that makes that undesirable.
10:47Chouserthe errors you get appear to be very specific, as if rhickey considered that option and explicitly rejected it
10:47ChouserI don't think I've read an explanation anywhere though.
10:47cemerickwe can tag-team him when he returns ;-)
12:11cemerickis this the only way to get a reference to the class for Object[] (for example): (. Class (forName "[Ljava.lang.Object;")) ?
12:44Chouser(class (to-array []))
12:44Chouseryours might be better, but there's another option anyway.
12:46Chouser(class (into-array [0])) ==> class [Ljava.lang.Integer;
13:22nchubrichHi, has anyone encountered problems using JLine with clojure?
13:22nchubrichSpecifically, I followed all the instructions on the group:
13:22nchubrichjava -cp jline-0.9.94.jar:clojure.jar jline.ConsoleRunner clojure.lang.Repl
13:23nchubrichin the directory with both jars:
13:23nchubrichCPL.TXT changes.txt jline-0.9.94.jar readme.txt target
13:23nchubrichbuild.xml clojure.jar pom.xml src
13:24nchubrichand get:
13:24nchubrichException in thread "main" java.lang.ClassNotFoundException: clojure.lang.Repl
13:27Chousernchubrich: sorry, I don't know. I use rlwrap instead of jline
13:28Chouserrhickey: have you explained somewhere why (def my-ns/foo) is disallowed?
13:29nchubrichYes, rlwrap definitely works better; but for some reason JLine works better with Emacs
13:29nchubrich(I have a friend who got it on his system, but for some reason doesn't work on mine.)
13:32fyuryunchubrich: you have svn version of Clojure?
13:33rhickeyChouser: there isn't a firm position there, mostly denied conservatively. One issue would be, locality of namespace definition - if anyone can inject into a namespace from any other it will be difficult for tools
13:33nchubrichI don't think so, but it's build 20080612
13:33fyuryunchubrich: I remember having some problems with jline, but that was some time ago, it works now
13:34Chouserok. cemerick was apparently trying to do something in a ns via a macro, but I'm not sure what.
13:34nchubrichfyuryu, do you think SVNing it would help for some reason?
13:35fyuryunchubrich: yeah, that date sounds about right, try the svn version
13:35nchubrichI haven't put jline.jar in my system-wide extensions library; that seemed to cause problems so the group said.
13:36rhickeyChouser: you were looking for a queue? You could try clojure.lang.PerisistentQueue
13:37fyuryunchubrich: I have jline in the same directory as clojure.jar. And use the scripts from the wiki
13:43nchubrichthanks for your help fyuryu, I'm going to try SVN....
13:49cemerickrhickey: what Chouser was referring to was a situation where a macro was looking to use gen-and-load-class, and also populate the necessary namespace that the gen-class'ed class would look in for method impls. Short of requiring the macro to be used from within the class namespace, the macro would either need to be able to def fully-qualified names, or be able to use in-ns in a try/finally so as to restore *ns* after populating the namespace.
13:52rhickeycemerick: you mean (bind [*ns* blah] ...) ?
13:56cemerickrhickey: I tried that; doesn't appear to work: (binding [*ns* (find-ns 'blah)] (def foo 5)) => #'user/foo
13:56cemerickmaybe I'm missing something...?
13:57ChouserIs (conj (clojure.lang.PersistentQueue/EMPTY) ...) the Right Way to create one?
13:57cemerick(FWIW, namespace 'blah does already exist)
13:58rhickeyyou're not, that won't work because all the names involved are resolved at compile-time but the binding happens at run time, and is a common error
13:59rhickeygen-class et al are a good example of where one ns is defining another
14:00cemerickYeah, I see why that doesn't work; I could eval all of the defs, but that's pretty irritating.
14:01rhickeycemerick: but aren't you in a macro?
14:02cemerickrhickey: yes; its forms are still subject to *ns*, though, right? Perhaps my macro-fu is weak.
14:02rhickeyChouser: yes, then you can use the conj/pop protocol
14:02Chouserrhickey: ok, thanks.
14:03Chouserit's count appears to including counting a seq -- not constant time?
14:03Chouserits
14:05rhickeyChouser: no, many seqs have constant-time count, including vector's
14:07rhickeycemerick: yeah being in a macro doesn't help
14:08cemerickrhickey: ok, glad I'm not losing it
14:09cemerickrhickey: FWIW, I've got a first pass of a 'defbean' macro working that does what we discussed last night, but it's less than ideal. Having to coordinate the namespaced impl. as well as ensure that the class in question isn't loaded twice makes for a hairy mess, really.
14:09rhickeycemerick: does defbean generate a bean on disk or immediately loaded?
14:10cemerickrhickey: right now, it's immediately loaded. We have a build process and such that coordinates where and when gen-class stuff is saved off, but I've been trying to not use that so defbean could be generally applicable.
14:11rhickeycemerick: who could consume the named members of such a bean (unless there is an interface defining them)?
14:12cemerickLooking back over our use-cases this morning, always having a Java interface for each entity we're interested in is common, so I may just downshift into using proxy to build the PSM subclass off of a given interface.
14:13rhickeycemerick: for dynamic beans that's all that makes sense to me
14:13cemerickrhickey: no one, unless we're saving the classes
14:15cemerickI'll have to go over our models and see whether simply referring to a concrete, gen-class'ed impl is something that would be beneficial. It's certainly irritating to have to have a pile of interfaces for every entity (compared to having the option of having them pop out concretely from clojure).
14:16rhickeycemerick: or do you want gen-interface?
14:16cemerickrhickey: I've *always* wanted gen-interface :-)
14:16rhickeycemerick: what were the loaded-twice issues?
14:17cemerickrhickey: Nothing super-complex -- the jvm would just throw a duplicate class def exception after a second eval of the defbean macro. Fixed with a check for the class that defbean emits via gen-class.
14:18cemerickrhickey: FWIW, what I really want is a gen-class that carries method impl's around with it, a la proxy.
14:18cemerickI know that opens up a whole other can of worms, tho.
14:19rhickeycemerick: but does defbean allow a change in signature, i.e. adding methods? if so people will expect it to be able to be run more than once
14:20cemerickrhickey: No. Another vote for either using proxy, or always saving the generated class.
14:22rhickeygen-and-load-class is very limited, because Java is limited in supporting static class names + dynamic signatures
14:24rhickeycemerick: as I said to Chouser, the prohibition on defs of explicitly-qualified names is conservatism on my part
14:25Chouserconsider yourself tag-teamed.
14:25cemerickChouser: :-P
14:26rhickeyone issue is the fact that all of the names in any such definition will be resolved in *ns*, not the ns of the def'ed var
14:26cemerickrhickey: Given some of the example code I've seen on the group of late, I don't blame you at all. I do think there has to be some mechanism for safely def-ing fully-qualified names, though.
14:27cemerickmaybe have a *def-ns* that we can bind, so that def-ed symbols are resolved there, but all others are resolved in *ns*?
14:28rhickeycemerick: still very confusing, for me too
14:28cemerickThat feels over-complicated, though
14:31ChouserI would be very surprised if *ns* was 'user and (def foo/bar baz) was refering to any baz other than user/baz
14:31rhickeycemerick: want to past defbean so I can see what you are up against?
14:32rhickeyChouser: what about (def foo/bar bar) ?
14:33ChouserI really wouldn't expect any fully-qualified name to early in an expression to change the ns used by later symbols.
14:33Chousernow if it was (def-in-ns foo bar bar) ... then I would start to wonder.
14:34rhickeyChouser: (defn foo/bar [] .... (bar))
14:35Chouseryeah, I would expect to have to say (foo/bar), though I'm sure that would be a common mistake.
14:35rhickeyChouser: I'm not disagreeing, just highlighting what are likely to be the points of confusion
14:36cemerickrhickey: Yeah, I'll paste it in 5 min. It's a pretty ugly baby. :-)
14:36Chousermaybe not as common as forgetting to (refer 'clojure) after my (in-ns ...), but still common.
14:37cemerickIMO, def-ing a fully-qualified name is definitely an edge case -- I wouldn't expect it to be available by default. This is how I came to my *def-ns* suggestion.
14:40Chouserthis would be a possible solution for the gen-class namespace pollution as well.
14:40Chouseras opposed to method function-name mangling.
14:40rhickeyChouser: how so?
14:42Chouserif I genclass namespace fooclass, instead of then wanting to do (in-ns 'fooclass) (refer 'clojure), I could stay in my 'user ns (or where-ever) and do (defn fooclass/methname1 ...)
14:43Chouserdid that make any sense?
14:44rhickeyChouser: except it's not fooclass, it's com.company.package.Classname, and there's no ns in which to alias it!
14:45Chouserwhy couldn't I alias it? but even without that, I'd rather use a long name for each method def, than sprinkle clojure/ all through my code.
14:46Chousergranted mangling each method name with a leading . would be nicer than either. :-)
14:46rhickeyChouser: your straw man was function name mangling, which wouldn't require that
14:47rhickeyChouser: also, you'd have to qualify all helper fns etc
14:47ChouserI didn't mean to claim fully-qualified def was better than mangling, just that it could also solve the problem.
14:47Chouserindeed.
14:47lisppaste8cemerick pasted "defbean first cut" at http://paste.lisp.org/display/64107
14:49cemerickrhickey: so, it's a bit of a mess at the moment, but there are enough issues that I think it's worth not pursuing with the current state of things (in favor of an interface/proxy impl)
14:50cemerick(it's also possible that I've made a hash of it)
14:54rhickeycemerick: so it create a class with the same name as *ns*?
14:54cemerickrhickey: yes; it seemed like the only reasonable approach given the fully-qualified def issue
14:55rhickeyright, just trying to understand
14:55rhickeyyou'd have preferred taking a class name too?
14:57cemerickwell, that's not really settled yet -- I've seen a lot of code around that keeps all of the gen-class stuff in one file, in one namespace, and our approach is to put any gen-class in its own -gen.clj file (which makes the build process identify what generates classfiles, and what just needs to be loaded as a sanity check and to see about reflection warnings). Providing a classname to defbean certainly makes it clearer what's going on under the covers.
14:59kotarakis there a way to use apply with . besides (eval `(. ~obj foo ~@args))?
15:02rhickeykotarak: (defn jcall [obj name & args]
15:02rhickey (clojure.lang.Reflector.invokeInstanceMethod
15:02rhickey obj
15:02rhickey (str name)
15:02rhickey (if args (to-array args) (clojure.lang.RT.EMPTY_ARRAY))))
15:02rhickey(defn jfn [name]
15:02rhickey #(apply jcall %1 name %&))
15:03kotarakwow. thanks :)
15:44rhickeyso who's gonna write the macro's to gen gxp? http://code.google.com/p/gxp/
15:49cemerickrhickey: since we have Class/field access (i.e. Math/PI), can we reclaim '.' so that it invokes methods on java.lang.Class? i.e. this doesn't work (.getMethods String)
15:55ChouserCompile-time type checking, lightweight runtime system -- is this a template or programming language?
16:17rhickeycemerick: (macroexpand '(Math/random))
16:18rhickeyChouser: it's your typical server pages thing except:
16:18rhickeyit's functional
16:18rhickeyit's compiled
16:19rhickeythe resulting compiled classes can be consumed from Java/Clojure
16:19cemerickrhickey: OK, I deserved that :-)
16:21cemerickhowever, I'm confused in general. (.getName String) => Exception, and (.getName (class String)) => "java.lang.Class"
16:21rhickeycemerick: just wanted to show it is still not syntax, just a transformation. Making it first class could complicate code walkers etc, which for now can just call macroexpand and get the canonic form. I agree, (. classname static-member) is not otherwise preferable in any way to classname/static-member
16:22rhickey. has special evaluation rules, if its first argument looks like a classname, it's considered a static call
16:22rhickey(. String getName) - static call to getName method on String (doesn't exist, error)
16:23rhickey(. (class String) getName) -> the class of the String class object is Class
16:23cemerickheh, this works: (defn foo [c] (.getName c)) (foo String)
16:24cemerickyeah, I see what was going on there, I was just assuming that there was something more complicated going on
16:28rhickey(. classname member) predated class object literals, but the fundamental problem is Java's, which uses class names as scopes - I guess I could force everyone to use String.class to name the class object, like Java does
16:29rhickey(just kidding)
16:30cemerickbut only a little, right? :-)
16:30rhickeycemerick: that's how it started out, no class literals, and (class String) meant String.class
16:31cemerickyeah, I was mostly winking towards the "it's Java's fault"
16:31rhickeynow (class String) means (.getClass String) and String means String.class
16:31rhickeyoh, it's definitely Java's fault
16:31rhickey:)
16:32cemerick:-)
16:32cemerickrhickey: I've been meaning to ask you about future generics plans (if any)...
16:34rhickeycemerick: my plan is to pray they never move away from type erasure for generics. Without it lots of Clojure's interop would be horribly type-burdened. This was a major factor for me in dropping .Net. Generics are bad for dynamic languages, after all, they are only about types.
16:38cemerickI've spent some not-inconsiderable amount of time in scala-land, so I'm not averse to types (and like them on occasion). I wouldn't mind eventually seeing a dynamic-friendly type system in clojure (perhaps implemented as a plugin for a future componentized clojure compiler). I'm obviously not asking you for this, though.
16:54rhickeycemerick: I'm not likely to settle for types - I just don't think they give the required benefits. If you look at something like the PLT contracts, Eiffel pre/post conditions, predicate dispatch, Qi's superimposable sequent-calculus based system etc, there are some cool ideas.
16:55rhickeyI am in favor of programmers being able to assert things about their code and the compiler/runtime system assisting them.
20:24rhickeyI've added validators for vars/refs/agents - an optional second arg for agent and ref, get/set-validator, also shutdown-agents