2016-09-24 3 views
0

Ich habe mich schon einige Wochen lang bemüht, eine Accumulate-Funktion zu implementieren. Ich habe eine "Map" -Funktion ordnungsgemäß implementiert, die über eine Liste iteriert und eine Funktion für jedes Element ausführt.Implementieren der "Accumulate" -Funktion im Schema

ich diese Funktion bin mit implementieren „Accumulate“

(define accumulate 
    (lambda (op base func ls) 
    (if(null? ls) 
     ls 
    (cond (not (null? (cdr ls)) (op base (map func ls) (accumulate op base func (cdr ls)))) 
     (op base (map func ls) (op base (func(car ls)))) 
    ) 
    ))) 
    ;It gets to a point (the last element) after applying the map function to each element, 
    ;where it is '(number) instead of an expected "number" (outside of()). I cannot figure out 
    ;how to circumvent this. 

Ich bin fest, wie dieses Recht zu bekommen. Was ist der richtige Weg?

Das gewünschte Ergebnis ist:

; accumulate: combines using OP the values of a list LS after mapping a function FUNC on it 
; (accumulate + 0 sqr '(1 2 3)) => 14 
; (accumulate * 1 sqr '(1 2 3)) => 36 
; 
+0

Ich denke, Ihre 'cond' Aussage ist nicht korrekt. '(cond ((nicht (null? (cdr ls))) (op base ...' – chepner

+0

Was genau soll es die Ausgabe von "akkumulieren" sein? Bitte geben Sie eine Beispieleingabe mit der erwarteten Ausgabe –

+0

Auch, warum tun Sie benötigen 'map'? Sind Sie sicher, dass Ihre Eingabe eine Liste von _lists_ ist? –

Antwort

1

Sie wollen einen Faltvorgang implementieren, die für eine Liste funktioniert, müssen Sie nicht map verwenden müssen, einfach jedes Element wiederum verarbeiten. Das ist mehr, wie es:

(define accumulate 
    (lambda (op base func ls) 
    (if (null? ls) 
     base 
     (op (func (car ls)) 
      (accumulate op base func (cdr ls)))))) 

Zum Beispiel:

(accumulate + 0 sqr '(1 2 3)) 
=> 14 

(accumulate * 1 sqr '(1 2 3)) 
=> 36 
+0

Vielen Dank für Ihren Rat. Eine Kopie der beabsichtigten Ausgabe als Referenz hinzugefügt. –

+0

@ChristopherKelly jetzt, das ist anders! sehen Sie? Sie brauchen nicht' Karte überhaupt! –

0

Sie können implementieren Ihre accumulate mit map, für Spaß und kein Gewinn:

(define accumulate 
    (lambda (op base func ls) 
    (let ((z (map list ls))) ; box'em 
     (car (reverse   ; last 
     (map (lambda (x y) 
       (let ((acc (op (car x) (func (car y))))) 
       (set-car! y acc) 
       acc)) 
      (reverse (cdr (reverse  ; bulast 
          (cons (list base) z)))) 
      z)))))) 

(display (accumulate + 0 (lambda(x)(* x x)) (list 1 2 3 4))) 

; 0 1 2 3 
; 1 2 3 4 => 30 

Emuliert (mit die offensichtliche Wendung), in r5rs-Schema, die Old-Time-Lazy-Stream-Programmierung Definition

accumulate op base ls = last z 
         where 
          z = base : zipWith op z ls -- (:) is cons 

~> accumulate (+) 0 (map (^2) [1..4]) 
30 

-- 0 a b c d + 
-- 1 4 9 16 = 
-- 0 a b c d 

, die auch das akkumulierte Ergebnis an einem überlagerten Listenknoten "schreibt", während es sich entlang der Listen bewegt. Dies ist tatsächlich bekannt als scanl in z.B. Haskell, und das letzte Ergebnis von dieser Liste nehmend, macht es foldl (die linke Falte).