Gimp2.6で使える関数
- ブーリアンと等値 -

 一覧にある関数はとりあえず、使えそうな関数です。
現在のところ、確認は、2.6.10で行っています。


ブーリアンと等値
boolean? ( boolean? v)boolean
論理値か判定

論理値は #t#f 。このいずれかならば真(#t)を返し、それ以外では偽(#f)を返す。

>(boolean? #t)
#t
>(boolean? #f)
#t
>(boolean? 1)
#f
not ( not v)戻り値
論理の反転

v が #f ならば、真(#t)、それ以外ならば #f を返す。

>(not #f)
#t
>(not #t)
#f
>(not '())
#f
>(not 0)
#f
equal? ( equal? s1 s2)boolean
同等

equal?eqv?eq? はいずれも等値であれば #t 、そうでなければ、#f を返す。等値の判断は、最も厳しいのが eq? で、もっとも緩いのが equal? である。
 equal? は通常の感覚の「等しい」にもっとも近いものです。リストの比較など以外では、それぞれのデータ型に定義された比較関数を使うのが実際的です。
 r5rs(schemeの規格書のひとつの日本語訳(Translated into Japanese by Hisao Suzuki suzuki@acm.org)によれば、以下のように説明されています。

equal? は再帰的にペア、ベクタ、および文字列の内容を比較し、それ以外の数やシンボルなどのオブジェクトに対してはeqv? を適用する。おおざっぱな原則として、同じように印字されるオブジェクトどうしは一般にequal? である。

(equal? 'a 'a) ⇒ #t
(equal? '(a) '(a)) ⇒ #t
(equal? '(a (b) c) '(a (b) c)) ⇒ #t
(equal? "abc" "abc") ⇒ #t
(equal? 2 2) ⇒ #t
(equal? (make-vector 5 'a) (make-vector 5 'a)) ⇒ #t

 Gimp2で試した例です。

>(equal? '(a (b c)) '(a (b c) ))
#t
>(equal? '(a (b c)) (list 'a '(b c) ))
#t
>(equal? (make-string 5 #\a) (make-string 5 #\a))
#t
>(equal? "aaaaa" (make-string 5 #\a))
#t
eqv? ( eqv? )boolean
等しい

ペア(リストを含む)、ベクターと文字列は、メモリーに占める位置が同じならば、等しいと判定。それ以外は、大まかに言えば、値が同じならば等しいと判定します。
 r5rsでは以下のように説明されています。

eqv? 手続きはある有用な等価関係をオブジェクトに対して定義する。簡単にいえば,もしもobj1 とobj2 が通常同じオブジェクトだと見なしてよいものならば,#t を返す。この関係にはいささか解釈の余地があるが,下記の部分的なeqv? の規定はScheme のすべての実装に対して成り立つ。
次が成り立つならばeqv? 手続きは#t を返す:

  • 2 obj1 とobj2 がともに#t またはともに#f である。
  • 2 obj1 とobj2 がともにシンボルであって,かつ
    (string=? (symbol->string obj1) (symbol->string obj2)) ⇒ #t
    
    注: これはobj1 とobj2 のどちらも,6.3.3 節でほのめかされているような“未インターンのシンボル” ではないことを仮定している。この報告書は,実装依存の拡張に対するeqv?の振舞をあえて規定するようなことはしない。
  • obj1 とobj2 がともに数であって, 数値的に等しく(6.2節の= を見よ),かつともに正確数またはともに不正確数である。
  • obj1 とobj2 がともに文字であって,かつchar=? 手続き(6.3.4 節) で同じ文字だと判定される。
  • obj1 とobj2 がともに空リストである。
  • obj1 とobj2 がともにペア,ベクタ,または文字列であって,記憶領域の中の同じ場所を表す(3.4 節)。
  • obj1 とobj2 がともに手続きであって,場所タグが等しい(4.1.4 節)。

次が成り立つならばeqv? 手続きは#f を返す:

  • obj1 とobj2 の型が異なる(3.2 節)。
  • obj1 とobj2 の一方が#t で他方が#f である。
  • obj1 とobj2 がともにシンボルだが
    (string=? (symbol->string obj1) (symbol->string obj2)) ⇒ #f
    
  • obj1 とobj2 の一方が正確数で他方が不正確数である。
  • obj1 とobj2 がともに数であって,= 手続きが#f を返す。
  • obj1 とobj2 がともに文字であって,char=? 手続きが#f を返す。
  • obj1 とobj2 の一方が空リストだが他方がそうでない。
  • obj1 とobj2 がともにペア,ベクタ,または文字列であって,別々の場所を表している。
  • obj1 とobj2 がともに手続きであって,なんらかの引数に対して異なった振舞をする(異なった値を返す,または異なった副作用をもつ) だろう。
  • (eqv? 'a 'a) ⇒ #t
    (eqv? 'a 'b) ⇒ #f
    (eqv? 2 2) ⇒ #t
    (eqv? '() '()) =) #t
    (eqv? 100000000 100000000) ⇒ #t
    (eqv? (cons 1 2) (cons 1 2)) ⇒ #f
    (eqv? (lambda () 1) (lambda () 2)) ⇒ #f
    (eqv? #f 'nil) ⇒ #f
    (let ((p (lambda (x) x))) (eqv? p p)) ⇒ #t
    

    下記の例は,上記の規則がeqv? の振舞を完全には規定していないという実例を示している。このような場合について言えることは,eqv? の返す値はブーリアンでなければならないということだけである。

    (eqv? "" "") ⇒ 未規定
    (eqv? '#() '#()) ⇒ 未規定
    (eqv? (lambda (x) x) (lambda (x) x)) ⇒ 未規定
    (eqv? (lambda (x) x) (lambda (y) y)) ⇒ 未規定
    

    次の例は,ローカルな状態をもった手続きに対するeqv? の使用を示している。gen-counter は毎回別々の手続きを返しているはずである。なぜなら,各手続きはそれ自身の内部カウンタをもっているからである。一方,gen-loser は毎回等価な手続きを返している。なぜなら,そのローカル状態は,手続きの値または副作用に影響しないからである。

    (define gen-counter
        (lambda ()
            (let ((n 0))
                (lambda () (set! n (+ n 1)) n))))
    (let ((g (gen-counter)))
        (eqv? g g))                 ⇒ #t
    (eqv? (gen-counter) (gen-counter))
                                    ⇒ #f
    
    (define gen-loser
        (lambda ()
            (let ((n 0))
                (lambda () (set! n (+ n 1)) 27))))
    (let ((g (gen-loser)))
        (eqv? g g)) ⇒ #t
    (eqv? (gen-loser) (gen-loser)) ⇒ 未規定
    
    (letrec ((f (lambda () (if (eqv? f g) 'both 'f)))
             (g (lambda () (if (eqv? f g) 'both 'g))))
        (eqv? f g))
                                    ⇒ 未規定
    (letrec ((f (lambda () (if (eqv? f g) 'f 'both)))
             (g (lambda () (if (eqv? f g) 'g 'both))))
        (eqv? f g))
                                    ⇒ #f
    

    定数オブジェクト(リテラル式が返すオブジェクト) を改変することはエラーだから,適切なところで実装が定数どうしの構造を共有化することは,要求はされていないけれども,許されている。したがって定数についてのeqv? の値はときどき実装依存である。

    (eqv? '(a) '(a)) ⇒ 未規定
    (eqv? "a" "a") ⇒ 未規定
    (eqv? '(b) (cdr '(a b))) ⇒ 未規定
    (let ((x '(a))) (eqv? x x)) ⇒ #t
    
    根拠: eqv? の上記の定義は,手続きとリテラルの取扱いにおいて 実装に自由度を許している。つまり,実装は,二つの手続きないし 二つのリテラルが互いに等価であることを検出することも検出し そこなうことも自由であり,両者の表現に使用するポインタまた はビット・パターンが同一であることを以て等価なオブジェクトで あることと同一視することにしてもしなくてもよい。

 Gimp2で試した例です。

>(define a '(a b c))
a
>(eqv? a a)
#t
>(define b a)
b
>(eqv? a b)
#t
>(eqv? '(a (b c)) '(a (b c) ))
#f
>(eqv? '(a (b c)) (list 'a '(b c) ))
#f
>(eqv? (make-string 5 #\a) (make-string 5 #\a))
#f
>(eqv? "aaaaa" (make-string 5 #\a))
#f
>(eqv? #\a #\a)
#t
>(eqv? 1 1)
#t

リストや文字列は、値が同じでも、同じ実体を指していない #f になります。
最後の例の文字では、値が同じなので #t になっています。

eq? ( eq? )boolean
同一か?

最も厳しい等価の判定。大雑把に言えば、引数が同じオブジェクトのとき #t、そうでなければ #f。

r5rsでは次のように説明されています。

eq? は,いくつかの場合においてeqv? よりも細かく差異を見分けられることを除けば,eqv? と同様である。

eq? とeqv? はシンボル,ブーリアン,空リスト,ペア,手続き,および非空の文字列とベクタに対して同じ振舞をする ことが保証されている。数と文字に対するeq? の振舞は実依存だが,いつでも真か偽を返し,そして真を返すようなときは,eqv? もまた真を返す。eq? は空ベクタと空文字列に対してもeqv? と違う振舞をしてよい。

(eq? 'a 'a) ⇒ #t
(eq? '(a) '(a)) =) 未規定
(eq? (list 'a) (list 'a)) ⇒ #f
(eq? "a" "a") ⇒ 未規定
(eq? "" "") ⇒ 未規定
(eq? '() '()) ⇒ #t
(eq? 2 2) =) 未規定
(eq? #\A #\A) ⇒ 未規定
(eq? car car) ⇒ #t
(let ((n (+ 2 3))) (eq? n n)) ⇒ 未規定
(let ((x '(a))) (eq? x x)) ⇒ #t
(let ((x '#())) (eq? x x)) ⇒ #t
(let ((p (lambda (x) x))) (eq? p p)) ⇒ #t

根拠: 普通,eq? はeqv? よりもずっと効率的に.たとえば,なにか複雑な演算ではなく単純なポインタ比較として.実装することが可能だろう。一つの理由として,eq? をポインタ比較として実装するといつでも定数時間で終了するだろうが,二つの数のeqv?を定数時間で計算することは必ずしも可能とは限らないからである。手続きを使って状態付きオブジェクトを実装するような応用においては,eq? はeqv? と同じ制約に従うから,eq? をeqv? のように使ってもよい。

 Gimp2で試した例です。

>(define a '(a b c))
a
>(eqv? a a)
#t
>(define b a)
b
>(eqv? a b)
#t
>(eq? '(a (b c)) '(a (b c) ))
#f
>(eq? '(a (b c)) (list 'a '(b c) ))
#f
>(eq? (make-string 5 #\a) (make-string 5 #\a))
#f
>(eq? "aaaaa" (make-string 5 #\a))
#f
>(eq? #\a #\a)
#f
>(eq? 1 1)
#f

eqv?と違う結果になったの文字の比較と数値の比較。値が同じだけれど違う実体を指しているから #f になっています。


アルゴ算法堂へ戻る