Search code examples
schemelispchicken-scheme

Any tips on creating interfaces for a function in Scheme LISP


I've been doing some genetic programming with Chicken Scheme. I have been defining functions to have interfaces since internally a function might need to iterate over a list.

I want to avoid exposing all of these details to the caller.

EG:

(define (find-errors trees target)
    (define (error-loop evaluated-trees trees-to-evaluate target)
        (if (equal? (length trees-to-evaluate) 0)
            evaluated-trees
            ;pop tree from head of trees-to-evaluate, add it to evaluate-trees, call loop again
    )
    (error-loop (list) trees target)
)

Perhaps this looping function does not seem too complex but there will be more complex loops that require more parameters. I just want to avoid exposing extra information to the functions that call other functions.

Is there a more idiomatic way to do it? This seems to be a thorough style guide but I couldn't find a reference to function interfaces.

For example, is this preferable? If I was going to have a loop outside of where it is used, would it make sense to have some way to name the function so that people know it is for internal use?

(define (_error-loop evaluated-trees trees-to-evaluate target)
    (if (equal? (length trees-to-evaluate) 0)
        evaluated-trees
        ;pop tree from head of trees-to-evaluate, add it to evaluate-trees, call loop again
)

(define (find-errors trees target)
    (_error-loop (list) trees target)
)

Thanks


Solution

  • In this particular case of a recursive function that starts with some of the top level function's arguments and possibly a extra accumulator argument, a named let is invaluable syntactic sugar:

    (define (find-errors trees target)
        (let loop ((evaluated-trees '())
                   (trees-to-evaluate trees))
            (if (null? trees-to-evaluate)
                evaluated-trees ; possibly (reverse evaluated-trees)
                (loop (cons (evaluate-error (car trees-to-evaluate) target) evaluated-trees)
                      (cdr trees-to-evaluate)))))
    

    map is also a good fit here, eliminating the explicit loop entirely:

    (define (find-errors trees target)
        (map (lambda (tree) (evaluate-error tree target)) trees))
    

    In general, though, using let[rec] vs define inside a function to define private helper functions vs using top-level definitions is pretty much a matter of preference, style and opinion, and thus isn't really on topic for Stack Overflow.