モジュールの作り方と使い方

さて、本を読み進めるうちに書くコードも長くなってきた。たとえば前のエントリで書いた関数 o= は32行ある。だけど、本質的な部分はテスト用コードと空行を含めても11行だ。残りは、o= を作るための補助的というか基本的な関数のコードで占められている。こういうコードは冗長なだけでなく、コードを見難くする。

というわけで、基本的な関数はモジュールにして外に追いやりたいと思ったので、Gauche でのやり方を調べてみた。

 cf. 4.11 モジュール ― Gauche ユーザリファレンス
 cf. 3.1 Gaucheを起動する ― Gauche ユーザリファレンス

簡単な作り方と使い方をまとめると、次のようになる。

  1. define-module を使ってモジュールを定義し、中に関数の定義を書く。
  2. 上記の中で export-all を使って、定義した関数をエクスポートしておく。
  3. 適当なファイル名で保存する。
  4. モジュールを使う側のファイルで、(use モジュール名) とする。
  5. gosh を起動するときに -I. オプションをつける。”.” はモジュールがカレントディレクトリにある場合。

で、今まで書いた基本的な関数をまとめたモジュールがこれ。モジュール名は mymodule とした。

(define-module mymodule

(define atom?
  (lambda (x)
    (and (not (pair? x)) (not (null? x)))))

(define lat?
  (lambda (l)
    (cond
      ((null? l) #t)
      ((atom? (car l)) (lat? (cdr l)))
      (else #f))))

(define add1
  (lambda (n)
    (+ n 1)))

(define sub1
  (lambda (n)
    (- n 1)))

(define o+
  (lambda (n m)
    (cond
      ((zero? m) n)
      (else (add1 (o+ n (sub1 m)))))))

(define o-
  (lambda (n m)
    (cond
      ((zero? m) n)
      (else (sub1 (o- n (sub1 m)))))))

(define o*
  (lambda (n m)
    (cond
      ((zero? m) 0)
      (else (o+ n (o* n (sub1 m)))))))

(define o>
  (lambda (n m)
    (cond
      ((zero? n) #f)
      ((zero? m) #t)
      (else (o> (sub1 n) (sub1 m))))))

(define o<
  (lambda (n m)
    (cond
      ((zero? m) #f)
      ((zero? n) #t)
      (else (o< (sub1 n) (sub1 m))))))

(define o=
  (lambda (n m)
    (cond
      ((o> n m) #f)
      ((o< n m) #f)
      (else #t))))

(export-all))

テスト用スクリプト:

(use mymodule)

(print (atom? 'a))
(print (lat? '(my name is takatoh)))
(print (lat? '(my name (is) takatoh)))
(print (o+ 2 5))
(print (o- 10 4))
(print (o* 3 3))
(print (o> 12 8))
(print (o< 7 10))
(print (o= 6 6))

試してみよう。

^o^ > gosh -I. test_mymodule.scm
#t
#t
#f
7
6
9
#t
#t
#t

うまくいってるようだ。
このモジュールは、スクリプトモードだけでなくインタラクティブモードでも使える。

^o^ > gosh -I.
gosh> (use mymodule)
#
gosh> (atom? 'a)
#t
gosh> (lat? '(hello scheme))
#t
gosh> (o= 3 7)
#f

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください