Search code examples
listrecursionschememessage-passingr5rs

Recursive method in Scheme


I have a (in theory) simple method in Scheme, that has to use recursion. The problem is that I can't seem to figure out the recursion part... I have a procedure that takes a 'pointer' and arbitrary many arguments, and I need to pass the arguments one by one to another method. Here is what I got so far:

(define (push-elements ptr . args)
    (define (push-all ptr list)
        (if (null? list)
            '()
            (ptr 'push-elements (car list))))
     (push-all ptr list))

I know there is no recursion here, but I can't understand where to put it/how to do it. The thought is clear, inside 'push-all' I need to call:

(push-all ptr (cdr list))

If anyone could help me (and I would be very grateful for an explanation on how to go about making such a recursive method), that would be great.


Solution

  • Basically you are implementing a variant of for-each, which is like map just for the side effects:

    (define (for-each procedure lst)
      (let loop ((lst lst))
        (if (null? lst)        
            'undefined-value
            (begin
              (procedure (car lst))
              (loop (cdr lst))))))
    
    (for-each display (list 1 2 3 4)) ; prints 1234
    

    But you wanted to be able to specify the values as arguments so you need to change lst to be a rest argument:

    (define (for-each-arg procedure . lst) ; changed to dotted list / rest here
      (let loop ((lst lst))
        (if (null? lst)        
            'undefined-value
            (begin
              (procedure (car lst))
              (loop (cdr lst))))))
    
    (for-each-arg display 1 2 3 4) ; prints 1234
    

    If you want a more functional approach you are indeed making either a map or a fold. Perhaps a fold-left would be preferred:

    (define (fold-args join init . lst)
      (let loop ((acc init) (lst lst))
        (if (null? lst)
            acc
            (loop (join (car lst) acc) (cdr lst)))))
    
    (fold-args cons '() 1 2 3 4) ; ==> (4 3 2 1)
    

    You can actually implement for-each-arg with this:

    (define (for-each-arg procedure . lst)
      (apply fold-args 
             (lambda (x acc) 
               (procedure x) 
               'undefined) 
             'undefined 
             lst))
    
    (for-each-arg display 1 2 3 4) ; => undefined-value; prints 1234