Scheme中一个程序的while循环工作机制
While loops working mechanism of a program in Scheme
DrRacket 用户。
我很难理解这个程序 works.I 是如何自己编写的,它做了它必须做的事情,但我不明白是如何做到的。
我将 while 循环定义为:
(define (while test body)
(if (test)
(begin
(body)
(while test body))
(void)))
现在我需要编写一个程序,将给定过程应用于可变列表的每个元素。
这是我写的:
(define (mlist-map-while f x)
(while (lambda() (not (null? x)))
(lambda ()
(set-mcar! x (f (mcar x)))
(set! x (mcdr x))))
(void))
所以,定义
list1 (mlist 1 2 3)
并申请
(mlist-map-while (lambda (x) (+ x 1)) list1)
我们得到 '(2 3 4)
.
我不明白的是列表的第一个元素是如何保留在其中的,因为如果它完成了我在这里写的方式
(set! x (mcdr x))
设置-mcar!
的第一个程序一定是无用的,并且与第二个重叠。就像这个例子:
(define list1 (mlist 1 2 3))
(set-mcar! list1 9)
(set-mcdr! list1 (mcdr list!))
我们缺少第一个元素,但这个程序以某种方式将其保留并给出了所需的输出。我想知道它是如何工作的以及是否有另一种遍历给定列表的方法。
set-cdr!
和set!
有很大区别。第一个改变了对的 cdr
指针,而后者改变了绑定,因此名称应该指向什么。
在您的 mlist-map-while
中,变量 x
改变了 car
,然后将 x
代表的 改变为cdr
个 x
。它 从不 改变 cdr
所以你的绑定 list1
总是指向第一对,而 x
指向第一对,然后是第二对,依此类推。 .
所以更像是这样:
(define list1 (mlist 1 2 3))
(define list1-ref list1) ; variable pointing to the same value as list1
(set-mcar! list1-ref 9) ; set-car! changes the pair
(set! list1-ref (mcdr list)) ; set! updates what list1-ref points to
list1 ; ==> (9 2 3)
list-ref ; ==> (2 3)
您可以在不使用 set!
的情况下以相同的方式遍历列表,使用递归:
(define (fold function init lst)
(if (null? lst)
init
(fold function
(function (car lst) init)
(cdr lst))))
(fold + 0 '(1 2 3)
; ==> 6
(fold cons '() '(1 2 3))
; ==> (3 2 1)
请注意,这里我们递归并更改 lst
是什么,成为 cdr
。每个递归都有自己的 lst
,不要与调用者自己的相混淆。它最终与您示例中的 set!
相同,没有突变。
DrRacket 用户。
我很难理解这个程序 works.I 是如何自己编写的,它做了它必须做的事情,但我不明白是如何做到的。
我将 while 循环定义为:
(define (while test body)
(if (test)
(begin
(body)
(while test body))
(void)))
现在我需要编写一个程序,将给定过程应用于可变列表的每个元素。
这是我写的:
(define (mlist-map-while f x)
(while (lambda() (not (null? x)))
(lambda ()
(set-mcar! x (f (mcar x)))
(set! x (mcdr x))))
(void))
所以,定义
list1 (mlist 1 2 3)
并申请
(mlist-map-while (lambda (x) (+ x 1)) list1)
我们得到 '(2 3 4)
.
我不明白的是列表的第一个元素是如何保留在其中的,因为如果它完成了我在这里写的方式
(set! x (mcdr x))
设置-mcar!
的第一个程序一定是无用的,并且与第二个重叠。就像这个例子:
(define list1 (mlist 1 2 3))
(set-mcar! list1 9)
(set-mcdr! list1 (mcdr list!))
我们缺少第一个元素,但这个程序以某种方式将其保留并给出了所需的输出。我想知道它是如何工作的以及是否有另一种遍历给定列表的方法。
set-cdr!
和set!
有很大区别。第一个改变了对的 cdr
指针,而后者改变了绑定,因此名称应该指向什么。
在您的 mlist-map-while
中,变量 x
改变了 car
,然后将 x
代表的 改变为cdr
个 x
。它 从不 改变 cdr
所以你的绑定 list1
总是指向第一对,而 x
指向第一对,然后是第二对,依此类推。 .
所以更像是这样:
(define list1 (mlist 1 2 3))
(define list1-ref list1) ; variable pointing to the same value as list1
(set-mcar! list1-ref 9) ; set-car! changes the pair
(set! list1-ref (mcdr list)) ; set! updates what list1-ref points to
list1 ; ==> (9 2 3)
list-ref ; ==> (2 3)
您可以在不使用 set!
的情况下以相同的方式遍历列表,使用递归:
(define (fold function init lst)
(if (null? lst)
init
(fold function
(function (car lst) init)
(cdr lst))))
(fold + 0 '(1 2 3)
; ==> 6
(fold cons '() '(1 2 3))
; ==> (3 2 1)
请注意,这里我们递归并更改 lst
是什么,成为 cdr
。每个递归都有自己的 lst
,不要与调用者自己的相混淆。它最终与您示例中的 set!
相同,没有突变。