'Passing in a binary function into a Scheme function

Apologies if this is a common question. Searching up "Racket passing in lambda as an argument" doesn't return much. I'm trying to write a Racket function lsf that takes in an optional lambda function, and applies it to corresponding elements in two same-sized lists. This lambda defaults to addition.

For example, > (lsf '(2 4 5) '(6 7 8) (lambda (a b) (- b a))) should return a list '(4 3 3)

> (lsf '(2 5) '(3 6)) returns '(5 11) (defaults to addition).

Here's what I have so far:

( define ( lsf list1 list2 )
    ( if ( null? list1 )
        '()
        ( cons( + ( car list1 list2 )) 
            ( lsf ( cdr list1 ) ( cdr list2 )))
    )
)

How do I add this default addition function as a parameter (I think it goes after list2?), and how would I use it in place of the "+" that I have after cons?



Solution 1:[1]

In addition to rest-args and optionals (see other answers), Racket still has case-lambda (as in r6rs Scheme), so:

#lang racket

(define lsf
  (case-lambda
    [(list1 list2) ;; (Listof Number) (Listof Number) -> (Listof Number)
     ;; produce list of sums of corresponding elements of list1, list2
     (lsf list1 list2 +) ]
    [(list1 list2 combine) ;; (Listof X) (Listof Y) (X Y -> Z) -> (Listof Z)
     ;; produce list applying combine to corresponding elements
     (if (null? list1)
         '()
         (cons (combine (car list1) (car list2)) 
               (lsf (cdr list1) (cdr list2) combine))) ]))

And then:

> (lsf '(2 5) '(3 6))
'(5 11)

> (lsf '(1 2 3) '(#\a #\b #\c) make-string)
'("a" "bb" "ccc")

Solution 2:[2]

Use . in the parameter list to define a rest-arg, which gets a list of all the additional arguments. If the optional argument is supplied, this will be non-null and you can get the argument as its first element.

(define (lsf list1 list2 . rest)
  (if (null? list1)
      '()
      (let ((func (if (null? rest) + (first rest)))) ; default func to +
        (cons (func (car list1) (car list2))
              (lsf (cdr list1) (cdr list2) func)))))

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 mnemenaut
Solution 2 Barmar