------------------------------------------------------------------------------
MC logo
Find Function Examples
[^] CSc 404 Documentation And Examples
------------------------------------------------------------------------------
find.lsp
;
; This file contains three solutins to a fund function, which searches a list 
; some requested item, and returns its zero-based position in the list (if 
; found), or -1 if not.
;   (find '(a b c d) 'a) returns 0
;   (find '(a b c d) 'b) returns 1
;   (find '(a b c d) 'd) returns 3
;   (find '(a b c d) 'z) returns -1

; *** Version 1.  This uses a recursive case to find the indicated item in the
;     tail of the list.  The recursive case must add one to the position when
;     the item is found (since it was found in a one-step shorter list), but
;     avoid that increment when the recursive case indicates the item was not
;     found.  It does this by using a let to store the result of the recursion,
;     then modifies that conditionally.
(define (find lis x)
    (cond
        ((null? lis) (- 0 1))
        ((equal? x (car lis)) 0)
        (#t (let
              ( (recval (find (cdr lis) x)) )
              (if (< recval 0) recval (+ recval 1))
            )
        )
    )
)

; *** Version 2.  This is similar to the first version, but uses a helper 
;     function to conditionally increment the result returned from the 
;     recursion, so the let is unnecessary. Both versions are similar in that
;     the keep the recursion result in a variable:  In the first place, it is
;     placed in the let variable.  In the second, the parameter x of the
;     helper function +except-neg.

; Take a number.  For negatives, return it; for others increment it.
(define (+except-neg x)
    (if (< x 0) x (+ x 1))
)

(define (find lis x)
    (cond
        ((null? lis) (- 0 1))
        ((equal? x (car lis)) 0)
        (#t (+except-neg (find (cdr lis) x)))
    )
)

; *** Version 3.  This slightly different approach adds a parameter used to
;     keep track of the nesting depth (which is also the number of list 
;     items discarded by the cdr calls) on the way in.  This becomes the
;     return value and does not need to be incremented in the recursive case.
;     This avoids the need for the recursive case to modify the result it
;     receives, and to treat -1 differently.
(define (find lis x) (find-r lis x 0))

(define (find-r lis x depth)
    (cond
        ((null? lis) (- 0 1))
        ((equal? x (car lis)) depth)
        (#t (find-r (cdr lis) x (+ depth 1)))
    )
)