LISP: how to get the current amount of the list? (without global variable)

I am new to LISP.

To get the current amount of the list, I write:

(setf sum 0.0)
(mapcar #'(lambda(x)
    (setf sum (+ sum x)) sum) values))

For example, if you enter '(1 2 3 4)as input, the above code returns '(1 3 6 10)as output, etc.

Is it possible to do the same (in a more elegant way) without using a global variable sum?

+5
source share
5 answers
(loop for x in '(1 2 3 4) sum x into y collect y)

scanl is oneliner:

(defun scanl (f init xs)
  (loop for x in xs collect (setf init (funcall f init x))))
+6
source

You can use loop, for example:

(defun running-sum (xs)
  (loop with sum = 0
        for x in xs
        collect (setf sum (+ sum x))))

(running-sum '(1 2 3 4))

In principle, this is one and the same thing, but instead of a global one, a local variable is used and can be more understandable.

Alternatively, you can define a recursive function and a wrapper function:

(defun running-sum-recursive (xs)
  (running-sum-recursive2 0 xs))

(defun running-sum-recursive2 (sum xs)
  (if (eq xs nil)
    nil
    (let ((new-sum (+ sum (car xs))))
      (cons new-sum (running-sum-recursive2 new-sum (cdr xs))))))

(running-sum-recursive '(1 2 3 4))

, loop .

, Haskell :

runningSum xs = scanl1 (+) xs

runningSum [1, 2, 3, 4]

scanl1 function. , - Lisp ( ), Lisp .

: , Common Lisp - scanl scanl1, :

(defun scanl (f val xs)
  (loop for x in xs
        collect (setf val (funcall f val x))))

(defun scanl1 (f xs)
  (cons (car xs)
        (scanl f (car xs) (cdr xs))))

(scanl1 #'+ '(1 2 3 4))

: huaiyuan , .

+4

Haskell , reduce . ( ) loop):

(defun running-sum (lst)
  (reverse (reduce (lambda (acc x)
                     (cons (+ (first acc) x) acc))
                   (rest lst)
                   :initial-value (list (first lst)))))

, ( ), , , .

reduce, , .

, push - nreverse idiom:

(defun running-sum (lst)
  (let ((sums (list (first lst))))
    (dolist (x (rest lst))
      (push (+ x (first sums)) sums))
    (nreverse sums)))
+2

(define (running-sum ls)
     (cdr (reverse (foldl (lambda (y xs) (cons (+ (car xs) y) xs)) '(0) ls))))
+2

. :

; Computes a list of intermediary results of list summation
(define list-sum
  (lambda (l)
    (letrec ((recsum (lambda (lst acc acclst)
      (if (pair? lst)
        (recsum (cdr lst) (+ acc (car lst)) (cons acc acclst))
        (cons acc acclst)))))
    (recsum (cdr l) (car l) '()))))

:

> (list-sum '(1 2 3 4))   
(10 6 3 1)
> (list-sum '(2 4 6 8 10))
(30 20 12 6 2)
> 

, , , / /cdr. , ( ) . : .

I never did anything in LISP, so I can’t say if it translates directly to your dialect (?), But it is conceptually simple, and I’m sure that it is possible in LISP as well.

Ask if something is clear. Some time has passed since I used this family of languages ​​:)

+1
source

All Articles