Scheme 方案重新定义列表
我有一个名为手牌的列表和另一个名为牌组的列表,这里的主要目标是在我调用fnction draw时,将列表牌组中的第一张牌(或元素)放入列表手牌中Scheme 方案重新定义列表,scheme,blackjack,playing-cards,Scheme,Blackjack,Playing Cards,我有一个名为手牌的列表和另一个名为牌组的列表,这里的主要目标是在我调用fnction draw时,将列表牌组中的第一张牌(或元素)放入列表手牌中 > (draw hand deck) (2 C) > (draw hand deck) (2 C) (3 H) > (draw hand deck) (2 C) (3 H) (K D) 但每次我叫它手永远不会改变价值。。。 我不知道有没有像在O-Object中那样的方法可以永久更改手的内容 我最初定义手牌是空的,因为玩家没有牌可以
> (draw hand deck)
(2 C)
> (draw hand deck)
(2 C) (3 H)
> (draw hand deck)
(2 C) (3 H) (K D)
但每次我叫它手永远不会改变价值。。。
我不知道有没有像在O-Object中那样的方法可以永久更改手的内容
我最初定义手牌是空的,因为玩家没有牌可以开始
(define hand '())
不能更改列表的内容,但可以更改名称所指的列表。因此:
(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)
现在,每个列表“(“post”)”(“第一个”post”)和“(一个全新的列表)都是不可更改的(“不可变”)列表,但是一些列表的名称首先指向一个,然后指向另一个,然后指向第三个
警告:对于许多问题,您将希望避免设置!试着用不同的方式思考这个问题。例如,如果你在游戏中使用世界和宇宙,
然后,您将希望更新程序返回新的世界状态,而不是使用set!修改旧的。哦,接下来您会发现,从调用函数的人的角度来看,更改函数中名称所指的列表不会更改该名称所指的内容。因此:
(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)
功能性解决方案,
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)
Vijay为方案提供了最佳解决方案。但是,如果您真的想通过永久更改列表来实现这一点,则需要使用
set car代码>和设置cdr代码>。这在Scheme中是不自然的,需要一些技巧才能实现:
首先定义手部
和甲板
:
(define hand '(dummy))
(define deck '((2 C) (3 H) (K D)))
hand
必须从现有元素开始,这样它就有一些现有的列表结构需要修改。您不能使用设置汽车代码>和设置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
是否为空