Harita (üst düzey işlev) - Map (higher-order function)
Birçok olarak programlama dilleri , harita bir adıdır yüksek mertebeden fonksiyonu bir uygular verilen fonksiyon bir her elemana funktor örneğin bir, listede aynı sırada sonuçların listesini dönen,. İşlevsel formda düşünüldüğünde genellikle herkese uygulanır olarak adlandırılır .
Harita kavramı listelerle sınırlı değildir: sıralı kaplar , ağaç benzeri kaplar ve hatta vadeli işlemler ve vaatler gibi soyut kaplar için çalışır .
Örnekler: bir listeyi eşleme
Bir tamsayı listemiz olduğunu [1, 2, 3, 4, 5]
ve her tamsayının karesini hesaplamak istediğimizi varsayalım . Bunu yapmak için önce square
tek bir sayıya bir fonksiyon tanımlarız (burada Haskell 'de gösterilmiştir ):
square x = x * x
sonra arayabiliriz
>>> map square [1, 2, 3, 4, 5]
hangi verir [1, 4, 9, 16, 25]
, map
tüm listeden geçtiğini ve işlevi square
her öğeye uyguladığını gösterir.
Görsel örnek
Aşağıda, işleve göre X = [0, 5, 8, 3, 2, 1]
yeni bir listeye eşlemek istediğimiz tamsayıların bir listesi için eşleme sürecinin her adımının bir görünümünü görebilirsiniz :
X'
map
Haskell'ın taban başlangıcı (yani "standart kütüphanesi") bir parçası olarak sağlanır ve şekilde uygulanır:
map :: (a -> b) -> [a] -> [b]
map _ [] = []
map f (x : xs) = f x : map f xs
genelleme
Haskell'de polimorfik fonksiyonu map :: (a -> b) -> [a] -> [b]
a genelleştirilmiş polytypic fonksiyonu fmap :: Functor f => (a -> b) -> f a -> f b
ait herhangi bir türü için geçerli olan, tip sınıfı .
Functor
Bir tipte listelerinin []
bir örneği olarak tanımlanabilir Functor
kullanılarak tip sınıfı map
Önceki örnekten elde edilen işlevi:
instance Functor [] where
fmap = map
Örneklerin diğer örnekleri Functor
arasında ağaçlar bulunur:
-- a simple binary tree
data Tree a = Leaf a | Fork (Tree a) (Tree a)
instance Functor Tree where
fmap f (Leaf x) = Leaf (f x)
fmap f (Fork l r) = Fork (fmap f l) (fmap f r)
Bir ağaç üzerinde eşleme şu sonuçları verir:
>>> fmap square (Fork (Fork (Leaf 1) (Leaf 2)) (Fork (Leaf 3) (Leaf 4)))
Fork (Fork (Leaf 1) (Leaf 4)) (Fork (Leaf 9) (Leaf 16))
Functor
Type sınıfının her örneği için fmap
, sözleşmeye dayalı olarak functor yasalarına uymakla yükümlüdür :
fmap id ≡ id -- identity law
fmap (f . g) ≡ fmap f . fmap g -- composition law
burada Haskell'deki işlev bileşimini.
belirtir .
Diğer kullanımların yanı sıra, bu, çeşitli koleksiyon türleri için eleman bazında işlemlerin tanımlanmasına izin verir .
Ayrıca, eğer F ve G, iki funktorlar olan, bir doğal dönüşüm polimorfik tür bir fonksiyonudur açıdan fmap :
- herhangi bir işlev için .
Eğer h fonksiyonu ile tanımlanır parametrik polimorfizm yukarıdaki tip tanımı olarak, bu şartnamenin her zaman tatmin edilir.
Optimizasyonlar
Haritaların matematiksel temeli, bir dizi optimizasyona izin verir . Kompozisyon yasası, her ikisinin de
-
(map f . map g) list
ve map (f . g) list
aynı sonuca yol açar; yani, . Bununla birlikte, ikinci formun hesaplanması ilk forma göre daha verimlidir, çünkü her biri bir listenin tamamını sıfırdan yeniden oluşturmayı gerektirir. Bu nedenle, derleyiciler ilk formu ikinciye dönüştürmeye çalışacaklardır; bu tür optimizasyon, harita füzyonu olarak bilinir ve döngü füzyonunun işlevsel analoğudur .
map
Harita işlevleri, örneğin bir katlama cinsinden tanımlanabilir ve sıklıkla tanımlanır foldr
; bu, birinin bir harita katlama füzyonu yapılabileceği anlamına gelir : foldr f z . map g
eşdeğerdir foldr (f . g) z
.
Yukarıdaki haritanın tek başına bağlantılı listelerde uygulanması kuyruk özyinelemeli değildir , bu nedenle büyük bir listeyle çağrıldığında yığında çok sayıda çerçeve oluşturabilir. Birçok dil, dönüşümlü olarak, eşlenmiş bir listeyi tersine çevirmeye eşdeğer, ancak kuyruk özyinelemeli bir "ters eşleme" işlevi sağlar. İşte fold -left işlevini kullanan bir uygulama .
reverseMap f = foldl (\ys x -> f x : ys) []
Tekil bağlantılı bir listeyi tersine çevirmek de kuyruk özyinelemeli olduğundan, normal haritayı kuyruk özyinelemeli bir şekilde gerçekleştirmek için ters ve ters harita oluşturulabilir, ancak liste üzerinde iki geçiş yapılmasını gerektirir.
Dil karşılaştırması
Harita işlevi, işlevsel programlama dillerinde ortaya çıkmıştır .
Lisp dili maplist
, 1959'da adı verilen ve 1958'de zaten görünen biraz farklı sürümleri olan bir harita işlevi tanıttı . Bu, maplist
ardışık dinlenme listeleri üzerinde bir işlevi eşlemek için orijinal tanımdır :
maplist[x;f] = [null[x] -> NIL;T -> cons[f[x];maplist[cdr[x];f]]]
Bu işlev maplist
, Common Lisp gibi daha yeni Lisp'lerde hala mevcuttur , ancak benzeri mapcar
veya daha genel olan işlevler map
tercih edilir.
Bir listenin öğelerini kullanarak kare almak, S-ifadesi notasyonunda maplist
şu şekilde yazılır :
(maplist (lambda (l) (sqr (car l))) '(1 2 3 4 5))
Fonksiyonu kullanarak mapcar
, yukarıdaki örnek şu şekilde yazılır:
(mapcar (function sqr) '(1 2 3 4 5))
Günümüzde eşleme işlevleri birçok prosedürel , nesne yönelimli ve çok paradigmalı dilde de desteklenmektedir (veya tanımlanabilir) : C++ 'ın Standart Kitaplığında buna std::transform
, C# (3.0)'ın LINQ kitaplığında denir. adlı bir uzatma yöntemi olarak sağlanır Select
. Harita ayrıca ColdFusion Markup Language (CFML), Perl , Python ve Ruby gibi yüksek seviyeli dillerde sıklıkla kullanılan bir işlemdir ; işlem map
bu dillerin dördünde de çağrılır . Ruby'de ( Smalltalk'tan ) collect
için bir takma ad map
da sağlanır . Common Lisp , bir harita benzeri işlevler ailesi sağlar; burada açıklanan davranışa karşılık gelen çağrılır ( CAR işlemini kullanarak erişimi gösterir ). Harita işleviyle aynı işlevselliği sağlayan sözdizimsel yapılara sahip diller de vardır.
mapcar
-car
Harita bazen, kullanıcı tarafından sağlanan bir işlevi iki listeden karşılık gelen öğelere uygulayabilen ikili (2-argüman) işlevleri kabul edecek şekilde genelleştirilir. Bazı diller gibi bunun için özel adlar kullanın map2 veya zipWith . Açık değişken işlevleri kullanan diller , değişken işlevli işlevleri desteklemek için değişken eşlilikli harita sürümlerine sahip olabilir . 2 veya daha fazla liste içeren harita, listeler farklı uzunlukta olduğunda ele alma sorunuyla karşılaşır. Bu konuda çeşitli diller farklıdır. Bazıları bir istisna oluşturur. Bazıları en kısa listenin uzunluğundan sonra durur ve diğer listelerdeki fazlalıkları görmezden gelir. Bazıları en uzun listenin uzunluğuna kadar devam eder ve zaten sona eren listeler için, değer olmadığını belirten işleve bir yer tutucu değeri iletir.
Destekleyen diller birinci sınıf işlevleri ve tımar , map
olabilir , kısmen tatbik için asansör bir işlevi olduğunu öğeye eşdeğer tek bir değer çalışmaları bu bütün bir kap üzerinde çalışır; örneğin, map square
bir listenin her öğesinin karesini alan bir Haskell işlevidir.
Dilim | Harita | Harita 2 listesi | Harita n listeleri | Notlar | Farklı uzunluklardaki listeleri işleme |
---|---|---|---|---|---|
APL |
func list
|
list1 func list2
|
func/ list1 list2 list3 list4
|
APL'nin dizi işleme yetenekleri, harita gibi işlemleri örtük hale getirir | liste uzunlukları eşit değilse veya 1 değilse uzunluk hatası |
Ortak Lisp |
(mapcar func list)
|
(mapcar func list1 list2)
|
(mapcar func list1 list2 ...)
|
en kısa listenin uzunluğundan sonra durur | |
C++ |
std::transform(
|
std::transform(
|
başlık <algoritma> başlaması , sonu ve sonucu yineleyiciler olan sonuç yazılır başlayan sonucu |
||
C# |
ienum.Select(func) ya da maddesi select
|
ienum1.Zip(ienum2, func)
|
Select bir uzantı yöntemidir ienum bir IEnumerable'dır Zip .NET 4.0'da tanıtılmıştır Benzer şekilde tüm .NET dillerinde |
en kısa liste bittikten sonra durur | |
CFML |
obj.map(func)
|
obj Bir dizi veya yapı nerede . func argüman olarak her öğenin değerini, indeksini veya anahtarını ve orijinal nesneye bir referans alır.
|
|||
Clojure |
(map func list)
|
(map func list1 list2)
|
(map func list1 list2 ...)
|
en kısa liste bittikten sonra durur | |
NS |
list.map!func
|
zip(list1, list2).map!func
|
zip(list1, list2, ...).map!func
|
StoppingPolicy tarafından sıkıştırılacağı belirtildi: en kısa, en uzun veya gerekliSameLength | |
Erlang |
lists:map(Fun, List)
|
lists:zipwith(Fun, List1, List2)
|
zipwith3 Ayrıca mevcut
|
Listeler eşit uzunlukta olmalıdır | |
iksir |
Enum.map(list, fun)
|
Enum.zip(list1, list2) |> Enum.map(fun)
|
List.zip([list1, list2, ...]) |> Enum.map(fun)
|
en kısa liste bittikten sonra durur | |
F# |
List.map func list
|
List.map2 func list1 list2
|
Diğer türler için işlevler mevcuttur ( Seq ve Array ) | İstisna atar | |
harika |
list.collect(func)
|
[list1 list2]
|
[list1 list2 ...]
|
||
Haskell |
map func list
|
zipWith func list1 list2
|
zipWithn func list1 list2 ...
|
n liste sayısına karşılık gelir; önceden tanımlanmışzipWith7
|
en kısa liste bittikten sonra durur |
Haxe |
array.map(func)
|
||||
J |
func list
|
list1 func list2
|
func/ list1, list2, list3 ,: list4
|
J'nin dizi işleme yetenekleri, harita gibi işlemleri örtük hale getirir | liste uzunlukları eşit değilse uzunluk hatası |
Java 8+ |
stream.map(func)
|
||||
JavaScript 1.6 ECMAScript 5 |
array#map(func)
|
List1.map(function (elem1, i) {
|
List1.map(function (elem1, i) {
|
Array#map, func öğesine 3 bağımsız değişken iletir : öğe, öğenin dizini ve dizi. Kullanılmayan argümanlar atlanabilir. | Sonunda durur List1 ile kısa diziler uzanan, tanımsız gerekirse öğeler. |
Julia |
map(func, list)
|
map(func, list1, list2)
|
map(func, list1, list2, ..., listN)
|
HATA: Boyut Uyuşmazlığı | |
günlük konuşma |
map(Closure, List)
|
map(Closure, List1, List2)
|
map(Closure, List1, List2, List3, ...) (up to seven lists)
|
Yalnızca Kapanış bağımsız değişkeni somutlaştırılmalıdır. | Arıza |
matematik |
func /@ list
|
MapThread[func, {list1, list2}]
|
MapThread[func, {list1, list2, ...}]
|
Listeler aynı uzunlukta olmalıdır | |
maksimum |
map(f, expr1, ..., exprn)
|
map, önde gelen operatörün ifadelerinkiyle aynı olduğu bir ifade döndürür; maplist bir liste döndürür |
|||
OCaml |
List.map func list
|
List.map2 func list1 list2
|
Invalid_argument istisnasını yükseltir | ||
PARI/GP |
apply(func, list)
|
Yok | |||
Perl |
map block list
|
Gelen bloğun veya İfade özel değişken $ _ sırayla listeden her değerini tutar. | Helper List::MoreUtils::each_array , en uzun olan bitene kadar birden fazla listeyi birleştirir, diğerleriniundef.
|
||
PHP |
array_map(callable, array)
|
array_map(callable, array1,array2)
|
array_map(callable, array1,array2, ...)
|
Çağrılabilir parametre sayısı, dizi sayısıyla eşleşmelidir. |
NULL öğelerle daha kısa listeleri genişletir |
Prolog |
maplist(Cont, List1, List2).
|
maplist(Cont, List1, List2, List3).
|
maplist(Cont, List1, ...).
|
Liste argümanları girdi, çıktı veya her ikisidir. Ayrıca zipWith, unzip, all içerir | Sessiz arıza (hata değil) |
piton |
map(func, list)
|
map(func, list1, list2)
|
map(func, list1, list2, ...)
|
Python 2'de bir liste ve Python 3'te bir yineleyici döndürür. |
zip() ve map() (3.x) en kısa liste sona erdikten sonra durur, oysa map() (2.x) ve itertools.zip_longest() (3.x) daha kısa listeleri None öğelerle
genişletir |
yakut |
enum.collect {block}
|
enum1.zip(enum2)
|
enum1.zip(enum2, ...)
|
enum is an Enumeration
|
çağrıldığı nesnenin sonunda durur (ilk liste); başka bir liste daha kısaysa, sıfır öğelerle genişletilir |
Pas |
list1.into_iter().map(func)
|
list1.into_iter().zip(list2).map(func)
|
Iterator::map ve Iterator::zip yöntemler hem take orijinal yineleyici mülkiyeti ve yenisini return; Iterator::zip yöntem dahili olarak çağırır IntoIterator::into_iter yöntemi üzerindelist2
|
kısa liste bittikten sonra durur | |
S - Sağ |
lapply(list, func)
|
mapply(func, list1, list2)
|
mapply(func, list1, list2, ...)
|
Daha kısa listeler döngüye alınır | |
Skala |
list.map(func)
|
(list1, list2)
|
(list1, list2, list3)
|
not: 3'ten fazla mümkün değil. | kısa liste bittikten sonra durur |
Şema ( Guile ve Racket dahil ) |
(map func list)
|
(map func list1 list2)
|
(map func list1 list2 ...)
|
listelerin hepsinin aynı uzunlukta olması gerekir (SRFI-1, farklı uzunluktaki listeleri alacak şekilde genişler) | |
küçük konuşma |
aCollection collect: aBlock
|
aCollection1 with: aCollection2 collect: aBlock
|
başarısız | ||
standart makine öğrenimi |
map func list
|
ListPair.map func (list1, list2)
|
2-argüman haritası için func , argümanlarını bir demet içinde alır |
ListPair.map en kısa liste sona erdikten sonra durur ListPair.mapEq , UnequalLengths istisna oluşturur
|
|
Süratli |
sequence.map(func)
|
zip(sequence1, sequence2).map(func)
|
en kısa liste bittikten sonra durur | ||
XPath 3 XQuery 3 |
list ! block for-each(list, func)
|
for-each-pair(list1, list2, func)
|
Gelen block bağlam öğe . şimdiki değeri tutan
|
en kısa liste bittikten sonra durur |
Ayrıca bakınız
- Functor (fonksiyonel programlama)
- Konvolüsyon (bilgisayar bilimi) , conv veya zip olarak da adlandırılır
- Filtre (üst düzey işlev)
- Katlama (üst düzey işlev)
- her biri için
- serbest monoid
- Fonksiyonel programlama
- Üst düzey işlev
- Liste anlama
- Harita (paralel desen)