Scheme演習 FAQ

原 謙治

Q. defineの挙動が謎です

なぜ Chez Schemeで
> (define x (+ 0 1))
> (define y x)
> x
1
> y
1
としたり
> (define (test1)
        (define x 1) ;; x を定義
        (define y x) ;; y を定義
        ;; 以下定義されたxとyを表示
        (display (list x y))
        (newline)))
> (test1)
(1 1)
とした場合は x = 1, y = 1となるのに
> (define (test2)
        (define x (+ 0 1)) ;; x を定義
        (define y x)       ;; y を定義
        ;; 以下定義されたxとyを表示
        (display (list x y))
        (newline)))
> (test2)
(1 #<void>)
とした場合は y が 1 に定義されないのでしょうか? (guileではエラー)
しかもGambit SchemeやGaucheを使うと y は 1 に定義されています。

A. let* を使いましょう

処理系は実装しなくてもよい機能なのです

トップレベルのdefineとネストされたdefine

例: nest-define-example

この関数を実行するとどんな出力になるか考えてみてください。
(define (nest-define-example)
        (define x 1) ;; x を 1 で定義
        (define y x) ;; y を x の値で定義
        (define z y) ;; z を y の値で定義
        ;; x y z のリストを表示
        (display (list x y z))
        (newline))

定義時の処理と実行時の処理

nest-define-exampleの定義時の処理

> (define (nest-define-example)
        (define x 1) ;; x を 1 で定義
        (define y x) ;; y を x の値で定義
        (define z y) ;; z を y の値で定義
        ;; x y z のリストを表示
        (display (list x y z))
        (newline))

nest-define-exampleの実行時の処理

> (nest-define-example)

結果

(1 1 #<void>)
が出力されます

解決方法

> (define (nest-define-example)
        (let* ((x 1) (y x) (z y))
          (display (list x y z))
          (newline)))
> (nest-define-example)
(1 1 1)

Q. Cの構造体みたいなのはないの?

A. あるといえばあります

いることが多いので使ってみるといいでしょう

ベクタによる実装

;; point構造体の定義
(define (make-point x y)
	(vector x y))
;; x座標の取り出し
(define (get-x point)
	(vector-ref point 0))
;; y座標の取り出し
(define (get-y point)
	(vector-ref point 1))
;; x座標の破壊的代入
(define (set-x! point x)
	(vector-set! point 0 x))
;; y座標の破壊的代入
(define (set-y! point y)
	(vector-set! point 1 y))
;; 座標表示関数
(define (print-point point)
	(display "x=")
	(display (get-x point))
	(display ",y=")
	(display (get-y point))
	(newline))

;; 以下動作確認用プログラム
(define sample
	(make-point 0 1))
(print-point sample) ;; x=0,y=1
(set-x! sample 2)
(print-point sample) ;; x=2,y=1

その他応用

なんでもとることができます