alex@umbc4.umbc.edu (Alex S. Crain) (03/04/91)
Newsgroups: comp.lang.scheme Subject: modularization of scheme code Summary: Expires: Sender: Reply-To: alex@umbc4.umbc.edu.UUCP (Alex S. Crain) Followup-To: Distribution: world Organization: University of Maryland Baltimore County Keywords: I'm laying out a rather large project (an operation system) in scheme and I'm looking for a way to restrict the scope of some objects. In C++ or CLOS, I would use objects and methods, in vinnilla CL I would use packages. I can't find a good way to do this in scheme. For example: suppose I was writing window system, and I had written a module for screen management. I would have some local data objects (like the screen data and backing store data (after securing the appropriate patent licence from AT&T, of course). I would also have some local functions and finally, I would have some exported functionality (create-window, etc). I would rather not make my locally used functions and data structures public if I don't have to, both to avoid cluttering the namespace and just for general neatness. Scheme doesn't provide a way (that I know of) of hiding anything except by nesting itside a function, and even if I wrapped the entire module inside of letrec body I don't know how to make the date structures permentent, and I only get one entry point (yuk). Or should I build everything dynamically and export a series of continuations to use as entry points, ala: (define (init-screen non-local-exit) (letrec ((screen-data (make-vector ...)) (entry-points '(())) ... ) ;; ;; define the new entry points ;; (let ((x (call/cc (lambda (k) (cons 'init k))))) (case (car x) ((init) (set-car! entry-points (cdr x))) ((create-window) ...) ((delete-window) ...) ...)) (non-local-exit entry-points))) (define (go) (let ((screen-calls (call/cc (lambda (k) (init-screen k))))) ... (screen-calls 'create-window) ... (screen-calls 'delete-window))) So, pray tell, whats to scoop? I'm working out of R3.99rs, so if this is crystal clear in 4.0, just say so. ################################# :alex. #Disclaimer: Anyone who agrees # Systems Programmer #with me deserves what they get.# University of Maryland Baltimore County ################################# alex@umbc3.umbc.edu
gyro@cymbal.reasoning.COM (Scott Layson Burson) (03/05/91)
Date: 3 Mar 91 20:28:48 GMT From: "Alex S. Crain" <alex@umbc4.umbc.edu> I'm laying out a rather large project (an operation system) in scheme and I'm looking for a way to restrict the scope of some objects. In C++ or CLOS, I would use objects and methods, in vinnilla CL I would use packages. I can't find a good way to do this in scheme. A simple solution is to prepend a "package prefix" to each of your global symbols. The disadvantage of this approach vis-a-vis CL packages is that you must always include the "package prefix" when naming a symbol; there is no concept of a "current package" in the context of which the prefix may be omitted from symbols in that package. That may sound distasteful, but I have used this approach in Lisps without packages and found it workable. If you really want objects that behave like instances, here is an approach I have used in CL without CLOS: ;;; Do we have DEFSTRUCT in Scheme? Anyhow, you get the idea. (defstruct window ;; The slots are the operations, not the instance variables. expose move reshape ...) (define (create-window left bottom width height ...) (let (... other instance variables ...) (letrec ((expose (lambda () ...)) (move (lambda (new-left new-bottom) ...)) ... other operations ...) ;; Now we build an instance of the WINDOW structure using EXPOSE etc. (make-window expose move reshape ...)))) Here the instance variables are the arguments to CREATE-WINDOW along with any local variables bound in the LET. As you see, they are not accessible to the outside except by way of the operations you define. Now to invoke the MOVE operation on WIN: ((window-move win) x y) Note that this uses closures, but not continuations. -- Scott