在Scheme中如何将函数作为参数传入另一函数并循环调用
代码存在的核心问题
- 函数名与形参定义不匹配:你定义的打印函数名为
printermsg,但调用forLoop时传入的函数名是printer;且printermsg没有定义形参,函数内部使用的msg属于未绑定变量,运行会报错。 loopBody参数解析错误:传入的loopBody是'(printer "text "),cdr loopBody得到的是仅包含字符串的列表("text "),而非你预期的单个字符串值。- 递归参数传递错误:递归调用时写的
'(fun str)是被引号包裹的字面量列表,不会对之前let绑定的fun、str变量求值,每次递归传入的都是符号本身而非实际的函数和参数。 - 逻辑与需求不符:你当前代码的逻辑是拼接字符串列表,而非调用传入的函数执行打印操作,且判断
reps = 0的逻辑完全没必要使用eval,属于冗余错误用法。
修复实现
方案1:保留你原有的传参格式
先修正打印函数的定义:
; 定义带形参的打印函数 (define (printer msg) (display msg))
修正forLoop的实现:
(define (forLoop loopBody reps) (let ((fun (car loopBody)) (print-content (cadr loopBody))) (cond ((= reps 0) (newline)) (else ; 执行传入的打印函数,传入对应参数 ((eval fun (interaction-environment)) print-content) ; 递归执行剩余次数 (forLoop loopBody (- reps 1))))))
调用代码和你原有写法一致:
(forLoop '(printer "text ") 4)
方案2:更简洁的函数式通用实现
不用传列表包裹的函数和参数,直接传入要执行的过程,逻辑更清晰不易出错:
(define (forLoop proc reps) (if (> reps 0) (begin (proc) (forLoop proc (- reps 1))) (newline)))
调用方式:
; 用lambda包裹你要循环执行的逻辑 (forLoop (lambda () (display "text ")) 4)
两种方案运行后都会输出你预期的text text text text 。
内容的提问来源于stack exchange,提问作者COM
相关产品推荐
相关产品推荐

