Background: I was working on a project in guile 1.8.8 scheme a few weeks ago and, being a little rusty, I forgot about the built-in (reduce) function, so I rolled my own. A little later, I ran into what seemed to be a hopeless bug, where calling a function with no side effects changed the flow of the rest of the program (working properly and passing a few unit tests vs. crashing completely) AFTER the function had long since returned. Several pieces of code which used to return something like (A B C D) were now returning only (A), causing a multitude of problems.
Minimum working example: After several days of whittling, I cornered the problem into this small piece of stand-alone code:
(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)))
Which prints out 6 1 1, instead of the expected 6 1 6.
Additional observations:
- Setting the second line to a
+yields the expected6 6 6. - Setting the second line to
andyields6 3 3. - Additional lines of
+after these produce additional1s or3s depending on what the second line is set to. So, the sequence+or++leads to the output6 1 1 1. - Additional lines of
andororafter the first do NOT switch the output back. So, if the sequence is+andor+, the output is6 3 3 3. It seems as though, once I've passedororandto(my-reduce), the function becomes permanently "stuck" having that as its argument. - I also notice that passing
andororto the built-in(reduce)function causes a type-error, since they are technically macros and not functions. - Along those same lines, I notice that swapping out
orfor(lambda (x y) (or x y))yields the expected output. Therefore, it seems that the critical thing here is that passing macros to my home-rolled reduce function causes an issue.
Question: What is going on here? Why does calling (my-reduce) with and or or cause such unexpected behavior? Does it have to do with the fact that those "functions" are actually macros?
Thanks in advance for any help. This one has really stumped me!