読者です 読者をやめる 読者になる 読者になる

モジュールのこと

Scheme の S6RS や S7RS では モジュールの名前を (shell command) みたいにリストで表記する。
私が使っている Guile ではそういう風に表記するので、調べてみたら R6RS や R7RS のあれだった。

R6RS でも R7RS でもモジュールじゃなくてライブラリというらしい。
Guile のモジュールはこのように書ける:

(define-module (std io)
  #:export (print println))

(define* (print #:rest args)
  (define (recur xs)
    (if (null? xs)
        #f
        (begin
          (display (car xs))
          (recur (cdr xs)))))
  (recur args))

(define* (println #:rest args)
  (define (recur xs)
    (if (null? xs)
        (newline)
        (begin
          (display (car xs))
          (recur (cdr xs)))))
  (recur args))

Guile には printprintln も無いので書いてみた。
どちらも可変引数を取って、それを出力する。
この 2 つの違いは println が最後に改行することくらいだ。

次は R6RS で同じライブラリを書いたらどうなるか。さあ、どうだ:

(library (std io)
  (import (rnrs (6)))
  (export print println))

(define* (print #:rest args)
  (define (recur xs)
    (if (null? xs)
        #f
        (begin
          (display (car xs))
          (recur (cdr xs)))))
  (recur args))

(define* (println #:rest args)
  (define (recur xs)
    (if (null? xs)
        (newline)
        (begin
          (display (car xs))
          (recur (cdr xs)))))
  (recur args))

これでいけるはずなんだが、syntax error になってしまった。

(library (std io)
  (export print println)
  (import (rnrs base (6)))

  (define (print #:rest args)
    (let recur ((xs args))
      (cond ((null? xs)   #f)
            (else         (display (car xs))
                          (recur   (cdr xs))))))

  (define (println #:rest args)
    (let recur ((xs args))
      (cond ((null? xs)   (newline))
            (else         (display (car xs))
                          (recur   (cdr xs)))))))

名前付き let にしたけどやっぱりだめっぽい。
なんかよくわからん………。
define* が無いって表示されるけど、define にしたらダメだし……。