Dear schemers,
For your information, we have been using "our own" version of conjoin and disjoin for the past decade. Only to find that srfi-235 has made them available with a different meaning. For conjoin srfi-235 states: The predicates are applied in turn to the args as follows: If a call to a predicate returns false, no more predicates are applied and #f is returned. If all predicates return true, then the last value is returned. If there are no predicates, #t is returned. But this language is ambiguous. I found two LISP interpretations that are consistent with each other and our interpretation, but disagree with the current version of conjoin in srfi-235, see: https://www.lisppad.app/libraries/lispkit/lispkit-combinator, conjoin: Returns a function invoking all functions f ... and combining the results with and. ((conjoin f1 f2 ...) x ...) is equivalent to (and (f1 x ...) (f2 x ...) ...). and https://common-lisp-libraries.readthedocs.io/alexandria/ (defun conjoin (predicate &rest more-predicates) "Returns a function that applies each of PREDICATE and MORE-PREDICATE functions in turn to its arguments, returning NIL if any of the predicates returns false, without calling the remaining predicates. If none of the predicates returns false, returns the primary value of the last predicate." (if (null more-predicates) predicate (lambda (&rest arguments) (and (apply predicate arguments) ;; Cannot simply use CL:EVERY because we want to return the ;; non-NIL value of the last predicate if all succeed. (do ((tail (cdr more-predicates) (cdr tail)) (head (car more-predicates) (car tail))) ((not tail) (apply head arguments)) (unless (apply head arguments) (return nil))))))) I propose to change the current meaning and the implementation of both conjoin and disjoin in srfi-235 to the ones here below: (define (conjoin . procs) "Like AND with procedures, i.e. ((conjoin p1 p2 ...) x ...) is equivalent to (and (p1 x ...) (p2 x ...) ...)." (lambda args (every (lambda (proc) (apply proc args)) procs))) (define (disjoin . procs) "Like OR with procedures, i.e. ((disjoin p1 p2 ...) x ...) is equivalent to (or (p1 x ...) (p2 x ...) ...)." (lambda args (any (lambda (proc) (apply proc args)) procs))) Where I have replaced predicates with procedures, apply each procedure to all of the arguments, and use every and any instead of a dedicated loop algorithm. Please also see guile issue 115: https://codeberg.org/guile/guile/pulls/115 and the updated tests. Kind regards, Regtur. -- Rutger van Beusekom <[email protected]> Free Software for Correctness Correctness for Free Software https://reasonable-sourcery.coop
