0
votes

I'm brand new to Scheme, and this is a homework question, so please no outright answers.

Here is my question:

Write a recursive procedure (any? arg1 arg2 ...), where the argi's are boolean values. any? returns #t if any of its arguments is #t, and #f otherwise.

These are the constraints:

You may not use the built-in procedures map, apply, list->vector, or vector->list in any procedure. Likewise, do not use a let expression or an internal define expression in any procedure, unless the problem says otherwise.

Here is the code I have:::

(define any?
  (lambda args
    (if (null? args)
        #f
        (if (equal? #t (car args))
            #t
            (any? (cdr args))))))

My problem seems to be that I am hitting an infinite loop on the last line (any? (cdr args)). I am not sure why that is happening. My professor said a hint was to write any? as an interface procedure, and write a helper that handles the list. I am not sure how that would help.

Any advice would be appreciated!

EDIT: I have added new code. I am still getting an infinite loop.

(define any?
  (lambda args
    (any-helper args)))

(define any-helper
  (lambda (list)
    (if (null? list)
        #f
        (if (equal? #t (car list))
            #t
            (any? (cdr list))))))

I thought by writing lambda args in my main function, I would be passing a list to my helper function. I'm not sure if that is actually happening. I am not sure how to ensure that I don't recurse over '() infinitely.

2

2 Answers

1
votes

Consider the steps taken by the function application (any? #f). This leads to a recursive call to (any? '()). Next, it checks to see if the argument list in this call, '(()), is null? (which it isn't, since it is a list containing '()). (equal #t '(()) is also false, so it keeps recursing since you're calling it with the same number of arguments instead of reducing the size of the input in each recursive call.

Hey, this is my 100th answer!

1
votes

When you have a symbol argument or a dotted list as prototype the last argument, in your case args, contains the rest of the given operands.

Imagine you evaluate (any? #f 5 6) then args would be (#f 5 6). Since first argument is #f you then call (any? '(5 6)) instead of (any? 5 6).

Usually you would make a named let or a local procedure to handle a one argument list so that your code actually would work, but since you are not allowed to you need to use apply to do this instead.

(apply any? '(#f 5 6)) is the same as (any? #f 5 6). You can think of apply as the opposite as dotted list/symbol prototype in a procedure definition.

PS: Your update using any-helper would work perfectly if you recurse with any-helper instead of any?.