简体   繁体   中英

Scheme sum of list

First off, this is homework, but I am simply looking for a hint or pseudocode on how to do this.

I need to sum all the items in the list, using recursion . However, it needs to return the empty set if it encounters something in the list that is not a number. Here is my attempt:

(DEFINE sum-list
  (LAMBDA (lst)
    (IF (OR (NULL? lst) (NOT (NUMBER? (CAR lst))))
      '()
      (+
        (CAR lst)
        (sum-list (CDR lst))
      )
    )
  )
)

This fails because it can't add the empty set to something else. Normally I would just return 0 if its not a number and keep processing the list.

I suggest you use and return an accumulator for storing the sum; if you find a non-number while traversing the list you can return the empty list immediately, otherwise the recursion continues until the list is exhausted.

Something along these lines (fill in the blanks!):

(define sum-list
  (lambda (lst acc)
    (cond ((null? lst) ???)
          ((not (number? (car lst))) ???)
          (else (sum-list (cdr lst) ???)))))

(sum-list '(1 2 3 4 5) 0)
> 15

(sum-list '(1 2 x 4 5) 0)
> ()

I'd go for this:

(define (mysum lst)
  (let loop ((lst lst) (accum 0))
    (cond
      ((empty? lst) accum)
      ((not (number? (car lst))) '())
      (else (loop (cdr lst) (+ accum (car lst)))))))

Your issue is that you need to use cond, not if - there are three possible branches that you need to consider. The first is if you run into a non-number, the second is when you run into the end of the list, and the third is when you need to recurse to the next element of the list. The first issue is that you are combining the non-number case and the empty-list case, which need to return different values. The recursive case is mostly correct, but you will have to check the return value, since the recursive call can return an empty list.

Because I'm not smart enough to figure out how to do this in one function, let's be painfully explicit:

#lang racket

; This checks the entire list for numericness
(define is-numeric-list?
  (lambda (lst)
    (cond
      ((null? lst) true)
      ((not (number? (car lst))) false)
      (else (is-numeric-list? (cdr lst))))))

; This naively sums the list, and will fail if there are problems
(define sum-list-naive
  (lambda (lst)
    (cond
      ((null? lst) 0)
      (else (+ (car lst) (sum-list-naive (cdr lst)))))))

; This is a smarter sum-list that first checks numericness, and then
; calls the naive version.  Note that this is inefficient, because the
; entire list is traversed twice: once for the check, and a second time
; for the sum.  Oscar's accumulator version is better!
(define sum-list
  (lambda (lst)
    (cond
      ((is-numeric-list? lst) (sum-list-naive lst))
      (else '()))))

(is-numeric-list? '(1 2 3 4 5))
(is-numeric-list? '(1 2 x 4 5))

(sum-list '(1 2 3 4 5))
(sum-list '(1 2 x 4 5))

Output:

Welcome to DrRacket, version 5.2 [3m].
Language: racket; memory limit: 128 MB.
#t
#f
15
'()
> 

I suspect your homework is expecting something more academic though.

Try making a "is-any-nonnumeric" function (using recursion); then you just (or (is-any-numeric list) (sum list)) tomfoolery.

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