Scheme 方案,sicp,解决方案3.19,无限循环过程在作为参数提供的情况下有效
有人能帮我澄清练习3.19的一个可能的解决方案吗。以实例列表循环为参数,给出了过程奥秘是无限循环。然而,当我们使用程序eq?若要检查列表是否包含循环,它将工作并提供真实值Scheme 方案,sicp,解决方案3.19,无限循环过程在作为参数提供的情况下有效,scheme,lisp,sicp,Scheme,Lisp,Sicp,有人能帮我澄清练习3.19的一个可能的解决方案吗。以实例列表循环为参数,给出了过程奥秘是无限循环。然而,当我们使用程序eq?若要检查列表是否包含循环,它将工作并提供真实值 (define (last-pair x) (if (null? (cdr x)) x (last-pair (cdr x)) ) ) (define (ma
(define (last-pair x)
(if (null? (cdr x))
x
(last-pair (cdr x))
)
)
(define (make-cycle x)
(set-cdr! (last-pair x) x)
)
(define (mystery x)
(define (loop x y)
(if (null? x)
y
(let ((temp (cdr x)))
(set-cdr! x y)
(loop temp x)
)
)
)
(loop x '())
)
(define t (list 1 2 3))
(define w (make-cycle t))
(eq? (mystery t) t)
看起来很神奇。如果有任何帮助,我将不胜感激。
神秘
通过反复剪掉每个条目的cdr
并将其替换为上一个x
的cdr
来反转“就地”数组
如果此列表没有循环,那么当您返回到原始的'()
时,它将结束反转。如果有一个循环,您将拥有原始数组的指针
这绝对是一个难以理解的问题。如果你做一个方框和指针图,它肯定会有帮助,你只需要画3个图表
自动生成列表图表 在这个过程中,我发现自己想要一种可视化列表突变的方法(并跳过无数的“绘制列表图…”练习)。我为此编写了一个小函数,我想如果我共享它,您可能会发现它很有用 这些图表是每次运行
循环
(在神秘
函数中)时在x
上运行此函数的示例
下面的代码是我用来生成这些图的代码。我作为Scheme新手编写了这段代码,但它的使用非常简单:函数(list->graphviz
)接受一个参数lst
,它是您想要作为图表的列表,以及一个可选参数graph name
,它为图形提供了一个特殊的名称
(define* (list->graphviz lst #:optional graph-name)
"""Convert a list into a set of Graphviz instructions
`lst' is the list you'd like a diagram of
`graph-name` is an optional parameter indicating the name you'd like to give the graph."""
(define number 0)
(define result "")
(define ordinals '())
(define (result-append! str)
(set! result (string-append result str)))
(define* (nodename n #:optional cell)
(format #f "cons~a~a" n (if cell (string-append ":" cell) "")))
(define* (build-connector from to #:optional from-cell)
(format #f "\t~a -> ~a;~%" (nodename from from-cell) (nodename to)))
(define (build-shape elt)
(define (build-label cell)
(cond ((null? cell) "/");; "∅") ; null character
((pair? cell) "*");; "•") ; bullet dot character
(else (format #f "~a" cell))))
(set! number (+ number 1))
(format #f "\t~a [shape=record,label=\"<car> ~a | <cdr> ~a\"];~%"
(nodename number)
(build-label (car elt))
(build-label (cdr elt))))
(define* (search xs #:optional from-id from-cell)
(let ((existing (assq xs ordinals)))
(cond
;; if we're not dealing with a pair, don't bother making a shape
((not (pair? xs)) (result-append! "\tnothing [shape=polygon, label=\"not a pair\"]\n"))
((pair? existing)
(result-append! (build-connector from-id (cdr existing) from-cell)))
(else
(begin
(result-append! (build-shape xs))
(set! ordinals (assq-set! ordinals xs number))
(let ((parent-id number))
;; make a X->Y connector
(if (number? from-id)
(result-append! (build-connector from-id parent-id from-cell)))
;; recurse
(if (pair? (car xs)) (search (car xs) parent-id "car"))
(if (pair? (cdr xs)) (search (cdr xs) parent-id "cdr"))))))))
(search lst)
(string-append "digraph " graph-name " {\n" result "}\n"))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;; Here is where `mystery' begins ;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define t '(1 2 3))
(set-cdr! (cddr t) t)
(define (mystery x)
(define (loop x y graph-num)
(display (list->graphviz x (format #f "graph~a" graph-num)))
(if (null? x)
y
(let ((temp (cdr x)))
(set-cdr! x y)
(loop temp x (+ 1 graph-num)))))
(loop x '() 0))
(mystery t)
如果您多次运行
list->graphviz
,此命令将生成一个postscript文件,该文件的优点是可以将每个列表分隔为自己的页面dot
还可以输出PNG、PDF和许多其他文件格式,如。secrety
通过反复剪掉每个条目的cdr
并将其替换为上一个x
的cdr
来反转“在位”数组
如果此列表没有循环,那么当您返回到原始的'()
时,它将结束反转。如果有一个循环,您将拥有原始数组的指针
这绝对是一个难以理解的问题。如果你做一个方框和指针图,它肯定会有帮助,你只需要画3个图表
自动生成列表图表 在这个过程中,我发现自己想要一种可视化列表突变的方法(并跳过无数的“绘制列表图…”练习)。我为此编写了一个小函数,我想如果我共享它,您可能会发现它很有用 这些图表是每次运行
循环
(在神秘
函数中)时在x
上运行此函数的示例
下面的代码是我用来生成这些图的代码。我作为Scheme新手编写了这段代码,但它的使用非常简单:函数(list->graphviz
)接受一个参数lst
,它是您想要作为图表的列表,以及一个可选参数graph name
,它为图形提供了一个特殊的名称
(define* (list->graphviz lst #:optional graph-name)
"""Convert a list into a set of Graphviz instructions
`lst' is the list you'd like a diagram of
`graph-name` is an optional parameter indicating the name you'd like to give the graph."""
(define number 0)
(define result "")
(define ordinals '())
(define (result-append! str)
(set! result (string-append result str)))
(define* (nodename n #:optional cell)
(format #f "cons~a~a" n (if cell (string-append ":" cell) "")))
(define* (build-connector from to #:optional from-cell)
(format #f "\t~a -> ~a;~%" (nodename from from-cell) (nodename to)))
(define (build-shape elt)
(define (build-label cell)
(cond ((null? cell) "/");; "∅") ; null character
((pair? cell) "*");; "•") ; bullet dot character
(else (format #f "~a" cell))))
(set! number (+ number 1))
(format #f "\t~a [shape=record,label=\"<car> ~a | <cdr> ~a\"];~%"
(nodename number)
(build-label (car elt))
(build-label (cdr elt))))
(define* (search xs #:optional from-id from-cell)
(let ((existing (assq xs ordinals)))
(cond
;; if we're not dealing with a pair, don't bother making a shape
((not (pair? xs)) (result-append! "\tnothing [shape=polygon, label=\"not a pair\"]\n"))
((pair? existing)
(result-append! (build-connector from-id (cdr existing) from-cell)))
(else
(begin
(result-append! (build-shape xs))
(set! ordinals (assq-set! ordinals xs number))
(let ((parent-id number))
;; make a X->Y connector
(if (number? from-id)
(result-append! (build-connector from-id parent-id from-cell)))
;; recurse
(if (pair? (car xs)) (search (car xs) parent-id "car"))
(if (pair? (cdr xs)) (search (cdr xs) parent-id "cdr"))))))))
(search lst)
(string-append "digraph " graph-name " {\n" result "}\n"))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;; Here is where `mystery' begins ;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define t '(1 2 3))
(set-cdr! (cddr t) t)
(define (mystery x)
(define (loop x y graph-num)
(display (list->graphviz x (format #f "graph~a" graph-num)))
(if (null? x)
y
(let ((temp (cdr x)))
(set-cdr! x y)
(loop temp x (+ 1 graph-num)))))
(loop x '() 0))
(mystery t)
如果您多次运行
list->graphviz
,此命令将生成一个postscript文件,该文件的优点是可以将每个列表分隔为自己的页面dot
还可以输出PNG、PDF和许多其他文件格式作为。如何绘制每个列表的cons单元格的内容?eq?
做什么?调用(生成循环t)
后,t是否循环?据我所知,t在执行行(生成循环t)后变为循环。(eq?(t)t)是检测列表内循环的测试。如果有循环则为真,否则为假。如果我尝试执行,行“(eq?(神秘的w)w)”抛出错误。我不明白为什么。eq?
在其参数相同时返回true(想想“指针比较”):。特别是,没有尝试检测循环。除非另有规定,否则接受列表的函数可能不会在有循环时终止。如何绘制每个列表的cons单元格的内容?eq?
做什么?调用(生成循环t)
后,t是否循环?据我所知,t在执行行(生成循环t)后变为循环。(eq?(t)t)是检测列表内循环的测试。如果有循环则为真,否则为假。如果我尝试执行,行“(eq?(神秘的w)w)”抛出错误。我不明白为什么。eq?
在其参数相同时返回true(想想“指针比较”):。特别是,没有尝试检测循环。除非另有规定,否则接受列表的函数可能不会在出现循环时终止。非常感谢您的回复。但我仍然不明白为什么在循环的情况下,我会得到原始数组的指针,为什么我会得到一些东西,因为过程(神秘z)根本不会终止。请你澄清一下,3个图应该说明什么。我会很感激的。非常感谢。我画了所有的细节后才明白。很抱歉再次打扰您。@Oliver我添加了关于如何自动绘制列表的更多信息。非常感谢您的回复。但我仍然不明白为什么在循环的情况下,我会得到原始数组的指针,为什么我会得到一些东西,因为过程(神秘z)根本不会终止。请你澄清一下,3个图应该说明什么。我会很感激的。非常感谢。我画了所有的细节后才明白。抱歉再次打扰您。@Oliver我添加了一些关于如何自动