为什么用宏调用我的自制(归约)函数会影响以后对该函数的调用?

Why does calling my home-rolled (reduce) function with a macro affect future calls to the function?

背景: 几周前,我在 guile 1.8.8 方案中从事一个项目,有点生疏,我忘记了内置的 (reduce) 功能,所以我推出了自己的功能。过了一会儿,我 运行 遇到了一个似乎无可救药的错误,其中调用一个没有副作用的函数改变了程序其余部分的流程(正常工作并通过一些单元测试与完全崩溃) AFTER 函数早已 returned。以前 return 类似 (A B C D) 的几段代码现在 return 只 (A),导致了很多问题。

最小工作示例:经过几天的磨合,我将问题解决到这一小段独立代码中:

(define (my-reduce fun ls)
    (if (null? (cdr ls))
        (car ls)
        (my-reduce fun (cons (fun (car ls) (cadr ls))
                             (cddr ls)))))

(format #t "~a "  (my-reduce +   '(1 2 3)))
(format #t "~a "  (my-reduce or  '(1 2 3)))
(format #t "~a~%" (my-reduce +   '(1 2 3)))

打印出 6 1 1,而不是预期的 6 1 6

补充观察:

问题:这是怎么回事?为什么用 andor 调用 (my-reduce) 会导致这种意外行为?这与那些 "functions" 实际上是宏的事实有关吗?

在此先感谢您的帮助。这个真的难倒我了!

你自己说了,你不能将 andor 作为需要函数的参数传递,因为它们是 macros,并且会报 "bad syntax" 错误。事实上,我什至不明白这对你有什么用:

(my-reduce or '(1 2 3))

我能想到的唯一办法就是你把andor重新定义为某处的函数,那个就是问题的根源。作为旁注,my-reduce(理解为折叠右操作)可以以更标准的方式实现,如下所示:

(define (my-reduce fun ls)
  (if (null? (cdr ls))
      (car ls)
      (fun (car ls)
           (my-reduce fun (cdr ls)))))

上面假设列表是非空的,如果情况并非总是如此,通常是传递一个初始值作为参数:

(define (my-reduce fun init ls)
  (if (null? ls)
      init
      (fun (car ls)
           (my-reduce fun init (cdr ls)))))