Higher order modules: a first stab
Hi guilers, I've been musing over the concept of higher order modules (modules parameterized by other modules) in the back of my mind, and am occasionally making steps towards implementing it in guile. I think that with guile's first class modules all the machinery is there, it's just a question of figuring out the best way to do it. The advantage for users of guile is that it provides a different, and hopefully useful, form of code reuse. Here is the first step towards it that I made. ;;; higher order modules for guile (define-syntax-parameter provide ; an "export" for `module' forms (lambda (stx) (syntax-violation 'provide "provide used outside a module form" stx))) (define-syntax module (lambda (stx) (syntax-case stx () ((module (params ...) body ...) (with-syntax (((tmp ...) (generate-temporaries #'(params ... #'(lambda (tmp ...) (define fresh (make-fresh-user-module)) (module-use! fresh (resolve-interface '(guile))) (save-module-excursion (lambda () (set-current-module fresh) (let ((export-alist '())) (syntax-parameterize ((provide (syntax-rules () ((provide foo bar (... ...)) (set! export-alist (append (list (cons 'foo foo) (cons 'bar bar) (... ... (define params tmp) ... body ... (map (lambda (pair) (let ((var (car pair)) (val (cdr pair))) (module-define! fresh var val))) export-alist) fresh)) ;; example module (define stream-utils (module (stream-car stream-cdr) (define (stream-drop s n) (if (zero? n) s (stream-drop (stream-cdr s) (- n 1 (define (stream-take s n) (if (zero? n) '() (cons (stream-car s) (stream-take (stream-cdr s) (- n 1) (provide stream-drop stream-take))) ;; first stream implementation ;; Stream a = Stream b (b -> a) (b -> Stream a) (import (rnrs records syntactic)) (define-record-type stream (fields val this next)) (define (stream-car stream) ((stream-this stream) (stream-val stream))) (define (stream-cdr stream) ((stream-next stream) (stream-val stream))) (define (constant-stream k) (define (next k) (make-stream k identity next)) (next k)) (define naturals (letrec ((next (lambda (current) (make-stream (+ 1 current) identity next (next -1))) (define stream-module (stream-utils stream-car stream-cdr)) (define stream-take (module-ref stream-module 'stream-take)) (stream-take naturals 10) ;;(0 1 2 3 4 5 6 7 8 9) ;; second stream implementation (use-modules ((ice-9 streams) #:renamer (symbol-prefix-proc 's:))) (define naturals2 (s:make-stream (lambda (x) (cons x (1+ x))) 0)) (define stream-module2 (stream-utils s:stream-car s:stream-cdr)) (define stream-take2 (module-ref stream-module2 'stream-take)) (stream-take2 naturals2 10) Currently, parameterized modules are functions that return a module, and functions are retrieved by module-ref. This is fine for a proof of concept, but hopefully I'll have something better integrated soon. Thanks to wingo for suggesting the current method of providing exports -- Ian Price "Programming is like pinball. The reward for doing it well is the opportunity to do it again" - from "The Wizardy Compiled"
Re: Problem with modules in Guile 2.0
Gubinelli Massimiliano writes: > Hi Mark, > thanks again. I start to understand better the Guile 2 compile > system. I decided to dig into boot-9.scm to have a more precise idea > of the ecosystem around my scripts. Unfortunately it seems that the > basic TeXmacs scripting infrastructure need a major change to be run > into Guile 2.0 and I'm afraid not to be sufficiently proficient in > scheme to do this in a short time. Why not convert your scripts to use the standard Guile module syntax? > Is there anyone on this list which would like to assist me to port GNU > TeXmacs to Guile 2.0. Currently the code in svn builds fine against > 2.0 so the problem is just to adapt the scheme scripts which rely on a > customized module system. I'd be glad to take a look. Where can I find your scripts? Regards, Mark
Re: Problem with modules in Guile 2.0
Hi Mark, On Mar 9, 2012, at 5:29 PM, Mark H Weaver wrote: > Gubinelli Massimiliano writes: > >> Hi Mark, >> thanks again. I start to understand better the Guile 2 compile >> system. I decided to dig into boot-9.scm to have a more precise idea >> of the ecosystem around my scripts. Unfortunately it seems that the >> basic TeXmacs scripting infrastructure need a major change to be run >> into Guile 2.0 and I'm afraid not to be sufficiently proficient in >> scheme to do this in a short time. > > Why not convert your scripts to use the standard Guile module syntax? > TeXmacs is currently composed of 250 scheme files for \sim 6 lines of scheme. Guile is used for customization and for other operations which do not require special performance. All the rest of the program is written in C++, in particular the typesetter and the GUI code. It has a slightly customized module system and features contextual overloading of functions (a function can be redefined to act differently is some condition is met without modifying the module which implemented the base behaviour). We would like to preserve the current system as much as possible. Moreover we want also to be compatible with previous versions of Guile (now we support Guile 1.4 up to Guile 1.8). The code does not depend very much on specific Guile features a part form the module system. >> Is there anyone on this list which would like to assist me to port GNU >> TeXmacs to Guile 2.0. Currently the code in svn builds fine against >> 2.0 so the problem is just to adapt the scheme scripts which rely on a >> customized module system. > > I'd be glad to take a look. Where can I find your scripts? > TeXmacs codebase is hosted at savannan (https://savannah.gnu.org/projects/texmacs/). Check out the svn trunk via svn co svn://svn.savannah.gnu.org/texmacs/trunk then you can find the scheme script in trunk/src/TeXmacs/progs at boot C++ evaluate init-texmacs.scm which in turn bootstrap the custom module system defined in kernel/boot.scm and start to load modules. We have a facility to lazy load modules since in old machines the bootstrap of the scheme code is too slow. With the current svn you will not be able to build TeXmacs with Guile 2.0. If you are interested in that I will tell you how to do. I still do not know very well the scheme code (almost all of it has been written by the main developer, Joris van der Hoeven). Massimiliano > Regards, > Mark