From: Nikodemus S. <nik...@ra...> - 2005-11-16 22:15:44
|
There are a some of snags in our current setup that I'd like to address. 1. Nuking the asdf.fasl breaks REQUIRE of non-contrib modules. This is easy to fix by removing the conditionalization on SBCL_BUILDING_CONTRIB from ASDF and installing the require-hook unconditionally on SBCL. ...but presumably there was a reason why it was not made that way in the first place. Does anyone remember why? 2. When trying to package SBCL in a way that is ment coexist with another version of SBCL things get ugly very quickly for REQUIRE. Consider something like Swank -- both installed SBCLs will need their own versions. Currently to do this one must assume a great deal about the environment: nothing new pushed on either *MODULE-PROVIDER-FUNCTIONS* or *CENTRAL-REGISTRY* and no accidental symlinks to other versions of Swank in eg ~/.sbcl/systems/. If we supported something like (setf (module-provider :swank) (lambda (name) (assert (string= name :swank)) (load "path/to/right/swank-loader.lisp"))) that took precedence over *MODULE-PROVIDER-FUNCTIONS* ensuring sane behaviour would be a lot easier. How would people feel about the added complexity? This has some benefits for vanilla SBCL too: while it makes sense to allow users to override contrib modules with different versions, I submit that requiring a stronger statement of intent then pushing something ill-adviced to *central-registry* might be in order. Something like (setf (module-provider :asdf-install) 'load-the-portable-asdf-install) makes it pretty clear they know what they're doing, whereas (push #p"/local/lisp/systems/" asdf:*central-registry*) is probably just an oversight. 3. I'm also slightly suspicious of the way precedence of module provider functions work. While it is nice and simple it is also a bit untrackable. Unless you explicitly frob it you end up with a different precedence depending on the order you load stuff. While this is not a big problem per se, it rules out adding another provider as a workaround for 2. Cheers, -- Nikodemus Schemer: "Buddha is small, clean, and serious." Lispnik: "Buddha is big, has hairy armpits, and laughs." |
From: Pascal C. <pc...@p-...> - 2005-11-16 22:53:45
|
I don't completely undertand what you're trying to achieve, but maybe using an idiom common in the CLOS MOP could help. You could make require call a generic function require-using-system (or some such), and then get more fine-grained control over the behavior of require. Here is a sketch. (defvar *system* 'standard) (defgeneric require-using-system (system &rest args) (:method ((system (eql 'standard)) &rest args) ... standard behavior ...)) (defun require (&rest args) (apply #'require-using-system *system* args)) Then later on, you can define your own behavior like this: (defmethod require-using-system ((system (eql 'my-system)) &rest args) ... different approach ...) (let ((*system* 'my-system)) (require :whatever)) (This is basically a light-weight version of dynamically scoped functions, in the sense that also indirect calls to require will be affected. I don't think you need a class hierarchy here to make this work like in the xyz-using-class idiom, but eql specializers should be sufficient.) If this is besides the point then sorry for the fuzz... Cheers, Pascal -- Pascal Costanza, mailto:pc...@p-..., http://p-cos.net Vrije Universiteit Brussel, Programming Technology Lab Pleinlaan 2, B-1050 Brussel, Belgium |
From: Nikodemus S. <nik...@ra...> - 2005-11-17 07:29:13
|
On Wed, 16 Nov 2005, Pascal Costanza wrote: > I don't completely undertand what you're trying to achieve, but maybe using > an idiom common in the CLOS MOP could help. You could make require call a > generic function require-using-system (or some such), and then get more > fine-grained control over the behavior of require. Here is a sketch. Almost, but not quite. I'm trying to ensure that eg. (REQUIRE :SWANK) will get the right Swank no matter how many copies are lying around the file system, unless the user has gone out of his way to say that he really wants a different Swank. So dynamic scoping is not what I'm after. (setf *system* my-system) Globally frobbing *SYSTEM* has the same problem as the current approach: any further modifications to REQUIRE by further specicalization are in danger of accidentally losing the magic I've hung on it. In scheme like yours if the module-name was canonized to a keyword by REQUIRE (something I'm not offhand sure we're allowed to do if it requires interning) I could use an EQL-specializer on the ones I care about to ensure correct behaviour, but I'm not sure I see the advantage. Variations like (defun require (name &optional pathnames) (or (require-from-pathnames name pathnames) (require-using-class name (find-module-class name))) ... (define-module-class important-module ()) (define-module-class swank (important-module)) (defmethod require-using-class (name (module-class important-module)) ...) would work too. If people find this less icky then (SETF MODULE-PROVIDER), then I'd be happy to implement something like this. Cheers, -- Nikodemus Schemer: "Buddha is small, clean, and serious." Lispnik: "Buddha is big, has hairy armpits, and laughs." |