You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Racket(Lisp)程序计算正常却报错:期望可应用参数的过程

帕斯卡三角Racket程序执行正确却报错的原因分析

问题描述

为何以下生成帕斯卡三角的Racket程序能正确完成计算并输出结果,却仍出现错误提示application: not a procedure; expected a procedure that can be applied to arguments?我已确保print_pascal函数在所有可返回位置都返回#f。

原代码

#!/usr/bin/racket
#lang racket/base

(define (pascal_value row column)
  (cond ((< row 0) 0)
        ((< column 0) 0)
        ((= column 1) 1)
        ((= column row) 1)
        ((> column row) 0)
        (else (+ (pascal_value (- row 1) (- column 1)) (pascal_value (- row 1) column )))
        )
  )

(pascal_value 6 4)
(define (pascal_triangle max_rows)
  (define (print_pascal row column)
    (cond
     ((> row max_rows) (printf "done\n") #f)
     (else (cond ((= column row) (
                                  (printf "~a\n" (pascal_value row column))
                                  (print_pascal (+ row 1) 1)
                                  ) #f)
                 (else (
                        (printf "~a " (pascal_value row column))
                        (print_pascal row (+ column 1))
                        )
                       #f
                       )
                 )
           #f
           )
     )
    #f
    )
  (print_pascal 1 1)
  )

(pascal_triangle 7)

执行输出

[I] ➜ ./1_12.lisp
10
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
done
application: not a procedure;
 expected a procedure that can be applied to arguments
  given: #<void>
  context...:
   /home/ubuntu/Software/code_samples/sicp_exercises/1_12.lisp:17:2: print_pascal
   [repeats 28 more times]
   body of "/home/ubuntu/Software/code_samples/sicp_exercises/1_12.lisp"

错误原因

问题出在多余的括号嵌套上。在Racket中,括号()的核心作用是调用过程,如果你把多个表达式用额外的括号包裹,Racket会把第一个表达式的返回值当作可调用的过程,去执行后面的参数。

比如原代码里的这段:

((printf "~a\n" (pascal_value row column))
 (print_pascal (+ row 1) 1))

printf执行后返回的是#<void>,Racket会尝试把这个#<void>当作过程去调用后面的(print_pascal ...),但#<void>并非可调用的过程,因此触发了application: not a procedure错误。

程序能正常输出结果,是因为printf和递归调用print_pascal已经完成了执行,但执行结束后这个错误逻辑被触发,导致报错。你添加的#f是在嵌套括号之外,无法阻止括号内的错误逻辑执行。

修正后代码

(define (pascal_triangle max_rows)
  (define (print_pascal row column)
    (cond
     ((> row max_rows) (printf "done\n"))
     (else (cond ((= column row) (printf "~a\n" (pascal_value row column)) (print_pascal (+ row 1) 1))
                 (else (printf "~a " (pascal_value row column)) (print_pascal row (+ column 1)))))
     ))
  (print_pascal 1 1)
  )

(pascal_triangle 9)

修正时去掉了多余的嵌套括号,让多个表达式直接按顺序执行(Racket中(expr1 expr2)会先执行expr1,再执行expr2,最终返回expr2的结果)。同时无需额外返回#f,因为cond会自动返回最后一个表达式的结果,而printf返回的#<void>不会引发错误——因为没有尝试把它当作过程调用。


内容的提问来源于stack exchange,提问作者urmish

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 04:05:14