2016-03-26 20 views
-3

こんにちは、私はquestion.Letsを持っています。リストに要素を追加する関数を定義しました。リストに要素があり、新しい要素がある一覧表示するために、第2として追加され、Scheme内の既存のリストに要素を追加する

>(add a) ; here list is empty 
'(a) 
>(add b) ; here a is in the list 
'(a b) 
>(add c) ; here a and b is in the list 
(a b c) 

一覧がthis.Howのように更新されthis.Forの例のように行く私はthis.Iのような関数を書くことができ、私のcode.Iで空のリストにするたびに要素を追加し、それがある意味それは私のものと同じです。

>(add a) 
'(a) 
>(add b) 
'(b) 
>(add c) 
'(c) 

この目的のために適切なコードを書くにはどうすればよいですか?ここで は値を変異させるための2つの方法があるだけで、他の言語のように私のコード

#lang racket 
(define addToList 
    (lambda (a b) 
    (cond ((null? a) b) 
      ((null? b) a) 
      ((cons (car a) (addToList (cdr a) b)))))) 
(addToList '(1 2 3) '()) 
+0

@ LukePark私は空リストに追加するたびに上のように言った。あなたがそれを読んだら見ることができる – dymayd

答えて

0

です。変数のポイント(バインディング)を変更するか、オブジェクトの一部を変更してターゲットオブジェクトを変更することができます。最後のものは、オブジェクトがプリミティブでないことを要求します。

突然変異使用
#!r6rs 
(import (rnrs)) 

(define lst '())  
(define (add element) 
    (set! lst (append lst (list element))) ; adding to front is much cheaper 
    lst) 

#!r6rs 
(import (rnrs) 
     (rnrs mutable-pairs)) 

(define lst (list 'head)) 
(define tail lst) ; keep the last cons so we can add O(1) 

(define (add element) 
    (set-cdr! tail (list element)) 
    (set! tail (cdr tail)) 
    (cdr lst))) 

それは実際には何を変異ていないので、あなたの手順では、より多くの機能一種のように見えますが、あなたはその結果、あなたを守れば、それは仕事との結合変数を使用して

リストを拡張するのではなく、要素を末尾に点線のリストとして追加するという事実を修正しました。私はそれがより多くのスキームのように見えるように、このようにそれを書かれているだろう

(define addToList 
    (lambda (a b) 
    (cond ((null? a) (list b)) ; result needs to be a list 
      ((null? b) a) 
      ((cons (car a) (addToList (cdr a) b)))))) 

(define lst '()) 
(set! lst (addToList lst 1)) 
(set! lst (addToList lst 2)) 
(set! lst (addToList lst 3)) 
lst ; ==> (1 2 3) 

:前に追加もちろん

(define (add-to-end lst e) 
    (if (null? lst) 
     (list e) 
     (cons (car lst) 
      (add-to-end (cdr lst) e))))) 

ははるかに安いですし、昔ながらのconsで行われます。いくつかの要素を追加し、実際にそれを最後に追加したい場合は、要素を追加した後にリストを逆にして同じ効果を得ます。

0

すべてのLisp方言で空のリストが特別な不変の値であるため、任意のLisp方言の空のリストに「追加」することはできません。

ラケットでは、空のリストが不変であるだけでなく、すべてのリストもあります。正しく操作するには、リストを操作するコードを "functional"スタイルで記述する必要があります。

あなたadd機能の意味でのリストに「追加」もう一つの要素で、まったく新しいリストを作成し、前と同じ変数にバインドする意味になります。

;;; This implementation of add would behave just like 
;;; the examples at the top of your question. 
(define add 
    (let ((the-list '())) 
     (lambda (new-item) 
     (set! the-list 
       (append the-list (list new-item))) 
     the-list))) 

上記の関数の実行新しいものを追加する前にすべての要素をコピーすることが でなければならないので、より遅い方が遅いです。the-listです。それは、代わりに最後のリストの開始に追加するはるかに高速です:

(define add 
    (let ((the-list '())) 
     (lambda (new-item) 
     (set! the-list 
       (cons new-item the-list)) 
     the-list))) 

このため、ほとんどのラケットプログラムは後方自分のリストを作成し、その後 を作成するために、できるだけ遅くreverseを使用しますリストのフォワードバージョン。