Gauche の手続き : 3
呼称: ローカル変数と可変長引数
目的: ローカル変数とスコープ、可変長引数の取得方法を学ぶ
ローカル変数には let 式を使用します。
;; <初期値式> が評価され、その値が <変数> に束縛される ;; これが一般形? (let ((<変数1> <初期値式1>) (<変数2> <初期値式2>) ・・・ (<変数N> <初期値式N>)) <式> ...) ;; <初期値式> の評価順序を保証する (let* ((<変数1> <初期値式1>) (<変数2> <初期値式2>) ・・・ (<変数N> <初期値式N>)) <式> ...) ;; <変数1> 〜 <変数N> が見えているスコープで ;; <初期値式1> 〜 <初期値式N> を評価する (letrec ((<変数1> <初期値式1>) (<変数2> <初期値式2>) ・・・ (<変数N> <初期値式N>)) <式> ...)
letrec は <初期値式> が lambda 式である場合や「ローカルな再帰手続き」を書くのに有効です。内部的には、ローカル手続きは letrec 式へ展開され、let 式は lambda 式へと展開されるようです。
;; lambda 式と let 式の表記、内容は等価 gosh> ((lambda (a b) (+ a b)) 1 2) gosh> (let ((a 1) (b 2)) (+ a b)) 3 ;; ローカル手続きと letrec 式の表記、内容は等価 (define (revl lis) (define (revl-rec init lis) (if (null? lis) init (revl-rec (cons (car lis) init) (cdr lis)))) (revl-rec '() lis)) gosh> (revl '(1 2 3)) (3 2 1) (define (revr lis) (letrec ((revr-rec (lambda (init lis) (if (null? lis) init (revr-rec (cons (car lis) init) (cdr lis)))))) (revr-rec '() lis))) gosh> (revr '(1 2 3)) (3 2 1)
次に可変長引数を取る手続きの定義です。
;; 「2個以上の引数」 (define (func a b . c) ...) または (define (func (lambda (a b . c) ...)) ;; 「0個以上の引数」 (define (func . a) ...) または (define func (lambda a ...))
練習問題。
;; 引数をリストで返す手続き list を定義する (define my-list (lambda a cons '() a)) gosh> (my-list 1 2 3) (1 2 3) gosh> (my-list 1) (1) gosh> (my-list) ()