0

完全な Swindle パッケージで Scheme を使用しており、条件を使用して整数の偶数/奇数を再帰的に決定しようとしています。私のコードは次のとおりです。

(define (odd? x)(
            (cond 
              ((= x 0) '#f)
              ((= x 1) '#t)
              ((= (even? (- x 1)) #t) '#f)
              (else '#t))))

(define (even? x)(
              (cond
                ((= x 0) '#f)
                ((= x 2) '#t)
                ((= (odd? (- x 1)) #t) '#f)
                (else '#t))))

ただし、 (even? x) または (odd? x) を実行すると [x は何らかの数値ですが、同じエラーが発生するため問題ありません] 次のようになります。指定された引数に適用できるプロシージャが必要です: #t 引数...: [なし]

誰でも助けることができますか?ありがとう。私は理想的な Scheme 構文に 100% 精通しているわけではないので、そうかもしれません。

4

2 に答える 2

0

かっこ内のすべての Scheme 形式は、またはのようなアプリケーションです。最初は引数付きの関数として呼び出し、値を生成します。2 番目は引数を指定して呼び出そうとしますが、プロシージャではないため、エラーが発生します。引数のないアプリケーションも同様です。それでも、引数なしで呼び出されるように、最初の部分として適用されるプロシージャが必要ですよね? スキームでは、括弧は重要です。それらは単にグループ化するためのものではありません (他の言語のように)。したがって、余分な括弧があると、ブール値である結果を評価する余分な試行が発生します。つまり、プロシージャではないため、これはエラーです。(sin 42)(42 sin)sin4242sin42(42)

それでは、'#fただ#fです。同様に for #t(両方とも自分自身に評価されます); 条件1は just (boolean の結果の同じセットを生成します) (( 1はブール値の比較には使用できません。数値のみで使用することになっています)) と同じです:(= test #t) (equal? test #t)test=

(define (odd? x)
        (cond 
          ((= x 0) #f)
          ((= x 1) #t)
          ((even? (- x 1)) #f)
          (else #t)))

また、次(if test #f else...)と同じ(if (not test) else... #f)です。

(define (odd? x)
        (cond 
          ((= x 0) #f)
          ((= x 1) #t)
          ((not (even? (- x 1))) #t)
          (else #f)))                 ; (else ...) is like (#t ...)

論理接続詞を使用すると、同じ結果の句をマージでき、相互に排他的な句を再配置できます (相互排他性は明示的なガードで実現できます)。

(define (odd? x)
        (cond 
          ((and (/= x 0)              ; a guard
                (or (= x 1) 
                    (not (even? (- x 1))))) #t)
          ((or (= x 0) #t) #f)))

しかし、どちらが正しい(cond (test #t) (else #f)か:(if test #t #f)test

(define (odd? x) (and (> x 0)         ; `>` is better
                      (or (= x 1) 
                          (not (even? (- x 1))))))

ガードは、負のes(> x 0)のフォールスルーを防ぎます。x

しかし、これは完全に間違っています。n奇数であるためには偶数でn-1 なければならず、その逆ではありません!

(define (odd? x) (and (> x 0)         ; work only for positive integers
                      (or (= x 1) 
                          (even? (- x 1)))))

と書くことはできます(not (odd? (- x 1)))が、末尾再帰にはなりません。これ末尾再帰モジュロ コンス( 「コンストラクタ」として機能) になりますnotが、理由2の歴史的なまぐれにより、Scheme 実装には TRMC 最適化は必要ありません。andandorフォームの最後の式は、実際には末尾の位置にあります。しかし、そうではありませんnot(( 2は 1974 年に記述されているにもかかわらず. ))

の定義についても同じことを繰り返しますeven?

于 2013-11-10T07:53:46.237 に答える
0

式を囲む誤った括弧のペアがありますcond(それが報告されたエラーの原因です)。しかし、各手順にはあまりにも多くの条件があり、=数値をブール値と比較するために使用しているため、契約違反が発生するポイントがあります。=ここで置き換えることができる修正についてequal?

((equal? (even? (- x 1)) #t) '#f)

そしてここで:

((equal? (odd? (- x 1)) #t) '#f)

しかし、その後、手順は依然として不正確な結果をもたらします。

(even? 5)
=> #t
(odd? 7)
=> #f

正直なところ、すべての問題を解決する実装を簡素化する方がよいと思います。代わりにこれを試してください:

(define (odd? x)
  (cond ((= x 0) #f)
        (else (even? (- x 1)))))

(define (even? x)
  (cond ((= x 0) #t)
        (else (odd? (- x 1)))))

これで正しい答えが得られます:

(even? 4)
=> #t
(even? 5)
=> #f
(odd? 6)
=> #f
(odd? 7)
=> #t
于 2013-11-10T04:51:30.733 に答える