Gauche の手続き : 1

呼称: 手続きオブジェクト
目的: 様々な手続きを学ぶ

(define (add a b)
  (+ a b))

gosh> add
#<closure add>

手続きを評価すると、# が返される。#<...> は、リテラルで書けないオブジェクトを示す。

(define (<名前> <引数> ... ) <式> ...)

(define <名前> (lambda (<引数> ...) <式> ...))

「手続きの定義」はどちらも同じ事を表し、前者を MIT 記法と呼びます。

;; 以下の定義はどちらも
gosh> (define (add a b) (+ a b))
gosh> (define add (lambda (a b) (+ a b)))
gosh> (add 1 2)
3

;; lambda 式を評価すると #f が返される
gosh> (lambda (a b) (+ a b))
#<closure #f>

;; 簡単な手続きは lambda 式を使った方が簡潔
(define (length3 lis)
  (fold (lambda (a b) (+ b 1)) 0 lis))
gosh> (length3 '(1 2 3))
3

手続きとリストを引数に取る for-each や map といった組み込み手続きがあります。

(for-each <手続き> <リスト>)

(map <手続き> <リスト>)

両者の違いは、リストの要素に手続きを適用した結果を返すかどうかになります。map はリストで結果を返す。

gosh> (for-each (lambda (x) (print x)) '(1 2 3))
1
2
3
#<undef> ;; for-each の戻り値
gosh> (map (lambda (x) (print x)) '(1 2 3))
1
2
3
(#<undef> #<undef> #<undef>) ;; 戻り値がない場合は #<undef> になる?

gosh> (for-each (lambda (x) (+ x 1)) '(1 2 3))
#<undef>
gosh> (map (lambda (x) (+ x 1)) '(1 2 3))
(2 3 4)

練習問題にチャレンジ。

;; 数値とそれ以外が混ざったリストから数値だけに手続きを適用する
(define (for-each-numbers proc lis)
  (for-each (lambda (x) (if (number? x) (proc x))) lis))

gosh> (for-each-numbers print '(1 2 #f 3 4 #t))
1
2
3
4
#<undef>