C'è un nome per la funzione che restituisce un posizionalmente di espansione della versione della sua tesi?
-
12-11-2019 - |
Domanda
Considerare splatter
in questo codice Python:
def splatter(fn):
return lambda (args): fn(*args)
def add(a, b):
return a + b
list1 = [1, 2, 3]
list2 = [4, 5, 6]
print map(splatter(add), zip(list1, list2))
La mappatura di un n-ary funzione di n zippato sequenze sembra un comune abbastanza operazione che ci potrebbe essere un nome per questo già, ma non ho idea di dove mi piacerebbe trovare che.Vagamente evoca currying, e sembra che ci sono probabilmente altre tesi-centric HOFs che non ho mai sentito parlare.Qualcuno sa se questo è un "noto" funzione?Quando si parla di esso io sono bloccato con il tipo di imbarazzante lingua utilizzata nel titolo della domanda.
Modifica
Wow, Python map
lo fa automaticamente.Si può scrivere:
map(add, list1, list2)
E farà la cosa giusta, vi risparmio la fatica di splatter
ing funzione.L'unica differenza è che zip
restituisce un elenco la cui lunghezza è la lunghezza del più breve argomento, mentre map
si estende più brevi elenchi con None
.
Soluzione 2
Ho casualmente visto questo nella mia lista delle "Domande frequenti" e fu sorpreso che ora conosco la risposta.
Ci sono due interpretazioni della funzione che ho chiesto.
Il primo era il mio intento:per scattare una funzione che prende un numero fisso di argomenti e di convertirlo in una funzione che prende tali argomenti, come una dimensione fissa di lista o di una tupla.In Haskell, la funzione che esegue questa operazione si chiama uncurry
.
uncurry :: (a -> b -> c) -> ((a, b) -> c)
(Parentesi Extra per maggiore chiarezza).
È facile immaginare che si estende questo per funzioni di più di due argomenti, anche se non può essere espresso in Haskell.Ma uncurry3
, uncurry4
, etc.non sarebbe fuori luogo.
Così mi è stato giusto che "vagamente evoca currying", come in realtà è il contrario.
La seconda interpretazione è quello di prendere una funzione che prende un intenzionalmente numero variabile di argomenti e di ritorno di una funzione che accetta un unico elenco.
Perché splat
è così strano come una costruzione sintattica in Python, questo è difficile ragionare su.
Ma se pensiamo, diciamo, di JavaScript, che è una di prima classe denominata funzione di "splatting:"
varFn.apply(null, args)
var splatter = function(f) {
return function(arg) {
return f.apply(null, arg);
};
};
Quindi si potrebbe parafrasare che come una mera applicazione parziale della "apply
"la funzione:
var splatter = function(f) {
return Function.prototype.apply.bind(f, null);
};
O che utilizza, Underscore s partial
, siamo in grado di venire con la punto-free definizione:
var splatter = _.partial(Function.prototype.bind.bind(Function.prototype.apply), _, null)
Sì, è un incubo.
(L'alternativa per _.partial
richiede la definizione di una sorta di swap
helper e sarebbe uscito anche meno leggibile, credo.)
Quindi penso che il nome di questa operazione è solo "una parziale applicazione di apply
"o in Python caso, è quasi come un sezione di splat operatore -- se splat un "effettivo" dell'operatore.
Ma la particolare combinazione di uncurry
, zip
, e map
per la domanda originale è esattamente zipWith
, come chris ha sottolineato.Infatti, HLint per impostazione predefinita include una regola per sostituire questo complesso di costruire con una singola chiamata a zipWith
.
Spero che cancella le cose, il passato di Ian.
Altri suggerimenti
Penso zipWith
è la funzione ricerca (questo nome è usato almeno in Haskell).È anche un po ' più generale.In Haskell zipWith
è definito come segue (dove la prima riga è proprio il tipo):
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith f (a:as) (b:bs) = f a b : zipWith f as bs
zipWith _ _ _ = []
E il tuo esempio sarebbe qualcosa di simile
zipWith (+) [1, 2, 3] [4, 5, 6]
Dal momento che non conosco python molto bene, posso solo scegliere "zipWith analogico in Python?".