tommaisey
tommaisey

Reputation: 459

Scheme: reading files at macro expansion time

I'm using Chez Scheme and I'd like to introduce some top-level bindings based on the contents of a directory. The usage of this hypothetical macro might look like this:

(bind-files f "~/my-dir/")

;; Expanding to:
(begin (define f0 "~/my-dir/a.wav")
       (define f1 "~/my-dir/b.wav"))

I'm getting comfortable with syntax-case, datum->syntax and with-syntax as described in the Scheme book's examples. But I can't imagine how one could create identifiers based on the result of something 'runtime-y' like (directory-list "~/") - is it even possible?

(By the way, this is for a live-coding musical application, so there's no need to comment that this is a bad idea for reliable software - it's for a very specific interactive context.)

Upvotes: 1

Views: 782

Answers (1)

Takashi Kato
Takashi Kato

Reputation: 646

You can use something like this macro:

#!r6rs
(import (rnrs) (chezscheme))

(define-syntax bind-file
  (lambda (x)
    (define (name&file k dir)
      (define (->fn i)
        (string->symbol (string-append "f" (number->string i))))
      (let ((files (directory-list (syntax->datum dir))))
        (datum->syntax k (do ((i 0 (+ i 1)) (files files (cdr files))
                              (r '() (cons (list (->fn i) (car files)) r)))
                             ((null? files) r)))))
    (syntax-case x ()
      ((k dir)
       (string? (syntax->datum #'dir))
       (with-syntax ((((name file) ...) (name&file #'k #'dir)))
         #'(begin (define name file) ...))))))

(bind-file ".")

#|
;; depending on the number of files
f0 ... fn variables are defined.
|#

Upvotes: 1

Related Questions