Lassen Sie sich sagt, dass ich zu einem anderen Array ein Array Karte will, die die Summe von jeweils drei benachbarten Elementen in dem Quell Array enthält:
var source = [1, 2, 3, 4, 6, 7, 8] // to [6, 17, 8]
Karten erstellen 1: 1-Beziehungen, so dass dieser wouldn‘ t geeignete Verwendung von map
. Stattdessen wäre eine reduce
oder ("fold") hier besser.
const comp = f=> g=> x=> f (g (x));
const len = xs=> xs.length;
const isEmpty = xs=> len(xs) === 0;
const concat = xs=> ys=> ys.concat(xs);
const chunk= n=> xs=>
isEmpty (xs)
? []
: concat (chunk (n) (xs.slice(n))) ([xs.slice(0,n)]);
const reduce = f=> y=> xs=> xs.reduce((y,x)=> f(y)(x), y);
const map = f=> xs=> xs.map(x=> f(x));
const add = x=> y=> y + x;
const sum = reduce (add) (0);
var source = [1, 2, 3, 4, 6, 7, 8];
comp (map (sum)) (chunk (3)) (source);
//=> [ 6, 17, 8 ]
So wie Sie sehen können, wir zuerst die source
in Stücke von 3 verwandeln, dann map
wir die sum
Funktion über jeden Brocken.
Wenn Sie Leute über "deklarativen" Code sprechen hören, ist die letzte Zeile ziemlich klar und macht sich wenig Gedanken über die Implementierung. Wir sagen dem Computer nicht, wie seine Arbeit zu machen. Es gibt keine for
/while
Schleifen, keine Fremdvariablen oder Iteratoren, keine Logik usw.
"idgaf how, brechen nur source
in Gruppen von 3, und dann jeden Teil sum"
// very declaration, wow
comp (map (sum)) (chunk (3)) (source);
Oder einen Eimer mit zwei Elementen machen:
var source = [1, 2, 3, 4, 5, 6, 7] // to [[1, 2], [3, 4], [5, 6], [7]]
Mit dem gleichen Code oben
var source = [1, 2, 3, 4, 5, 6, 7];
chunk (2) (source);
// => [ [ 1, 2 ], [ 3, 4 ], [ 5, 6 ], [ 7 ] ]
Für die zweite ich folgendes haben, aber das sieht nicht sehr funktional wie ich Array von Index Zugriff bin:
function* pairMap(data) {
yield* data.map((item, index) => {
if (index > 0) {
return [data[index - 1], item];
}
});
}
Mit dem obigen Code können Sie einfach pairMap
const pairMap = f=> comp (map (f)) (chunk (2));
var source = [1, 2, 3, 4, 5, 6, 7];
pairMap (pair => console.log(pair)) (source);
// [ 1, 2 ]
// [ 3, 4 ]
// [ 5, 6 ]
// [ 7 ]
implementieren
Lernen Sie alle Dinge
Die Frage ist "funktional für benutzerdefinierte Iteration". Sie werden bemerken, dass mein Code sorta mit Array.prototype.reduce
und Array.prototype.map
überbrückt. Lernen, wie man diese auf eigene Faust zu bauen, wurde für mich ein gutes Lerninstrument zu verstehen, dass es funktioniert Aufbau Funktionsschleifen/Iteratoren/Steuerung ist einfach und macht Spaß
const isEmpty = xs=> xs.length === 0
const head = xs=> xs[0];
const tail = xs=> xs.slice(1);
const reduce = f=> y=> xs=>
isEmpty (xs)
? y
: reduce (f) (f (y) (head (xs))) (tail (xs));
const add = x=> y=> y + x;
reduce (add) (0) ([1,2,3]);
//=> 6
!.
OK, lassen Sie uns sehen, wie wir Karte
const concat = xs=> ys=> ys.concat(xs);
const append = x=> concat ([x]);
const map = f=>
reduce (ys=> x=> append (f (x)) (ys)) ([]);
const sq = x => x * x;
map (sq) ([1,2,3])
//=> [ 1, 4, 9 ]
Quiz 1 tun würde: Sie filter
schreiben, some
und every
reduce
mit?
Troll Warnung: Es gibt viele verschiedene Möglichkeiten, diese Funktionen zu implementieren. Wenn Sie anfangen, rekursive Funktionen zu schreiben, sollten Sie zuerst wissen, was ein tail call ist. ES6 erhält eine Tail-Call-Optimierung, wird aber für eine Weile nicht mehr verbreitet sein. Für eine Weile konnte Babel es mit einer while-Schleife transpilieren, aber es ist in Version 6 vorübergehend deaktiviert und wird zurückkehren, sobald sie es behoben haben.
Quiz 2: Wie können Sie meine reduce
mit einem richtigen Tail Call umschreiben?
Es gibt eine Reihe von Möglichkeiten und das sind zwei sehr verschiedene Probleme. Was hast du probiert? –
Funktional bedeutet nicht nur 'map',' reduce' und 'filter'. Funktional bedeutet, dass es deklarativ ist und wo Funktionen erstklassige Bürger afaik sind. –
@ WillemVanOnsem, das ist meine Frage. Wie macht man das "deklarativ"? – norbertpy