Scheme运行帕斯卡三角代码报错:attempt to apply non-procedure #<void>
Scheme打印帕斯卡三角报错#的问题解决
你遇到的问题核心是Scheme的括号使用规则理解有误。报错里的#<void>是display过程的返回值——因为display是用于输出的副作用过程,它不会返回有意义的值,默认返回#<void>(空值)。
你的代码里犯了一个典型错误:把多个表达式用额外的括号包裹起来,比如:
((display (pascal (+ row 1) (+ col 1))) (if (< col row) ((display " ") (prt_iter n row (+ col 1))) ((display "\n") (prt_iter n (+ row 1) 0))))
这种写法在Scheme里会被解释为:先执行第一个display得到#<void>,然后尝试把这个#<void>当成一个过程,去调用后面的if表达式作为参数——但#<void>不是可调用的过程,所以触发了报错。
而你手动测试时的代码是单独写每个display,没有多余的括号,所以不会触发这个问题。
修正后的代码
把多余的外层括号去掉,同时在if的分支里如果需要执行多个表达式,用begin来包裹(标准Scheme要求if的then/else分支只能是单个表达式,多个表达式需要用begin组合):
(define (pascal n k) (if (or (= k 1) (= k n)) 1 (+ (pascal (- n 1) (- k 1)) (pascal (- n 1) k)))) (define (prt_iter n row col) (if (< row n) (begin (display (pascal (+ row 1) (+ col 1))) (if (< col row) (begin (display " ") (prt_iter n row (+ col 1))) (begin (display "\n") (prt_iter n (+ row 1) 0)))) (display "\nfinished"))) (define (prt n) (prt_iter n 0 0)) (prt 5)
关键修改点
- 去掉了每个分支外层多余的
((...))括号,避免把display的返回值当成过程调用 - 用
begin包裹每个if分支里的多个表达式,确保它们按顺序执行(部分Scheme实现允许省略begin,但标准写法建议加上,保证兼容性)
运行修正后的代码,就能正常打印出帕斯卡三角了。
内容的提问来源于stack exchange,提问作者Van Young
相关产品推荐
相关产品推荐

