1

私はScheme(Petite Chez Scheme)を学び始めたばかりで、自分自身への挑戦としてクイックソートを実装しようとしています。ただし、実行すると次の例外が発生します。

Exception: attempt to apply non-procedure (1 2 3 4 5 7 ...)

これがEmacsからの私のSchemeセッションです:

Petite Chez Scheme Version 8.4
Copyright (c) 1985-2011 Cadence Research Systems

> (define (set a i k)
    (define (reduce-list a i n)
      (if(= i n)
     a
     (reduce-list (cdr a) (+ i 1) n)))
    (if(= i 0)
       (cons k (cdr a))
       (let ((b (cons k (reduce-list a 0 (+ i 1)))))
     (let push-front ((lst b) (original-list a) (n (- i 1)))
       (if(<= n 0)
          (cons (list-ref original-list 0) lst)
          (push-front (cons (list-ref original-list n) lst) original-list (- n 1)))))))

(define (swap lst i j)
    (let ((a (list-ref lst i))
      (b (list-ref lst j)))
      (set (set lst i b) j a)))

(define (partition a i j r)
    (cond [(= j r) (cons (+ i 1) (swap a (+ i 1) j))]
      [(<= (list-ref a j) (list-ref a r)) (partition (swap a j (+ i 1)) (+ i 1) (+ j 1) r)]
      [else (partition a i (+ j 1) r)]))

(define (quicksort a p r)
    (if(< p r)
       (begin(
          (let* ((c (partition a (- p 1) p r))
            (q (car c))
            (b (quicksort (cdr c) p (- q 1))))
        (quicksort b (+ q 1) r))))
       a))

> (define lst (list 1 9 2 8 3 7 4 6 5))
> (define n (length lst))
> (trace quicksort)
(quicksort)
> (quicksort lst 0 (- n 1))
|(quicksort (1 9 2 8 3 7 4 6 5) 0 8)
| (quicksort (1 2 3 4 5 7 8 6 9) 0 3)
| |(quicksort (1 2 3 4 5 7 8 6 9) 0 2)
| | (quicksort (1 2 3 4 5 7 8 6 9) 0 1)
| | |(quicksort (1 2 3 4 5 7 8 6 9) 0 0)
| | |(1 2 3 4 5 7 8 6 9)
| | |(quicksort (1 2 3 4 5 7 8 6 9) 2 1)
| | |(1 2 3 4 5 7 8 6 9)
Exception: attempt to apply non-procedure (1 2 3 4 5 7 ...)
> 

誰かが何が悪いのか教えてもらえますか?前もって感謝します

4

3 に答える 3

1

問題は

begin

クイックソートで。いつ

(quicksort b (+ q 1) r)

最終的にa(実際には親クイックソートではb)を返し、let*ブロックは

(define (quicksort a p r)
  (if(< p r)
     (begin(
            (let* ((c (partition a (- p 1) p r))
                   (q (car c))
                   (b (quicksort (cdr c) p (- q 1))))
              (quicksort b (+ q 1) r)))) 
     a))

(define (quicksort a p r)
  (if(< p r)
     (begin
        (b)) ;this is the cause of the error 
     a))

また、bはリストであるため、呼び出そうとするとエラーが発生します。beginを削除すると、letブロックは意図したとおりに動作します。

于 2012-04-06T00:38:10.253 に答える
0

クイックソートで、行(begin(の最後とを削除します。)(quicksort b (+ q 1) r)

(beginおよび)クイックソート呼び出し行のは、その2番目のクイックソート呼び出しの結果を適用しています。

これは、これがの本体の最後の式であるlet*ため、let*の戻り値です。それが返すリストは、間違いなくプロシージャではないリストです。

また、すべてのletで暗黙的に開始します。

例えば

(let ([a 1] [b 2] [c 3])
  (set! b 3)
  a
  b)

3を返します(単純な呼び出しは価値がなく、その値は無視されます)

そしてそれは次のコードと同等です:

(let ([a 1] [b 2] [c 3])
  (begin
     (set! b 3)
     a
     b))
于 2012-04-06T00:41:36.943 に答える
0

他の人があなたの質問に対する答えを述べているので、私は他の答えから欠けている何かを明らかにしたいと思います。それはうまくいけばあなたや他の人がの理解に役立つでしょう(begin ())

関数には条件付きの後に2つのスロットしかないため、私はステートメントで行ったように最も一般的に使用(begin ())します。(if ())

したがって、は、条件付きの「道路の分割」自体(begin ())の片側または両側について複数のステートメントを評価する場合に役立ちます。

例:

(do ([i 0 (+ i 1)]) [(< i 10)]
  (if (= (% i 2) 1)
    (printf 'odd)
    (begin
      (printf 'even)
      'even)))

上記では、数が偶数の場合にChezに2つの別々のアクションを実行さ(begin ())せたい場合にのみ使用します。奇妙なときは、beginステートメントは必要なく、続行できます。ii

注意点として、ChezSchemeはbeginステートメントの内容を順番に評価します。Schemeプログラミング言語では、ページの下部近くに次のように書かれています。

「構文形式begin[...]は、その部分式を左から右に順番に評価し、letまたはlambda式の本体のように、最後の部分式の値を返します。」

于 2017-06-29T22:06:13.187 に答える