0
(define-struct position (name numshares share-price))

(define p1
(cons (make-position "INT" 10 192) (cons (make-position "SSS" 4 42) 
empty)))

mult is my helper function

(define (mult  n)
     ( * (position-numshares n) 
     (position-share-price n)))

const takes the position-numshares and the position-share-price in a list and multiplies them together.

(define (const n)
  (cond
    [(empty? n) empty]

     [(cons? n)
       (+ (mult (first n))
                )]))

What I would like to do is take the first of the list and add the rest of the list together. Instead, I only get the first of the list. So if I do (const p1) I only get 1920, but I would like to get 2088 (10*192 + 4*42). I've tried recurring for the rest, but get an error. I am probably missing something simple. Help would be appreciated.

Joshua Taylor
  • 84,998
  • 9
  • 154
  • 353
Josh
  • 499
  • 1
  • 7
  • 15

1 Answers1

2

First, note that in general, you can do

(list a b)

instead of

(cons a (cons b empty))

so you define p1 with

(define p1
  (list (make-position "INT" 10 192)
        (make-position "SSS" 4 42)))

which is easier to read, and makes your intent clearer. Now, to get 1920 from a structure created by (make-position "INT" 10 192), you've defined your helper procedure mult. You can map mult over your list p1 to get a new list of the products, i.e., (1920 168). Then you can use foldl with + and 0 on that list to compute its sum.

(define (const lst)
  (foldl + 0 (map mult lst)))

(const p1)
;=> 2088

If you don't want to use fold and map (which might be reasonable, since map means that a new list is getting allocated), you can write this out manually:

(define (const lst)
  (let const ((sum 0) (lst lst)) ; pretty much an implementation of fold, but 
    (if (null? lst)              ; with the function + built in, and mult applied
        sum                      ; to each element before passing to +
        (const (+ sum (mult (car lst)))
               (cdr lst)))))

(const p1)
;=> 2088

Another alternative would be to use foldl, but instead of passing +, pass in a function that combines + and mult:

(define (const3 lst)
  (foldl (lambda (struct sum)
           (+ (mult struct) sum))
         0
         lst))

(const3 p1)

As a Common Lisper, it's a bit disappointing to me that Scheme's foldl procedure doesn't take a key argument that gets applied to each element of the list before the function is applied to it. In Common Lisp, we'd write (foldl/foldr are reduce in Common Lisp):

(reduce '+ p1 :key 'mult)
Joshua Taylor
  • 84,998
  • 9
  • 154
  • 353
  • @Josh For more information about folds, you might have a look at [this answer about flattening a list](http://stackoverflow.com/a/19229532/1281433) and [this answer about comparing values](http://stackoverflow.com/a/19006055/1281433). (Disclaimer: those are both my answers.) – Joshua Taylor Oct 12 '13 at 20:28