I\'m new to Scheme and functional programming in general. Can someone explain this code — specifically what kons and knil are? The goal is to flat
The procedure shown is an implementation of fold:
In functional programming, fold – also known variously as reduce, accumulate, aggregate, compress, or inject – refers to a family of higher-order functions that analyze a recursive data structure and recombine through use of a given combining operation the results of recursively processing its constituent parts, building up a return value
Take note:
kons parameter is a two-argument function that's used for "combining" the current element of the list being processed with the accumulated valueknil parameter is the accumulated output resultTo see how this works, imagine for a moment that we have a function such as this:
(define (reverse knil lst)
(if (null? lst)
knil
(reverse (cons (car lst) knil) (cdr lst))))
(reverse '() '(1 2 3 4))
=> '(4 3 2 1)
In the above knil is used to accumulate the result, and it starts in a value of '() because we're building a list as output. And kons is called cons, which builds lists. Let's see another example:
(define (add knil lst)
(if (null? lst)
knil
(add (+ (car lst) knil) (cdr lst))))
(add 0 '(1 2 3 4))
=> 10
In the above knil is used to accumulate the result, and it starts in a value of 0 because we're building a number as output. And kons is called +, which adds numbers.
By now you must have realized that both examples share the same structure of a solution, both consume an input list and the only things that change is how we "combine" the values pulled from the list and the starting accumulated value. If we're smart, we can factor out the parts that change into a higher order procedure, that receives the changing parts as parameters - thus fold1 is born:
(define (fold1 kons knil lst)
(if (null? lst)
knil
(fold1 kons (kons (car lst) knil) (cdr lst))))
And both of the above examples can be easily expressed in terms of fold1, just pass along the right parameters:
(define (reverse lst)
(fold1 cons '() lst))
(define (add lst)
(fold1 + 0 lst))
Now for the second part of the question: if you want to flatten a list with fold1 you can try this:
(define (helper x lst)
(if (pair? x)
(fold1 helper lst x)
(cons x lst)))
(define (flatten lst)
(reverse (helper lst '())))
(flatten '(1 2 (3) (4 (5)) 6))
=> '(1 2 3 4 5 6)