From: Ian Price <ianprice90@googlemail.com>
To: guile-user@gnu.org
Subject: Higher order modules: a first stab
Date: Fri, 09 Mar 2012 13:51:51 +0000 [thread overview]
Message-ID: <87obs5991k.fsf@Kagami.home> (raw)
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"
next reply other threads:[~2012-03-09 13:51 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-03-09 13:51 Ian Price [this message]
2012-03-21 19:16 ` Higher order modules: a first stab Ludovic Courtès
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.gnu.org/software/guile/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87obs5991k.fsf@Kagami.home \
--to=ianprice90@googlemail.com \
--cc=guile-user@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).