简体   繁体   中英

R5RS scheme code find sum of the even elements in a list(recursive and higher order abstractions)?

(define mylist (list 1 2 3 5 8 9 10))

;;sum of the squares of the even elements of mylist
(define (evens lis)
  (cond (;; Check stop condition 1
         (null? lis)
         '())
        (;; Check stop condition 2: list of length = 1
         (null? (cdr lis))
         '())
        (else
         ;; Check: Building list with second element
         ;; The previous cond clauses have already sorted out
         ;; that lis and (cdr lis) are not null.
         (cons (cadr lis)
               ;; Check: Recurse "the rest of the rest" of lis with cddr
               (evens (cddr lis))))))

(define (sum-even lis)
  (if (null? lis)
  0
  (+ (expt (car lis) 2) (sum-even(cdr lis))))) ;;add all squared even elements

(sum-squared-even (evens mylist))

Here is my attempt to find the sum of the squares of the even elements in the list. However, I am really new to r5rs, is that possible I can write these scheme into only one procedure? Also, I was asked to write a second version in terms of map, foldr, and filter . Hope anyone familiar with r5rs can help me out! Thanks!

First of all, your function is wrong since you do not test the numbers of the list for evenness. This should be the correct definition:

;;even elements of a list
(define (evens lis)
  (cond (;; Check stop condition
         (null? lis)
         '())
        (;; Check if first element is even,
         ;; return it with the evens of the rest of the list
         (even? (car lis))
         (cons (car lis) (evens (cdr lis))))
        (else
         ;; First element is odd, return only the evens of the rest of the list
         (evens (cdr lis)))))

Then, to answer to your first question, this is a solution with a single recursive function:

;;sum of the squares of the even elements of a list
(define (sum-square-evens lis)
  (cond ((null? lis)
         0)
        (;; Recurring, first case: the first element is even, so square it
         ;; and add to the result of summing the square of the evens of the rest of the list
         (even? (car lis))
         (+ (expt (car lis) 2)
            (sum-square-evens (cdr lis))))
        (else
         ;; Recurring, when the first element is not even
         ;; the result is obtained by summing the square of the evens of the rest of the list
         (sum-square-evens (cdr lis)))))

Finally here is the function written with foldl-map-filter :

(define (sum-square-evens-2 lis)
  (foldl + 0 (map (lambda(x) (expt x 2)) (filter even? lis))))

but note that foldl is not a primitive function of R5RS Scheme, so you should run your program with DrRacket with the #lang racket specification, or you should define it or load a library in which it is defined.

Here is the meaning of the second function:

  1. filter applies a predicate to all the elements of a list, a returns a new list containing all the elements that satisfy the predicate. In this case the predicate is even? , so the result of (filter even? lis) is the list of all the even numbers of lis .
  2. To this list the map high order function is applied, to produce as result the results of the function first argument (in this case a function that squares its argument) applied to its second argument (a list). So the result of (map ...) is a new list containing the squares of all the even elements of the original list.
  3. Finally, (foldl + 0 (n1 n2 ...nk)) returns (...((0 + n1) + n2) + ... + nk) , since it repeatedly applies the binary function + to the elements of the list, using 0 as its first (left) operand. (Note that foldl and foldr are in this case equivalent, the second one calculating the sum as (n1 + (n2 + ...(nk + 0)...)) )

Here's how I would do it; I'll leave to you the definitions of sum and square :

(sum (map square (filter even? '(1 2 3 5 8 9 10))))

It's handy to collect convenience functions like sum and square in a library that is loaded automatically when you start your Scheme interpreter, so you can write simple expressions like this without delay.

Your sum_even has perhaps a wrong name as it will square every element and sum it together, thus square-sum is perhaps a better name.

If you wanted the even placed elements to be squared and summed you just use the two procedures you have posted:

(define (square-sum-even lst)
  (square-sum (evens lst)))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM