>我正在尝试使用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 what
desiplayreturns 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