2010-03-31 52 views
0

我有一個名爲hand的列表,另一個名爲deck,這裏的主要目標是當我打電話給fnction draw時將第一張牌(或元素)放在列表​​中,並將它放在列表中。 ...Scheme重新定義一個列表

> (draw hand deck) 
(2 C) 
> (draw hand deck) 
(2 C) (3 H) 
> (draw hand deck) 
(2 C) (3 H) (K D) 

,但每次我把它叫做手從未在O型對象的變化值... 我無言以對,有沒有辦法像以永久改變手的內容?

我最初定義爲空手,因爲玩家沒有牌開始。

(define hand '()) 

回答

0

您不能更改列表的內容,但可以更改名稱引用的列表。所以:

(let ((some-list '("post"))) 
(display "initially: ") 
(display some-list) 
(newline) 
(set! some-list (cons "first" some-list)) 
(display "added first: ") 
(display some-list) 
(newline) 
(set! some-list '(a completely new list)) 
(display "finally: ") 
(display some-list) 
(newline) 
some-list) 

現在每個列表的「(‘後’)」(‘第一’,‘後’)和「(一個完全新的列表)是不變的(‘不變’)名單,但名稱一些 - 列出第一個指向一個,然後是另一個,然後是第三個。

警告:對於很多問題,你會想避免設置!並嘗試以不同的方式思考問題。例如,如果你在遊戲中使用世界和宇宙, http://pre.plt-scheme.org/plt/doc/teachpack/2htdpuniverse.html 那麼你會希望你的更新程序返回一個新的狀態而不是使用set!修改舊的。

0

呵呵,接下來你會發現,在一個函數內改變一個名字引用的列表不會改變這個名字所指的名稱。所以:

(define (foo lst) 
    (set! lst '(hi)) 
    (display "within foo: ") 
    (display lst) 
    (newline) 
    lst) 
(define my-list '(hello)) 
(foo my-list) 
(display "after foo: ") 
(display my-list) 
(newline) 
(set! my-list (foo my-list)) 
(display "using the result of foo: ") 
(display my-list) 
(newline) 
1

功能性解決方案,draw是無副作用:

;; Returns a cons whose car will be the new hand and cdr being the 
;; rest of the original deck 
(define (draw deck hand) 
    (if (not (null? deck)) 
     (cons (cons (car deck) hand) (cdr deck)) 
     (cons hand()))) 

;; Gets the new hand from the cons returned by draw. 
(define (hand cards) (car cards)) 

;; Gets the new deck from the cons returned by draw. 
(define (deck cards) (cdr cards)) 

;; test 
(define cards (draw '(1 2 3 4 5)())) 
cards 
=> ((1) 2 3 4 5) 
(hand cards) 
=> (1) 
(deck cards) 
=> (2 3 4 5) 
;; draw again 
(set! cards (draw (deck cards) (hand cards))) 
cards 
=> ((2 1) 3 4 5) 
(hand cards) 
=> (2 1) 
(deck cards) 
=> (3 4 5) 
0

維傑 - 有計劃的最佳解決方案。但是,如果您真的要想通過永久更改列表來完成此項工作,則需要使用set-car!set-cdr!。這是不是在計劃自然,需要幾個黑客,使其工作:

首先定義handdeck

(define hand '(dummy)) 
(define deck '((2 C) (3 H) (K D))) 

hand已開始與現有的元素,使其具有一定的現有列表結構進行修改。您無法使用set-car!set-cdr!(零)('())。

現在寫draw

(define (draw from to) 
    ; push the top element of `from` onto `to` 
    (set-cdr! to (copy to)) 
    (set-car! to (car from)) 
    ; pop the top element of `from` off 
    (set-car! deck (cadr deck)) 
    (set-cdr! deck (cddr deck))) 
; also we need to define copy 
(define (copy l) 
    (map (lambda (x) x) l)) 

這意味着你的手的最後一個元素將永遠是假的。這將是最好添加一個檢查的初步情況和覆蓋它,而不是推的:

(define (draw from to) 
    ; push the top element of `from` onto `to` (just overwrite the first time) 
    (when (pair? (cdr to)) 
    (set-cdr! to (copy to))) 
    (set-car! to (car from)) 
    ; pop the top element of `from` off 
    (set-car! deck (cadr deck)) 
    (set-cdr! deck (cddr deck))) 

您也應該檢查from沒有做任何事情之前空。