1

したがって、SICPcons carから、 andcdrをプロシージャとして定義できることがわかります。

(define (cons x y)
    (lambda (m) (m x y)))

(define (car z)
    (z (lambda (p q) p)))

(define (cdr z)
    (z (lambda (p q) q)))

listしかし、リストを作成するために引数を取る事前定義された手続きは、元の を使用しconsます。つまり、list構築されたリストは、私が望む手順ではありません。

(car (list 1 2 3))
;The Object (1 2 3) is not applicable

だから私はこれを書きます:

(define (list . l)
    (if (null? l)
        '()
        (cons (original-car l)
              (list (original-cdr l)))))

original-carandをどのように定義するのか疑問に思っていますoriginal-cdr。スキームでプロシージャのコピーを作成する方法はありますか? または、この問題を解決する別の方法があります。どうも

4

2 に答える 2

4

それらを再定義する前に「元の」プロシージャへの参照を保存する必要がある場合は、「新しい」プロシージャを定義する前にエイリアスを作成するだけです(それが「コピー」の意味だと思います)。このような:

(define original-cons cons)
(define original-car car)
(define original-cdr cdr)
(define original-list list)

このように、新しい名前で参照する限り、古い手順を引き続き使用できます。つまり、、、および as プロシージャの実装はcons次のようcarになります。cdrlist

(define (my-cons x y)
  (lambda (m) (m x y)))

(define (my-car z)
  (z (lambda (p q) p)))

(define (my-cdr z)
  (z (lambda (p q) q)))

(define (my-list . els)
  (if (null? els)
      '()
      (my-cons
       (original-car els)
       (apply my-list (original-cdr els)))))

そして確かに、それは機能します:

(define lst (my-list 1 2 3 4))
lst
=> #<procedure>
(my-car lst)
=> 1
(my-car (my-cdr lst))
=> 2
于 2013-06-09T03:25:54.820 に答える
2

実装のリストは次のように定義されます

(define (list . l) l)

ただし、これは基礎となる実装の多くを使用しています。たとえば、ネイティブの cons を使用して動作します。consで定義されてSICPいるのは思考実験であるため、実装には少し修正が必要です。

(define (my-cons x y)
    (lambda (m) (m x y)))

(define (my-car z)
    (z (lambda (p q) p)))

(define (my-cdr z)
    (z (lambda (p q) q)))

(define (my-list . l)
  (define (my-list-aux l)
    (if (null? l)
        '()
        (my-cons (car l)
                 (my-list-aux (cdr l)))))
  (my-list-aux l))

;; optional, update binding
(define car my-car)
(define cdr my-cdr)
(define list my-list)

my-cons my-car、my-cdr、および my-list は、質問で定義されているとおりです。変更のみが正しい手順への参照です (スキームと競合しない名前で)

于 2013-06-09T02:36:30.433 に答える