Ich möchte ein funktionelles Äquivalent der Listen-Comprehensions schreiben, die nur Funktionen höherer Ordnung und ohne Nebenwirkungen verwenden. Ich tue dies ausschließlich zu Lernzwecken. Ich weiß, dass die Listenkomprehensionen Pythonic sind. In Python ist map(f, xs)
gleichbedeutend mit [f(x) for x in xs]
. Aber was sind die Entsprechungen darunter?
[f(x, y) for x in xs for y in ys]
[f(x, y) for x in range(1, 5) for y in range(x, 5)]
map
gibt nur Listen gleicher Länge zurück. reduce
ist allgemeiner, Sie können map
und filter
darauf implementieren.
Daher kann A wie folgt implementiert werden:
%Vor%Aber das verallgemeinert sich nicht auf & gt; 2 für Klauseln. Und B ist noch komplizierter, da die Iterationsvariable aus der 1. for-Klausel im 2. Satz verwendet wird. Wie schreibe ich eine Funktion (oder einen Satz von Funktionen), die Listenverständnisfunktionalität implementiert?
Dies ist das Muster einer Monade , speziell der Listen-Monade. In vielen Sprachen sind Monaden hinter irgendeiner Art von syntaktischem Zucker verborgen, wie C # 's LINQ , Scalas Notation oder, in noch mehr Sprachen, (Multi-) Listen-Comprehensions (wie hier in Python).
Der Schlüsselbegriff für die Übersetzung von jeder dieser zuckerhaltigen Syntax in gewöhnliche Funktionen ist (im speziellen Fall von Listen) eine Funktion vom Typ ([a], a -> [b]) -> [b]
, die der wesentliche Teil der Definition einer Monade ist. Diese Funktion ist unter verschiedenen Namen bekannt, z. (>>=)
oder "bind", flatMap
oder concatMap
oder selectMany
.
Für den Fall von Listen ist concatMap
oder flatMap
wahrscheinlich der beste Name, weil er das ist: eine Funktion, die Listen zurückgibt, einer Liste zuordnen und eine Liste von Listen geben; dann glätten Sie diese Liste.
Nun zu etwas konkreter 1 :
%Vor%Testen:
%Vor%Und mehr Spaß:
%Vor% Schließlich sollte beachtet werden, dass obwohl eine map
-ähnliche Funktion immer für eine Monade benötigt wird, im Allgemeinen reduce
nicht genug ist - was tatsächlich benötigt wird, ist eine verallgemeinerte "Abflachung" Operation join
, mit einem Typ wie m<m<a>>
(unter Verwendung der Template / Generics-Syntax), wobei m
der Typ ist der betreffenden Monade.
1 Wie in den Kommentaren erwähnt, kann dies auch als concatMap = lambda xs, f: chain.from_iterable(map(f, xs))
definiert werden, indem itertools
und die Identität (>>=) ≡ join . fmap
verwendet werden.
Sie können itertools.starmap
und itertools.product
für den Fall A :
Demo:
%Vor%Tags und Links python map list-comprehension functional-programming fold