无法理解诡计方案代码中的错误



>我正在尝试使用Guile Scheme在终端上打印帕斯卡三角形。
什么是帕斯卡三角形?

这是脚本:

#!/usr/local/bin/guile 
-e main -s 
!#
(define (fact-iter product counter max-count)
(if (> counter max-count)
product
(fact-iter (* counter product) (+ counter 1) max-count)))
(define (factorial n)
(fact-iter 1 1 n))
(define (n-C-r n r) 
(/ (factorial n) (* (factorial (- n r)) (factorial r))
)
)

(define (row-iter r l n)
(cond   ((= r 0) ((display 1) (row-iter (+ r 1) l n)))
((and (> r 0) (< r l)) ((display (n-C-r l r)) (display " ") (row-iter (+ r 1) l n)))
((= r l) (display 1))
)
)

(define (line-iter l n)
(cond ((<= l n) ( (row-iter 0 l n)
(line-iter (+ l 1) n) ) )
)
)
(define (pascal-triangle n)
(line-iter 0 n) )
(define (main args)
(pascal-triangle (string->number (car (cdr args)) 10))
)

文件名是 pascalTriangle.scm
顶部的Shebang 符号具有正确的诡计路径。
我已经通过chmod +x pascalTriangle.scm授予了权限,使用命令./pascalTriangle.scm
5运行程序

运行时,上述脚本,观察到以下输出/错误:

1回溯:在冰-9/boot-9.scm:
   157:5 [捕获 #t #<捕获关闭 ac8400=">...]
在未知文件中:
?: 4 [apply-smob/1 #

问题是您在cond中的结果表达式周围添加了多余的括号。由于cond有明确的begin因此您今天的代码如下所示:

(define (row-iter r l n)
(cond ((= r 0)
;; you see the double (( ?
((display 1)
(row-iter (+ r 1) l n)))
((and (> r 0) (< r l))
;; you see the double (( ?
((display (n-C-r l r))
(display " ")
(row-iter (+ r 1) l n)))
((= r l)
;; without double (( and thus ok
(display 1))))

需要像这样删除多余的括号:

(define (row-iter r l n)
(cond ((= r 0)
(display 1)
(row-iter (+ r 1) l n))
((and (> r 0) (< r l))
(display (n-C-r l r))
(display " ")
(row-iter (+ r 1) l n))
((= r l)
(display 1))))

如果你使用if,你将不得不使用begin

(define (row-iter r l n)
(if (= r 0)
(begin
(display 1)
(row-iter (+ r 1) l n))
(if (and (> r 0) (< r l))
(begin
(display (n-C-r l r))
(display " ")
(row-iter (+ r 1) l n))          
(display 1))))

仅修复此过程并不能解决您的问题,因为您在line-iter中也有相同的错误。您可能会在每个cond学期开始时看到双重((,但除非您正在做一些花哨的事情,否则您不应该在其他任何地方期待它。

当添加多余的括号((display "something") #t)它会被解释为(display "something")将返回一个过程,并且您希望使用参数#t检查该过程的结果。当评估所有部分时,它会失败,因为那时它会发现未定义的值不是一个过程。在某些情况下,它有效:

((if (< x 0) - +) x 1) ; absolute increment value without changing sign

在这里,您可以看到当x小于零时,第一部分被评估为评估-的结果。如果是-10则结果将-11,如果是10则应用的程序将是评估+,结果11

稍后它会发现值3不是一个过程,你得到错误。 并得到 Scheme 应该做的结果(应用 3'(#t))and it detects that 3 (in your case whatdesiplayreturns which is an unspecified value) Scheme interprets this by evaluating(显示 (n-C-r l r)' 打印某些东西和返回值,根据规范 i 未定义,因此实现者自由选择, 然后,由于括号过多,因此作为过程应用。

在 Guile 中,规范中未定义的值的结果将成为显示#<unspecified>且被 REPL 忽略的单例。您可能会发现一个 Scheme 实现,其中未指定的值是一个不带参数的过程,您的实现将完美运行,但不可移植。

Sylwester在他的回答中所说的错误是((display (n-C-r l r)) (display " ") (row-iter (+ r 1) l n)))表达式。该语句确实通过评估打印某些内容并返回未定义值((display (n-C-r l r))来解释这一点,并作为将((display (n-C-r l r))视为过度括号的过程应用。

我使用排序解决了问题。begin特殊形式用于组合多个语句并返回最后一个语句的值。 麻省理工学院方案中的测序。这在诡计计划中也有效。

开始特殊形式的语法:(begin <e1> <e2> <e3>....<en>)
它返回<en>表达式的返回值。

以下是更改的代码:

(define (row-iter n r) 
(cond ((= r 0) (begin (display 1) (display " ") (row-iter n (+ r 1))))
((and (> r 0) (< r n)) (begin (display (n-C-r n r)) (display " ") (row-iter n (+ r 1))))
((= r n) (display 1))
)
)

尽管输出未正确格式化为"三角形",但我们可以在更改代码后获得左缩进的帕斯卡三角形。

通过运行./pascalTriangle 5,我们得到的输出为

1    
1 1    
1 2 1    
1 3 3 1    
1 4 6 4 1    
1 5 10 10 5 1

最新更新