schemeracketr5rs

Applying operations on Scheme (R5RS) with a condition


I'm trying to create a Scheme program (Language R5RS) which applies an operation to a set of lists, depending on how big a number is on a list.

So the function looks like

(apply-function f g)

The condition is, if f(a b) where a < 5, then apply operation f(a b).

But if a is equal or greater than 5, apply g(a b). (The second operation)

This sounds confusing but a visual example should clear it up: So, an example would be

((apply-function '* '+) '((2 3) (8 6)))

Would return:

'(6 14)

Another example would be

((apply-function '* '+) '((5 7) (2 3) (3 3))

Returns

'(12 6 9)

I've tackled operations on Scheme before, but the condition part is throwing me off and I'm not sure where to start. Any help is appreciated!


Solution

  • Version 1: If you use procedures + and * instead of symbols '+ and '*:

    #lang r5rs
    
    (define apply-function
      (lambda (f g)
        (lambda (lop)
          (map (lambda (p)
                 (if (< (car p) 5)
                      (f (car p) (cadr p))
                      (g (car p) (cadr p))))
               lop))))
    
    (display ((apply-function * +) '((2 3) (8 6))))
    (newline) 
    (display ((apply-function * +) '((5 7) (2 3) (3 3))))
    

    Version 2: You can make an association list matching symbols to procedures

    #lang r5rs
    
    (define proc-list `((* . ,*) (+ . ,+)))
    
    (define (get-proc s)
      (let ((p (assq s proc-list)))
        (if p (cdr p) s)))
    
    
    (define apply-function
      (lambda (f g)
        (lambda (lop)
          (map (lambda (p) 
                 (if (< (car p) 5)
                     ((get-proc f) (car p) (cadr p))
                     ((get-proc g) (car p) (cadr p))))
               lop))))
    
    (display ((apply-function '* '+) '((2 3) (8 6))))
    (newline) 
    (display ((apply-function '* '+) '((5 7) (2 3) (3 3))))
    

    Version 3: Uses eval

    #lang r5rs
    
    (define (my-eval e)
      (eval e (scheme-report-environment 5)))
    
    (define apply-function
      (lambda (f g)
        (lambda (lop)
          (map (lambda (p) (if (< (car p) 5)
                               (my-eval (list f (car p) (cadr p)))
                               (my-eval (list g (car p) (cadr p)))))
               lop))))
    
    (display ((apply-function '* '+) '((2 3) (8 6))))
    (newline) 
    (display ((apply-function '* '+) '((5 7) (2 3) (3 3))))