グローバル変数を宣言し, それに値を結びつけるには define という命令を使う.
define は通常の変数の宣言の他に, 関数を定義するためにも使われる.
注意:
Scheme には関数と通常の変数の区別がない
hello.scm
1 2 3 4 5 6 | ; Hello Scheme World as a variable
(define vhello "Hello Scheme World")
; Hello Scheme World as a function
(define fhello (lambda ()
"Hello Scheme World"))
|
hello.scm の実行結果は:
guile> (load "hello.scm")
guile> vhello
"Hello Scheme World"
guile> fhello
#<procedure fhello ()>
guile> (fhello)
"Hello Scheme World"
注意:
fhello を手続きとして呼び出すためには (fhello) というように括弧でくくる.
引数を取る関数を定義するときは lambda の後ろに引数のリストを置けば, それが引数となる.
farg.scm
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | ; hello with name
(define hello
(lambda (name)
(string-append "Hello " name "!")))
; sum of three numbers
(define sum3
(lambda (a b c)
(+ a b c)))
; a + b
(define add
(lambda (a b)
(+ a b)))
; a - b
(define min
(lambda (a b)
(- a b)))
; a * b
(define mul
(lambda (a b)
(* a b)))
; a / b
(define div
(lambda (a b)
(/ a b)))
|
farg.scm の実行結果は:
guile> (load "farg.scm")
guile> (hello "feifei")
"Hello feifei!"
guile> (sum3 1 2 3)
6
guile> (add 1 2)
3
guile> (mul 1 2)
2
guile> (div 1 2)
1/2
任意個の引数をとる関数を定義することができる. ゼロ個以上の固定された引数に加えて, 個数が不定の引数 (レストパラメータ) をとることができる.
個数が不定の引数は, リストとして関数本体に渡る. 今までの説明範囲では使い道はないのであるが, 繰り返しや, 高階関数とともに利用するとエレガントなコードを書くことができる.
以下の例は, 関数に渡った引数をリストにして返す関数である. 3つの通常の引数とレストパラメータをとる. 通常の引数の後に, ドットで区切って, レストパラメータを書く.
args.scm
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | (define 3args+
(lambda (a b c . d)
(list a b c d)))
(define args0.1
(lambda ( . d)
(list d)))
(define args1.1
(lambda (c . d)
(list c d)))
(define args2.1
(lambda (b c . d)
(list b c d)))
|
args.scm の実行結果は:
guile> (load "args.scm")
guile> (3args+ 1 2 3)
(1 2 3 ())
guile> (3args+ 1 2 3 4)
(1 2 3 (4))
guile> (3args+ 1 2 3 4 5)
(1 2 3 (4 5))
guile> (3args+ 1 2 3 4 5 6)
(1 2 3 (4 5 6))
guile> (3args+ 1 2 3 4 5 6 7)
(1 2 3 (4 5 6 7))
guile> (args0.1)
(())
guile> (args0.1 1)
((1))
guile> (args0.1 1 2)
((1 2))
guile> (args0.1 1 2 3)
((1 2 3))
guile> (args1.1 1)
(1 ())
guile> (args1.1 1 2)
(1 (2))
guile> (args1.1 1 2 3)
(1 (2 3))
guile> (args2.1 1 2)
(1 2 ())
guile> (args2.1 1 2 3)
(1 2 (3))
guile> (args2.1 1 2 3 4)
(1 2 (3 4))
lambda を使って関数を定義するのが正統な関数の定義法であるが, 下記の省略形が使える.
unregular.scm
1 2 3 4 5 6 7 8 9 10 11 | ;; Hello with Name
(define (hello name)
(string-append "Hello " name "!"))
;; sum of four numbers
(define (sum4 a b c d)
(+ a b c d))
;; returning a list of three and additional arguments
(define (args3.1 a b c . d)
(list a b c d))
|
unregular.scm の実行結果は:
guile> (load "unregular.scm")
guile> (hello "feifei")
"Hello feifei!"
guile> (sum4 1 2 3 4)
10
guile> (args3.1 1 2 3)
(1 2 3 ())
guile> (args3.1 1 2 3 4)
(1 2 3 (4))
guile> (args3.1 1 2 3 4 5)
(1 2 3 (4 5))
guile> (args3.1 1 2 3 4 5 6)
(1 2 3 (4 5 6))
次の書いてください:
1. 引数に 1 を加えて返す関数 (+1)
2. 引数から 1 を引いて返す関数 (-1)
addmin.scm
1 2 3 4 5 6 7 | ;; plus 1
(define (add1 x)
(+ x 1))
;; minus 1
(define (min1 x)
(- x 1))
|
addmin.scm の実行結果は:
guile> (load "addmin.scm")
guile> (add1 5)
6
guile> (min1 5)
4
guile> (add1 (add1 5))
7
guile> (min1 (min1 5))
3
guile> (min1 (add1 5))
5