Anonim işlev - Anonymous function

İçinde bilgisayar Programlama, bir anonim işlev (işlev değişmezi, lambda soyutlamasıveya lambda ifadesi) bir işlevi olmayan tanım ciltli bir tanımlayıcı. Anonim işlevler genellikle iletilen argümanlardır üst düzey işlevler veya bir işlevi döndürmesi gereken daha yüksek düzeyli bir işlevin sonucunu oluşturmak için kullanılır.[1]İşlev yalnızca bir kez veya sınırlı sayıda kullanılırsa, adsız bir işlev, adlandırılmış bir işlevi kullanmaktan sözdizimsel olarak daha hafif olabilir. Anonim işlevler her yerde bulunur fonksiyonel programlama dilleri ve diğer diller birinci sınıf işlevler, aynı rolü için işlev türü gibi değişmezler başkası için yap veri tipleri.

Anonim işlevler, Alonzo Kilisesi icadında lambda hesabı 1936'da elektronik bilgisayarlardan önce tüm işlevlerin anonim olduğu.[2] Birkaç programlama dilinde, anonim işlevler anahtar sözcük kullanılarak tanıtılmıştır. lambdave anonim işlevler genellikle lambdas veya lambda soyutlamaları olarak adlandırılır. Anonim işlevler bir özelliği olmuştur Programlama dilleri dan beri Lisp 1958'de ve artan sayıda modern programlama dili anonim işlevleri destekliyor.

Kullanımlar

Anonim işlevler, adlandırılması gerekmeyen işlevselliği ve muhtemelen kısa süreli kullanım için kullanılabilir. Bazı önemli örnekler şunları içerir: kapanışlar ve köri.

Anonim işlevlerin kullanımı bir stil meselesidir. Bunları kullanmak asla bir sorunu çözmenin tek yolu değildir; her anonim işlev, adlandırılmış işlev olarak tanımlanabilir ve adla çağrılabilir. Bazı programcılar, belirli, yeniden kullanılamayan kodu, kodu çok sayıda küçük tek satırlık normal işlevle karıştırmadan kapsüllemek için anonim işlevler kullanır.

Bazı programlama dillerinde, anonim işlevler genellikle olayları geri aramalara bağlamak veya işlevi belirli değerler için örneklemek gibi çok özel amaçlar için uygulanır; işlevi.

Aşağıdaki örnekler Python 3'te yazılmıştır.

Sıralama

Standart olmayan bir şekilde sıralama girişiminde bulunulduğunda, adlandırılmış bir işlev oluşturmak yerine sıralama mantığını anonim bir işlev olarak içermek daha kolay olabilir. Çoğu dil bir genel sıralama işlevi sağlar. sıralama algoritması Bu işlev, genellikle iki öğenin eşit olup olmadığını veya birinin diğerinden daha büyük veya küçük olup olmadığını nasıl karşılaştıracağını belirleyen rastgele bir işlevi kabul eder.

Bir dizi listesini dizenin uzunluğuna göre sıralayan bu Python kodunu düşünün:

>>> a = ['ev', "araba", 'bisiklet']>>> a.çeşit(anahtar=lambda x: len(x))>>> Yazdır(a)["araba", 'bisiklet', 'ev']

Bu örnekteki anonim işlev, lambda ifadesidir:

lambda x: len(x)

Python'da bir lambda işlevinin temel sözdizimi

lambda arg1, arg2, arg3, ...: <operasyon açık  argümanlar geri dönen a değer>

Lambda işlevi tarafından döndürülen ifade bir değişkene atanabilir ve kodda birden çok yerde kullanılabilir.

>>> Ekle = lambda a: a + a>>> Yazdır(Ekle(20))40

Anonim işlev bir argümanı kabul eder, xve daha sonra tarafından kullanılan bağımsız değişkeninin uzunluğunu döndürür çeşit() Bir başka örnek, bir listedeki öğeleri sınıflarının adına göre sıralamak olabilir (Python'da her şeyin bir sınıfı vardır):

>>> a = [10, 'numara', 11.2]>>> a.çeşit(anahtar=lambda x: x.__sınıf__.__name__)>>> Yazdır(a)[11.2, 10, 'numara']

Bunu not et 11.2 sınıf adına sahip "yüzen", 10 sınıf adına sahip "int", ve 'numara' sınıf adına sahip "str". Sıralanan sıra"yüzen", "int", sonra "str".

Kapanışlar

Kapanışlar, aşağıdakileri içeren bir ortamda değerlendirilen fonksiyonlardır: bağlı değişkenler. Aşağıdaki örnek, girdiyi eşikle karşılaştıran anonim bir işlevde "eşik" değişkenini bağlar.

def comp(eşik):    dönüş lambda x: x < eşik

Bu, bir tür karşılaştırma işlevi üreteci olarak kullanılabilir:

>>> func_a = comp(10)>>> func_b = comp(20)>>> Yazdır(func_a(5), func_a(8), func_a(13), func_a(21))Doğru Doğru Yanlış Yanlış>>> Yazdır(func_b(5), func_b(8), func_b(13), func_b(21))Doğru Doğru Doğru Yanlış

Olası her karşılaştırma işlevi için bir işlev yaratmak pratik olmayacaktır ve eşiği daha sonra kullanmak üzere tutmak çok zahmetli olabilir. Bir kapatmanın kullanılmasının nedeni ne olursa olsun, anonim işlev, karşılaştırmayı yapan işlevselliği içeren varlıktır.

Köri

Currying, bir işlevi birden fazla girdi almak yerine, tek bir girdi alacak ve ikinci girdiyi kabul eden bir işlev döndürecek şekilde değiştirme işlemidir. Bu örnekte, gerçekleştiren bir işlev bölünme herhangi bir tamsayı, belirli bir tamsayı ile bölme yapan bir tamsayıya dönüştürülür.

>>> def bölmek(x, y):...     dönüş x / y>>> def bölen(d):...     dönüş lambda x: bölmek(x, d)>>> yarım = bölen(2)>>> üçüncü = bölen(3)>>> Yazdır(yarım(32), üçüncü(32))16.0 10.666666666666666>>> Yazdır(yarım(40), üçüncü(40))20.0 13.333333333333334

İsimsiz işlevlerin kullanımı belki körlemede yaygın olmasa da, yine de kullanılabilir. Yukarıdaki örnekte, işlev bölen, belirli bir bölen ile işlevler üretir. Yarım ve üçüncü işlevler bölme işlevini sabit bir bölen ile körükler.

Bölen işlevi ayrıca değişkeni bağlayarak bir kapanış oluşturur d.

Üst düzey işlevler

Bir üst düzey işlev argüman olarak bir işlevi alan bir işlevdir. Bu genellikle genel olarak tanımlanmış bir işlevin, genellikle döngü oluşturan bir yapı veya özyineleme şemasının davranışını özelleştirmek için kullanılır. Anonim işlevler, bu tür işlev bağımsız değişkenlerini belirtmenin uygun bir yoludur. Aşağıdaki örnekler Python 3'tedir.

Harita

Map işlevi, bir listenin her öğesi için bir işlev çağrısı gerçekleştirir. Aşağıdaki örnek kareler anonim bir işleve sahip bir dizideki her öğe.

>>> a = [1, 2, 3, 4, 5, 6]>>> Yazdır(liste(harita(lambda x: x*x, a)))[1, 4, 9, 16, 25, 36]

Anonim işlev bir argümanı kabul eder ve kendisiyle çarpar (karesini alır). Yukarıdaki form, aşağıda sunulan formun aynı anlama sahip olduğunu ve dil felsefesiyle daha uyumlu olduğunu iddia eden dilin yaratıcıları tarafından cesaretini kırmaktadır:

>>> a = [1, 2, 3, 4, 5, 6]>>> Yazdır([x*x için x içinde a])[1, 4, 9, 16, 25, 36]

Filtrele

Filtre işlevi, belirli bir işleve iletildiğinde True değerini veren bir listeden tüm öğeleri döndürür.

>>> a = [1, 2, 3, 4, 5, 6]>>> Yazdır(liste(filtre(lambda x: x % 2 == 0, a)))[2, 4, 6]

Anonim işlev, kendisine iletilen bağımsız değişkenin çift olup olmadığını kontrol eder. Aşağıdaki harita formu ile aynı şey daha uygun kabul edilir:

>>> a = [1, 2, 3, 4, 5, 6]>>> Yazdır([x için x içinde a Eğer x % 2 == 0])[2, 4, 6]

Kat

Katlama işlevi, bir yapıdaki tüm öğeler üzerinde çalışır (genellikle soldan sağa listeler için, bir "sol katlama" azaltmak Python'da), ilerledikçe bir değer biriktirir. Bu, bir yapının tüm öğelerini tek bir değerde birleştirmek için kullanılabilir, örneğin:

>>> itibaren functools ithalat azaltmak>>> a = [1, 2, 3, 4, 5]>>> Yazdır(azaltmak(lambda x,y: x*y, a))120

Bu gerçekleştirir

Buradaki anonim fonksiyon, iki argümanın çarpımıdır.

Bir katlamanın sonucunun tek bir değer olması gerekmez. Bunun yerine, katlama kullanılarak hem harita hem de filtre oluşturulabilir. Haritada, toplanan değer, orijinal listenin her bir öğesine bir işlev uygulama sonuçlarını içeren yeni bir listedir. Filtrede, biriken değer, yalnızca verilen koşulla eşleşen öğeleri içeren yeni bir listedir.

Dil listesi

Aşağıdakiler listesidir Programlama dilleri isimsiz anonim işlevleri tamamen veya kısmen bir çeşit olarak veya hiç desteklemeyen.

Bu tablo bazı genel eğilimleri göstermektedir. İlk olarak, anonim işlevleri desteklemeyen diller (C, Pascal, Nesne Pascal ) hepsi statik olarak yazılmış dillerdir. Ancak, statik olarak yazılmış diller anonim işlevleri destekleyebilir. Örneğin, ML diller statik olarak yazılmıştır ve temelde anonim işlevler içerir ve Delphi bir lehçe Nesne Pascal, anonim işlevleri desteklemek için genişletilmiştir. C ++ (tarafından C ++ 11 standart). İkincisi, işlev gören diller birinci sınıf işlevler (Dylan, Haskell, JavaScript, Lisp, ML, Perl, Python, Yakut, Şema ) genellikle anonim işlev desteğine sahiptir, böylece işlevler diğer veri türleri kadar kolayca tanımlanabilir ve aktarılabilir.

DilDestekNotlar
ActionScriptYeşil keneY
AdaKırmızı XNİfade işlevleri Ada2012'nin bir parçasıdır
ALGOL 68Yeşil keneY
APLYeşil keneYDyalog, ngn ve dzaima APL hem dfns hem de zımni işlevleri tam olarak destekler. GNU APL, dfns için oldukça sınırlı desteğe sahiptir.
Assembly dilleriKırmızı XN
BashYeşil keneYBash'de anonim işlevleri desteklemek için bir kitaplık oluşturuldu.[3]
CKırmızı XNDestek sağlanır Clang ve ile birlikte LLVM derleyici-rt lib. Kullanım imkanı sağlayan bir makro uygulama için GCC desteği verilmektedir. Daha fazla ayrıntı için aşağıya bakın.
C #Yeşil keneY[4]
C ++Yeşil keneYİtibariyle C ++ 11 standart
CFMLYeşil keneYİtibariyle Railo 4,[5] Soğuk füzyon 10[6]
ClojureYeşil keneY
COBOLKırmızı XNMikro Odak 'in standart olmayan Yönetilen COBOL diyalekti, anonim temsilciler / yöntemler olarak adlandırılan lambdaları destekler.[7]
KıvrılmaYeşil keneY
DYeşil keneY
Dart oyunuYeşil keneY[8]
DelphiYeşil keneY[9]
DylanYeşil keneY
EyfelYeşil keneY
KaraağaçYeşil keneY
İksirYeşil keneY[10]
ErlangYeşil keneY[11]
F #Yeşil keneY[12]
FaktörYeşil keneY"Alıntılar" bunu destekler[13]
FortranKırmızı XN
FrinkYeşil keneY[14]
GitYeşil keneY[15]
GosuYeşil keneY[16]
HarikaYeşil keneY[17]
HaskellYeşil keneY
HaxeYeşil keneY
JavaYeşil keneYDesteklenen Java 8. Bakın Java sınırlamaları ayrıntılar için aşağıdaki bölüm.
JavaScriptYeşil keneY
JuliaYeşil keneY[18]
KotlinYeşil keneY[19]
LispYeşil keneY
LogtalkYeşil keneY
LuaYeşil keneY[20]
KABAKULAKKırmızı XN
MathematicaYeşil keneY
AkçaağaçYeşil keneY[21]
MATLABYeşil keneY
MaximaYeşil keneY[22]
Yeni Nesil KabukYeşil keneY
NimYeşil keneY[23]
OCamlYeşil keneY[24]
OktavYeşil keneY[25]
Nesne PascalYeşil keneYObject Pascal'ın bir lehçesi olan Delphi, anonim işlevleri destekler (resmi olarak, anonim yöntemler) Delphi 2009'dan beri doğal olarak. Oksijen Nesne Pascal lehçesi de onları destekler.
Amaç-C (Mac OS X 10.6+)Yeşil keneYAranan bloklar; Objective-C'ye ek olarak bloklar, Apple platformunda programlama yaparken C ve C ++ üzerinde de kullanılabilir.
PascalKırmızı XN
PerlYeşil keneY[26]
PHPYeşil keneYPHP 5.3.0'dan itibaren, gerçek anonim işlevler desteklenmektedir.[27] Eskiden, yalnızca C # uygulamasına çok benzer şekilde çalışan kısmi anonim işlevler desteklenirdi.
PL / IKırmızı XN
PythonYeşil keneYPython, lambda sözdizimi aracılığıyla anonim işlevleri destekler,[28] sadece ifadeleri destekler, ifadeleri değil.
RYeşil keneY
RaketYeşil keneY[29]
RakuYeşil keneY
RexxKırmızı XN
RPGKırmızı XN
YakutYeşil keneYRuby'nin anonim işlevleri, Smalltalk, arandı bloklar.
Pas, paslanmaYeşil keneY
ScalaYeşil keneY
ŞemaYeşil keneY
SmalltalkYeşil keneYSmalltalk'ın anonim işlevleri çağrılır bloklar.
Standart MLYeşil keneY
SwiftYeşil keneYSwift'in anonim işlevlerine Kapanışlar denir.
TypeScriptYeşil keneY
TclYeşil keneY[30]
ValaYeşil keneY[30]
Visual Basic .NET v9Yeşil keneY
Görsel Prolog v 7.2Yeşil keneY
WLanguage v25Yeşil keneYWinDev / WebDev / WinDev Mobile paketi tarafından kullanılan PCSoft'un W-Dili, 25 (2019) sürümü itibariyle anonim işlevleri destekler
Wolfram DiliYeşil keneY

Örnekler

Çok sayıda dil anonim işlevleri veya benzer bir şeyi destekler.

APL

Yalnızca bazı lehçeler anonim işlevleri destekler. dfns, zımni tarzda veya her ikisinin birleşiminde.

      f{×} ⍝ dfn olarak      f 1 2 31 4 9           g⊢×⊢   ⍝ Zımni 3 tren (çatal) olarak      g 1 2 31 4 9      h×    ⍝ Türetilmiş bir zımni işlev olarak      h 1 2 31 4 9

C (standart olmayan uzantı)

Anonim işlev, standart C programlama dili tarafından desteklenmez, ancak bazı C lehçeleri tarafından desteklenir. GCC ve Clang.

GCC

GNU Derleyici Koleksiyonu (GCC), anonim işlevleri destekler. yuvalanmış işlevler ve ifade ifadeleri. Şu biçime sahiptir:

( { dönüş_türü anonim_fonksiyonlar_adı (parametreleri) { function_body } anonim_fonksiyonlar_adı; } )

Aşağıdaki örnek yalnızca GCC ile çalışır. Makroların nasıl genişletildiğinden dolayı, l_body parantez dışında virgül içeremez; GCC, virgülü makro bağımsız değişkenler arasında bir sınırlayıcı olarak ele alır. l_ret_type eğer çıkarılabilir __bir çeşit__ kullanılabilir; aşağıdaki örnekte __bir çeşit__ dizi, gerekirse gerçek değer için başvurulan test türü * döndürür.

#Dahil etmek <stdio.h>// * bu, anonim işlevin tanımıdır * /#define lambda (l_ret_type, l_arguments, l_body)   ({                                                      l_ret_type l_anonymous_functions_name l_arguments    l_body    & l_anonymous_functions_name;    })#define forEachInArray (fe_arrType, fe_arr, fe_fn_body) {                                                                                           int i = 0;   for (; i }typedef yapı __Ölçek{  int a;  int b;} test türü;geçersiz çıktı(sabit test türü * dizi){  int ben;  için ( ben = 0; ben < 3; ++ ben )    printf("% d% d", dizi[ben].a, dizi[ben].b);  printf("");}int ana(geçersiz){  test türü dizi[] = { {0,1}, {2,3}, {4,5} };  çıktı(dizi);  / * isimsiz fonksiyon foreach fonksiyonu olarak verilmiştir * /  forEachInArray(test türü, dizi,    lambda (test türü, (geçersiz *eşya),    {      int temp = (*( test türü *) eşya).a;      (*( test türü *) eşya).a = (*( test türü *) eşya).b;      (*( test türü *) eşya).b = temp;      dönüş (*( test türü *) eşya);    }));  çıktı(dizi);  dönüş 0;}

Clang (C, C ++, Amaç-C, Amaç-C ++)

Clang adı verilen anonim işlevleri destekler bloklar, şu forma sahip:

^dönüş_türü ( parametreleri ) { function_body }

Yukarıdaki blokların türü dönüş_türü (^) (parametreler).

Yukarıda belirtilenleri kullanma bloklar uzatma ve Grand Central Dispatch (libdispatch), kod daha basit görünebilir:

#Dahil etmek <stdio.h>#Dahil etmek <dispatch/dispatch.h>int ana(geçersiz) {  geçersiz (^döngü_sayısı)() = ^{    için (int ben = 0; ben < 100; ben++)      printf("% d", ben);    printf("ah ah ah");  };/ * Başka bir işleve parametre olarak aktar * /  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), döngü_sayısı);/ * Doğrudan çağırın * /  döngü_sayısı();  dönüş 0;}

Bloklu kod ile derlenmelidir -fblocks ve bağlantılı -lBlocksRuntime

C ++ (C ++ 11'den beri)

C ++ 11 adı verilen anonim işlevleri destekler lambda ifadeleri, şu forma sahip:

[ele geçirmek](parametreleri) -> dönüş_türü { function_body }

Bu örnek bir lambda ifadesidir:

[](int x, int y) -> int { dönüş x + y; }

C ++ 11 ayrıca kapanışlar. Kapanışlar köşeli parantezler arasında tanımlanır [ve ] lambda ifadesinin bildiriminde. Mekanizma, bu değişkenlerin değer veya referans ile yakalanmasına izin verir. Aşağıdaki tablo bunu göstermektedir:

[]        // tanımlanmış değişken yok. Lambda'daki herhangi bir harici değişkeni kullanmaya çalışmak bir hatadır.[x, &y]   // x değer tarafından yakalanır, y referans ile yakalanır[&]       // herhangi bir harici değişken, kullanılıyorsa referans tarafından dolaylı olarak yakalanır[=]       // herhangi bir harici değişken, kullanılırsa dolaylı olarak değer tarafından yakalanır[&, x]    // x, açıkça değer tarafından tutulur. Diğer değişkenler referansla yakalanacaktır[=, &z]   // z, açıkça referansla yakalanır. Diğer değişkenler değer tarafından yakalanacaktır

Değere göre yakalanan değişkenler varsayılan olarak sabittir. Ekleme değişebilir parametre listesinden sonra onları sabit olmayan yapar.

Aşağıdaki iki örnek, bir lambda ifadesinin kullanımını gösterir:

std::vektör<int> some_list{ 1, 2, 3, 4, 5 };int Toplam = 0;std::her biri için(başla(some_list), son(some_list),               [&Toplam](int x) {	Toplam += x; });

Bu, listedeki tüm öğelerin toplamını hesaplar. Değişken Toplam lambda işlevinin kapanmasının bir parçası olarak saklanır. Yığın değişkenine bir referans olduğu için Toplamdeğerini değiştirebilir.

std::vektör<int> some_list{ 1, 2, 3, 4, 5 };int Toplam = 0;int değer = 5;std::her biri için(başla(some_list), son(some_list),              [&Toplam, değer, bu](int x) { Toplam += x * değer * bu->some_func(); });

Bu neden olur Toplam referans olarak saklanacak, ancak değer bir kopya olarak saklanacaktır.

Yakalanması bu özeldir. Referansla değil, yalnızca değerle yakalanabilir. bu yalnızca en yakın çevreleyen işlev statik olmayan bir üye işlevse yakalanabilir. Lambda, korumalı / özel üyeler açısından onu oluşturan üye ile aynı erişime sahip olacaktır.

Eğer bu açık veya kapalı olarak yakalanırsa, ekteki sınıf üyelerinin kapsamı da test edilir. Üyelerine erişiliyor bu açık kullanımına gerek yok this-> sözdizimi.

Spesifik dahili uygulama değişebilir, ancak beklenti, her şeyi referansla yakalayan bir lambda fonksiyonunun, yığın değişkenlerine bireysel referanslar yerine, oluşturulduğu fonksiyonun gerçek yığın işaretçisini depolamasıdır. Ancak, çoğu lambda işlevi küçük ve kapsamı yerel olduğundan, büyük olasılıkla satır içi ve bu nedenle referanslar için ek depolamaya gerek yoktur.

Yerel değişkenlere referanslar içeren bir kapanış nesnesi, oluşturulmasının en içteki blok kapsamından sonra çağrılırsa, davranış Tanımsız.

Lambda işlevleri, uygulamaya bağlı türdeki işlev nesneleridir; bu türün adı yalnızca derleyici tarafından kullanılabilir. Kullanıcı bir lambda işlevini parametre olarak almak isterse, parametre türü bir şablon türü olmalı veya bir std :: function veya lambda değerini yakalamak için benzer bir nesne. Kullanımı Oto anahtar kelime lambda işlevinin depolanmasına yardımcı olabilir,

Oto my_lambda_func = [&](int x) { /*...*/ };Oto my_onheap_lambda_func = yeni Oto([=](int x) { /*...*/ });

Değişkenler, vektörler ve dizilerde anonim işlevlerin depolanmasına bir örnek burada; ve onları adlandırılmış parametreler olarak iletmek:

#Dahil etmek <functional>#Dahil etmek <iostream>#Dahil etmek <vector>çift değerlendirme(std::işlevi<çift(çift)> f, çift x = 2.0) {  dönüş f(x);}int ana() {  std::işlevi<çift(çift)> f0 = [](çift x) { dönüş 1; };  Oto f1 = [](çift x) { dönüş x; };  decltype(f0) fa[3] = {f0, f1, [](çift x) { dönüş x * x; }};  std::vektör<decltype(f0)> fv = {f0, f1};  fv.Geri itmek([](çift x) { dönüş x * x; });  için (size_t ben = 0; ben < fv.boyut(); ben++) {    std::cout << fv[ben](2.0) << std::son;  }  için (size_t ben = 0; ben < 3; ben++) {    std::cout << fa[ben](2.0) << std::son;  }  için (Oto& f : fv) {    std::cout << f(2.0) << std::son;  }  için (Oto& f : fa) {    std::cout << f(2.0) << std::son;  }  std::cout << değerlendirme(f0) << std::son;  std::cout << değerlendirme(f1) << std::son;  std::cout << değerlendirme([](çift x) { dönüş x * x; }) << std::son;}

Boş yakalama belirtimine sahip bir lambda ifadesi ([]), lambda ile bildirildiği gibi aynı türdeki bir işlev işaretçisine dolaylı olarak dönüştürülebilir. Yani bu yasal:

Oto a_lambda_func = [](int x) { /*...*/ };geçersiz (* func_ptr)(int) = a_lambda_func;func_ptr(4); // lambda'yı çağırır.

Boost kütüphane, aşağıdaki sözdizimini kullanarak lambda işlevleri için de kendi sözdizimini sağlar:[31]

her biri için(a.başla(), a.son(), std::cout << _1 << ' ');

C #

İçinde C # anonim işlevler için destek, dil derleyicisinin çeşitli sürümleriyle derinleşmiştir. Kasım 2007'de yayınlanan v3.0 dili .NET Framework v3.5, anonim işlevler için tam desteğe sahiptir. C # onları adlandırır lambda ifadeleri, anonim işlevlerin orijinal versiyonunu takiben, lambda hesabı.[32]

// ilk int, x 'türüdür// ikinci int, dönüş türüdür// http://msdn.microsoft.com/en-us/library/bb549151.aspx " />Func<int,int> foo = x => x * x;Konsol.Yazı çizgisi(foo(7));

İşlev anonim olsa da, dolaylı olarak yazılmış bir değişkene atanamaz çünkü lambda sözdizimi anonim bir işlevi veya bir ifade ağacını belirtmek için kullanılabilir ve seçim derleyici tarafından otomatik olarak kararlaştırılamaz. Örneğin, bu işe yaramaz:

// derlenmeyecek!var foo = (int x) => x * x;

Bununla birlikte, bir lambda ifadesi yer alabilir tür çıkarımı ve bir yöntem argümanı, Örneğin. Harita özelliği ile anonim işlevleri kullanmak için System.Collections.Generic.List (içinde Hepsini dönüştür() yöntem):

// Listeyi başlatın:var değerler = yeni Liste<int>() { 7, 13, 4, 9, 3 };// İsimsiz işlevi listedeki tüm elemanların üzerine eşleyin, yeni listeyi geri getirinvar foo = değerler.Hepsini dönüştür(d => d * d) ; // foo değişkeninin sonucu System.Collections.Generic.List  türündedir

Önceki C # sürümleri, anonim işlevler için daha sınırlı desteğe sahipti. Şubat 2002'de .NET Framework v1.0 ile tanıtılan C # v1.0, aşağıdakilerin kullanımı yoluyla kısmi anonim işlev desteği sağladı: delegeler. Bu yapı biraz PHP temsilcilerine benzer. C # 1.0'da, temsilciler, bir sınıf içinde açıkça adlandırılmış bir yönteme başvuran işlev işaretçileri gibidir. (Ancak PHP'den farklı olarak, temsilci kullanıldığında ad gerekli değildir.) Kasım 2005'te .NET Framework v2.0 ile yayınlanan C # v2.0, adsız bir satır içi ifade yazmak için anonim yöntemler kavramını tanıttı bir temsilci çağrısında çalıştırılabilen bloklar. C # 3.0, bu yapıları desteklemeye devam eder, ancak lambda ifade yapısını da destekler.

Bu örnek C # 3.0'da derlenecek ve şu üç formu gösterecek:

    halka açık sınıf Test Sürücü    {        temsilci int SquareDelegate(int d);        statik int Meydan(int d)        {            dönüş d * d;        }         statik geçersiz Ana(dizi[] argümanlar)        {            // C # 1.0: Orijinal temsilci sözdizimi gerekli             // adlandırılmış bir yöntemle başlatılıyor.            SquareDelegate Bir = yeni SquareDelegate(Meydan);            Sistem.Konsol.Yazı çizgisi(Bir(3));             // C # 2.0: Bir delege,            // satır içi kod, "anonim yöntem" olarak adlandırılır. Bu            // yöntem, girdi parametresi olarak bir int alır.            SquareDelegate B = temsilci(int d) { dönüş d * d; };            Sistem.Konsol.Yazı çizgisi(B(5));             // C # 3.0. Bir delege ile başlatılabilir            // bir lambda ifadesi. Lambda bir int alır ve bir int döndürür.             // x'in türü derleyici tarafından çıkarılır.            SquareDelegate C = x => x * x;            Sistem.Konsol.Yazı çizgisi(C(7));             // C # 3.0. Bir girişi kabul eden bir temsilci ve            // bir çıktı döndürür, ayrıca Func <> türü ile örtülü olarak da bildirilebilir.            Sistem.Func<int,int> D = x => x * x;            Sistem.Konsol.Yazı çizgisi(D(9));        }     }

C # 2.0 sürümü durumunda, C # derleyicisi anonim işlevin kod bloğunu alır ve statik bir özel işlev oluşturur. Dahili olarak, işlev elbette üretilen bir ad alır; oluşturulan bu ad, Delegenin bildirildiği yöntemin adına dayanır. Ancak ad, kullanılması dışında uygulama koduna açık değildir. yansıma.

C # 3.0 sürümü durumunda, aynı mekanizma geçerlidir.

ColdFusion İşaretleme Dili (CFML)

fn = işlevi(){  // ifadeler};

CFML, yalnızca ifadeleri değil, işlevin tanımı içindeki tüm ifadeleri destekler.

CFML yinelemeli anonim işlevleri destekler:

faktöryel = işlevi(n){    dönüş n > 1 ? n * faktöryel(n-1) : 1;};

CFML anonim işlevleri kapatma uygular.

D

D satır içi kullanır delegeler anonim işlevler uygulamak için. Satır içi bir delege için tam sözdizimi

dönüş_türü temsilci(argümanlar){/*vücut*/}

Belirsizse, dönüş türü ve anahtar kelime temsilci göz ardı edilebilir.

(x){dönüş x*x;}temsilci (x){dönüş x*x;} // daha fazla ayrıntı gerekiyorsa(int x){dönüş x*x;} // parametre türü çıkarılamazsatemsilci (int x){dönüş x*x;} // aynentemsilci çift(int x){dönüş x*x;} // dönüş türünün manuel olarak zorlanması gerekiyorsa

2.0 sürümünden beri, D Derleyici gereksiz olduğunu kanıtlayamadığı sürece öbek üzerinde kapanışları ayırır; dürbün anahtar sözcüğü yığın tahsisini zorlamak için kullanılabilir. 2.058 sürümünden beri, kısaltma notasyonu kullanmak mümkündür:

x => x*x;(int x) => x*x;(x,y) => x*y;(int x, int y) => x*y;

Anonim bir işlev bir değişkene atanabilir ve şu şekilde kullanılabilir:

Oto sqr = (çift x){dönüş x*x;};çift y = sqr(4);

Dart oyunu

Dart oyunu anonim işlevleri destekler.[8]

var sqr = (x) => x * x;Yazdır(sqr(5));

veya

Yazdır(((x) => x * x)(5));

Delphi

Delphi 2009 sürümünde anonim işlevler tanıtıldı.

program demo;tip  TSimpleProcedure = referans -e prosedür;  TSimpleFunction = referans -e işlevi(sabit x: dizi): Tamsayı;var  x1: TSimpleProcedure;  y1: TSimpleFunction;başla  x1 := prosedür    başla      Writeln('Selam Dünya');    son;  x1;   // az önce tanımlanan anonim yöntemi çağır  y1 := işlevi(sabit x: dizi): Tamsayı    başla      Sonuç := Uzunluk(x);    son;  Writeln(y1('bar')); son.

PascalABC.NET

PascalABC.NET lambda sözdizimini kullanan anonim işlevleri destekler

başla  var n := 10000000;  var pp := Aralık(1,n)    .Seçiniz(x->Rec(Rastgele(),Rastgele()))    .Nerede(p->sqr(p.Madde 1)+sqr(p.Öğe2)<1)    .Miktar/n*4;  Yazdır(pp);son.

İksir

İksir kullanır kapatma fn anonim işlevler için.[10]

toplam = fn(a, b) -> a + b sontoplam.(4, 3)#=> 7Meydan = fn(x) -> x * x sonSıralama.harita [1, 2, 3, 4], Meydan#=> [1, 4, 9, 16]

Erlang

Erlang isimsiz işlevler için adlandırılmış işlevlere benzer bir sözdizimi kullanır.[11]

Square değişkenine bağlı% Anonim işleviMeydan = eğlence(X) -> X * X son.% Aynı işlevselliğe sahip adlandırılmış işlevMeydan(X) -> X * X.

Git

Git anonim işlevleri destekler.[15]

foo := işlev(x int) int {	dönüş x * x}fmt.Println(foo(10))

Haskell

Haskell anonim işlevler (lambda ifadeleri) için kısa bir sözdizimi kullanır.

 x -> x * x

Lambda ifadeleri, tür çıkarım motoruyla tam olarak entegredir ve "sıradan" işlevlerin tüm sözdizimini ve özelliklerini destekler (bağımsız değişken listesi yalnızca bir kez belirtildiğinden, kalıp eşleştirme için birden çok tanımın kullanılması hariç).

 harita (x -> x * x) [1..5] - [1, 4, 9, 16, 25] değerini döndürür

Aşağıdakilerin tümü eşdeğerdir:

 f x y = x + y f x = y -> x + y f = x y -> x + y

Haxe

İçinde Haxe anonim işlevler lambda olarak adlandırılır ve sözdizimini kullanır işlev (bağımsız değişken listesi) ifadesi; .

var f = işlevi(x) dönüş x*x;f(8); // 64(işlevi(x,y) dönüş x+y)(5,6); // 11

Java

Java adlandırılmış anonim işlevleri destekler Lambda İfadeleriile başlayarak JDK 8.[33]

Bir lambda ifadesi, parantez içine alınmış biçimsel parametrelerin virgülle ayrılmış bir listesinden, bir ok belirtecinden (->) ve bir gövdeden oluşur. Yalnızca bir parametre varsa parantezler gibi, parametrelerin veri türleri de her zaman ihmal edilebilir. Gövde, bir ifade veya bir ifade bloğundan oluşabilir.[34]

// parametresiz() -> Sistem.dışarı.println("Selam Dünya.")// bir parametre ile (bu örnek bir kimlik işlevidir).a -> a// bir ifadeyle(a, b) -> a + b// açık tür bilgileriyle(uzun İD, Dize isim) -> "id:" + İD + ", ad:" + isim// bir kod bloğu ile(a, b) -> { dönüş a + b; }// lambda gövdesinde birden çok ifadeyle. Bir kod bloğuna ihtiyacı var.// Bu örnek ayrıca iki iç içe lambda ifadesi içerir (ilki aynı zamanda bir kapamadır).(İD, defaultPrice) -> {    İsteğe bağlı<Ürün> ürün = ürün listesi.Akış().filtre(p -> p.getId() == İD).findFirst();    dönüş ürün.harita(p -> p.getPrice()).orElse(defaultPrice);}

Lambda ifadeleri "işlevsel arayüzlere" dönüştürülür (bir veya daha fazla varsayılan veya statik yönteme ek olarak yalnızca bir soyut yöntem içeren arayüzler olarak tanımlanır),[34] aşağıdaki örnekte olduğu gibi:

halka açık sınıf Hesap makinesi {    arayüz IntegerMath {        int operasyon(int a, int b);        varsayılan IntegerMath takas() {            dönüş (a, b) -> operasyon(b, a);        }    }    özel statik int uygulamak(int a, int b, IntegerMath op) {        dönüş op.operasyon(a, b);    }    halka açık statik geçersiz ana(Dize... argümanlar) {        IntegerMath ilave = (a, b) -> a + b;        IntegerMath çıkarma = (a, b) -> a - b;        Sistem.dışarı.println("40 + 2 = " + uygulamak(40, 2, ilave));        Sistem.dışarı.println("20 - 10 = " + uygulamak(20, 10, çıkarma));        Sistem.dışarı.println("10 - 20 = " + uygulamak(20, 10, çıkarma.takas()));        }}

Bu örnekte, adı verilen işlevsel bir arayüz IntegerMath ilan edildi. Uygulayan Lambda ifadeleri IntegerMath geçilir uygulamak() uygulanacak yöntem. Gibi varsayılan yöntemler takas Fonksiyonlarla ilgili yöntemleri tanımlar.

Java 8, mevcut bir yöntemde bir lambda oluşturmak için yöntem başvurusu (:: operatörü) adlı başka bir mekanizma tanıttı. Bir yöntem başvurusu, bağımsız değişkenlerin sayısını veya türlerini göstermez çünkü bunlar, işlevsel arabirimin soyut yönteminden çıkarılır.

IntBinary Operatör toplam = Tamsayı::toplam;

Yukarıdaki örnekte, işlevsel arayüz IntBinary Operatör soyut bir yöntem bildirir int applyAsInt (int, int), bu nedenle derleyici bir yöntem arar int sum (int, int) sınıfta java.lang.Integer.

Java sınırlamaları

Java 8 lambdalar aşağıdaki sınırlamalara sahiptir:

  • Lambdalar işaretli istisnalar atabilir ancak bu tür lambdalar Koleksiyon API'si tarafından kullanılan arayüzlerle çalışmaz.
  • Lambda'nın bildirildiği kapsam dahilinde olan değişkenlere, yalnızca etkin bir şekilde nihai olduklarında, yani değişken lambda kapsamının içinde veya dışında mutasyona uğramadıklarında, lambda içinde erişilebilir.

JavaScript

JavaScript /ECMAScript anonim işlevleri destekler.

uyarmak((işlevi(x){  dönüş x * x;})(10));

ES6 "ok işlevi" sözdizimini destekler, burada a => simgesi, anonim işlevin parametre listesini gövdeden ayırır:

uyarmak((x => x * x)(10));

Bu yapı genellikle Yer imleri. Örneğin, mevcut belgenin başlığını değiştirmek için (penceresinin başlık çubuğu ) onun için URL, aşağıdaki yer imi çalışıyor gibi görünebilir.

javascript:belge.Başlık=yer.href;

Bununla birlikte, atama ifadesi bir değer (URL'nin kendisi) döndürdüğünden, birçok tarayıcı aslında bu değeri görüntülemek için yeni bir sayfa oluşturur.

Bunun yerine, bir değer döndürmeyen anonim bir işlev kullanılabilir:

javascript:(işlevi(){belge.Başlık=yer.href;})();

İlk (dış) parantez çiftindeki işlev ifadesi, anonim bir işlevi bildirir ve bu daha sonra son parantez çiftiyle kullanıldığında çalıştırılır. Bu, ortamı aşağıdakilerle dolduran aşağıdakine neredeyse eşdeğerdir: f anonim bir işlevin aksine.

javascript:var f = işlevi(){belge.Başlık=yer.href;}; f();

Kullanım geçersiz() rastgele anonim işlevler için yeni sayfalardan kaçınmak için:

javascript:geçersiz(işlevi(){dönüş belge.Başlık=yer.href;}());

ya da sadece:

javascript:geçersiz(belge.Başlık=yer.href);

JavaScript, anonim işlevleri tanımlama, çağırma ve değerlendirme anlambilimine yönelik sözdizimsel inceliklere sahiptir. Bu bilinçaltı nüanslar, parantez içindeki ifadelerin değerlendirilmesinin doğrudan bir sonucudur. Aşağıdaki yapılar denilen hemen çağrılan işlev ifadesi bunu örnekle:

(işlevi(){ ... }())

ve

(işlevi(){ ... })()

Temsil etmek "işlev () {...}" tarafından fyapıların biçimi bir parantez içinde parantez içinde (f ()) ve bir parantez içine uygulanan bir parantez (f) ().

Bir parantez ifadesinin genel sözdizimsel belirsizliğine, bir fonksiyon için parantezli argümanlara ve bir fonksiyon tanımındaki biçimsel parametrelerin etrafındaki parantezlere dikkat edin. Özellikle JavaScript, bir , Parantez içindeki bir ifade bağlamında (virgül) operatörü. Sözdizimsel biçimlerin bir ifade ve bir işlevin argümanları için çakışması (işlev biçimsel parametre sözdizimini göz ardı ederek) yalnızca tesadüf değildir! Eğer f yukarıdaki yapılarda tanımlanmadığında, (()) ve ()(). İlki herhangi bir yerleşik işlevin sözdizimsel ipucunu sağlamaz, ancak ikincisi ilk parantezi yasal JavaScript olarak bir işlev olarak DEĞERLENDİRMELİDİR. (Kenara: örneğin, ()İfade bir işlev olarak değerlendirildiği sürece 'ler ([], {}, 42, "abc", işlev () {}) olabilir.)

Ayrıca, bir işlev bir Object örneğidir (aynı şekilde nesneler Function örnekleridir) ve nesne değişmez gösterim ayraçları, {} Ayraçlı kod için, bir işlevi bu şekilde tanımlarken kullanılır (kullanmanın aksine yeni İşlev (...)). Çok geniş ve titiz olmayan bir anlamda (özellikle genel bağlamalardan ödün verildiğinden), rastgele bir çaprazlı JavaScript ifadeleri dizisi, {şey}, bir sabit nokta nın-nin

(işlevi(){( işlevi(){( ... {( işlevi(){şey}() )} ... )}() )}() )

Daha doğrusu ama uyarılarla,

( işlevi(){şey}() ) ~=   A_Fixed_Point_of(      işlevi(){ dönüş işlevi(){ dönüş ... { dönüş işlevi(){şey}() } ... }() }()   )

Aşağıdaki JavaScript parçalarında anonim işlevin etkilerine dikkat edin:

  • işlev () {...} () çevrelemeden ()'s genellikle yasal değildir
  • (f = işlev () {...}) "unutmaz" f küresel olarak farklı (fonksiyon f () {...})
Verim ölçümler analiz etmek Uzay ve zaman karmaşıklıklar JavaScript'teki işlev çağrıları, çağrı yığını vb. çevirmen motor bu son anonim işlev yapıları ile kolayca uygulayın. Sonuçların çıkarımlarından, bir motorun yinelemeli ve yinelemeli uygulama ayrıntılarından bazılarını, özellikle de kuyruk özyineleme.

Julia

İçinde Julia anonim işlevler sözdizimi kullanılarak tanımlanır (bağımsız değişkenler) -> (ifade),

Julia> f = x -> x*x; f(8)64Julia> ((x,y)->x+y)(5,6)11

Lisp

Lisp ve Şema bir referans olan "lambda" yapısını kullanarak anonim işlevleri destekler lambda hesabı. Clojure "fn" özel formu ve # () okuyucu sözdizimi ile anonim işlevleri destekler.

(lambda (arg) (* arg arg))

Ortak Lisp

Ortak Lisp lambda ifadeleri kavramına sahiptir. Bir lambda ifadesi, ilk elemanı olarak "lambda" sembolü ile bir liste olarak yazılır. Liste daha sonra bağımsız değişken listesini, dokümantasyonu veya bildirimleri ve bir işlev gövdesini içerir. Lambda ifadeleri, lambda formlarının içinde ve özel operatör "function" ile kullanılabilir.

(işlevi (lambda (arg) (bir şey yap arg)))

"işlev", # 'olarak kısaltılabilir. Ayrıca makro lambda bir işlev formuna genişleyen var:

; keskin alıntı kullanarak#'(lambda (arg) (bir şey yap arg)); lambda makrosunu kullanarak:(lambda (arg) (bir şey yap arg))

Common Lisp'teki anonim işlevlerin tipik bir kullanımı, bunları daha yüksek düzey işlevlere iletmektir. Mapcar, bir listenin her öğesine bir işlev uygulayan ve sonuçların bir listesini döndüren.

(Mapcar #'(lambda (x) (* x x))        '(1 2 3 4)); -> (1 4 9 16)

lambda formu Common Lisp'te bir lambda ifadesi bir işlev çağrısında yazılacak:

((lambda (x y)   (+ (sqrt x) (sqrt y))) 10.0 12.0)

Common Lisp'teki anonim işlevlere daha sonra küresel adlar da verilebilir:

(setf (sembol işlevi 'sqr)      (lambda (x) (* x x))); SQR adını kullanarak aramamıza izin verir:(sqr 10.0)

Şema

Şema adlandırılmış işlevler basitçe Sözdizimsel şeker isimlere bağlı anonim işlevler için:

(tanımlamak (aynı arg)  (bir şey yap arg))

genişler (ve eşdeğerdir)

(tanımlamak aynı  (lambda (arg)    (bir şey yap arg)))

Clojure

Clojure "fn" özel biçimi aracılığıyla anonim işlevleri destekler:

(fn [x] (+ x 3))

Bir lambda tanımlamak için bir okuyucu sözdizimi de vardır:

# (+ % %2%3) ; Üç bağımsız değişken alan ve bunları toplayan anonim bir işlevi tanımlar.

Scheme gibi, Clojure'un "adlandırılmış işlevleri" adlara bağlı lambdalar için basitçe sözdizimsel şekerdir:

(tanım işlev [arg] (+ 3 arg))

şuna genişler:

(def işlev (fn [arg] (+ 3 arg)))

Lua

İçinde Lua (Scheme'de olduğu gibi) tüm işlevler anonimdir. Bir adlandırılmış işlev Lua'da bir fonksiyon nesnesine referans tutan bir değişkendir.[35]

Böylece, Lua'da

işlevi foo(x) dönüş 2*x son

sadece sözdizimi şekeri

foo = işlevi(x) dönüş 2*x son

Ters sıralı sıralama için anonim işlevlerin kullanımına bir örnek:

table.sort(, işlevi(a,b)  dönüş a.isim > b.isimson)

Wolfram Dili, Mathematica

Wolfram Dili programlama dilidir Mathematica. Anonim işlevler, ikincisinin programlanmasında önemlidir. Bunları yaratmanın birkaç yolu var. Aşağıda, bir sayıyı artıran birkaç anonim işlev bulunmaktadır. İlki en yaygın olanıdır. #1 ilk argümanı ifade eder ve & anonim işlevin sonunu gösterir.

#1+1&Fonksiyon[x,x+1]x[Fonksiyon]x+1

Yani, örneğin:

f:=#1^2&;f[8]64#1+#2&[5,6]11

Ayrıca Mathematica, yinelemeli anonim işlevler yapmak için ek bir yapıya sahiptir. '# 0' sembolü tüm işlevi ifade eder. Aşağıdaki işlev, girdisinin faktöriyelini hesaplar:

Eğer[#1==1,1,#1*#0[#1-1]]&

Örneğin, 6 faktöriyel şöyle olacaktır:

Eğer[#1==1,1,#1*#0[#1-1]]&[6]720

MATLAB, Oktav

Anonim işlevler MATLAB veya Oktav sözdizimi kullanılarak tanımlanır @ (bağımsız değişken listesi) ifade. Bağımsız değişken listesinde bulunmayan tüm değişkenler, kapsama alanından miras alınır.

 > f = @(x)x*x; f(8) ans =  64 > (@(x,y)x+y)(5,6) % Sadece Octave ile çalışır ans =  11

Maxima

İçinde Maxima anonim işlevler sözdizimi kullanılarak tanımlanır lambda (bağımsız değişken listesi, ifade),

 f: lambda ([x], x * x); f (8); 64 lambda ([x, y], x + y) (5,6); 11

ML

Çeşitli lehçeleri ML anonim işlevleri destekler.

OCaml

OCaml işlevlerinin adları olması gerekmez; isimsiz olabilirler. Örneğin, burada girdisini artıran anonim bir işlev var: fun x -> x + 1. Burada eğlence, anonim bir işlevi belirten bir anahtar kelimedir, x argümandır ve -> argümanı gövdeden ayırır.

Arttırma fonksiyonu yazmanın artık iki yolu var:

İzin Vermek inc x = x + 1İzin Vermek inc = eğlence x -> x+1

Sözdizimsel olarak farklıdırlar ancak anlamsal olarak eşdeğerdirler. Yani, farklı anahtar kelimeler içermelerine ve bazı tanımlayıcıları farklı yerlere koymalarına rağmen, aynı anlama gelirler.

Anonim işlevler, aynı zamanda Turing makinelerinin bir hesaplama modeli olduğu gibi matematiksel bir hesaplama modeli olan lambda hesabından çıkan bir terim olan lambda ifadeleri olarak da adlandırılır. Lambda hesabında, eğlenceli x -> e λx.e yazılır. Λ, anonim bir işlevi belirtir.

Sözdizimi.

eğlence x1 ... xn -> e

Statik anlambilim.

X1: t1 ve x2: t2 ve ... ve xn: tn olduğunu varsayarsak, e: u, sonra eğlenceli x1 ... xn -> e: t1 -> t2 -> ... -> tn -> u.Dinamik anlambilim.

Anonim bir işlev zaten bir değerdir. Gerçekleştirilecek bir hesaplama yok.

eğlence arg -> arg * arg

CS3110'dan Snippet, Cornell, öğreten Michael R. Clarkson, Robert L. Constable, Nate Foster, Michael D. George, Dan Grossman, Daniel P. Huttenlocher, Dexter Kozen, Greg Morrisett, Andrew C. Myers, Radu Rugina ve Ramin Zabih. [36]

F #

F # anonim işlevleri destekler,[12] aşağıdaki gibi:

(eğlence x -> x * x) 20 // 400

Standart ML

Standart ML aşağıdaki gibi anonim işlevleri destekler:

fn arg => arg * arg

Yeni Nesil Kabuk

Yeni Nesil Kabuk dildeki yaygınlıkları ve farklı kullanım durumları nedeniyle anonim işlevler için birkaç sözdizimi vardır.

Sözdizimleri:

f = X*X; f(8)                       # Sonuç: 64f = { Bir*B+C }; f(2,3,4)             # Sonuç: 10f = F(x:Int, y:Int) x*y+2; f(3, 4)  # Sonuç: 14f = "$ {X}, yaklaşık {Y} $"f("programlama", "anlambilim")       # Sonuç: "programlama tamamen anlambilimle ilgilidir"

Anonim işlevler kullanım örnekleri:

[0,1,2].harita(X*2)                    # Sonuç: [0,2,4]veri = {"a": "xxx", "b": "yyy"}veri.harita("$ {X} $ {Y}")            # Sonuç: ["a xxx", "b yyy"]

Nim

Nim çok satırlı çok ifadeli anonim işlevleri destekler. [37]

var anon = proc (var1, var2: int): int = var1 + var2iddia etmek anon(1, 2) == 3

Çok satırlı örnek:

var anon = işlev (x: int): bool =             Eğer x > 0:               sonuç = doğru             Başka:                sonuç = yanlışiddia etmek anon(9)

Anonim işlevler, diğer işlevlerin girdi parametreleri olarak aktarılabilir:

var şehirler = @["Frankfurt", "Tokyo", "New York"]şehirler.çeşit(  proc (x, y: dizi): int = cmp(x.len, y.len))

Anonim bir işlev, temelde adı olmayan bir işlevdir.

Perl

Perl 5

Perl 5 anonim işlevleri destekler,[26] aşağıdaki gibi:

(alt { Yazdır "Arandım" })->();         # 1. Oluşturulmuş olarak adlandırılan tamamen anonimbenim $ kare = alt { benim $ x = vardiya; $ x * $ x }; # 2. Bir değişkene atanmışalt köri {    benim ($ alt, @args) = @_;    dönüş alt { $ alt->(@args, @_) };         # 3. Başka bir işlevin dönüş değeri olarak}# Perl programlamada körleme örneğialt toplam { benim $ tot = 0; $ tot += $_ için @_; $ tot } #, bağımsız değişkenlerinin toplamını döndürürbenim $ curried = köri &toplam, 5, 7, 9;Yazdır $ curried->(1,2,3), "";    # 27 (= 5 + 7 + 9 + 1 + 2 + 3) yazdırır

Diğer yapılar alır çıplak bloklar Bir parametrenin lambda işlevlerine benzer bir işleve hizmet eden, ancak işlevlerle aynı parametre geçirme kuralına sahip olmayan argümanlar olarak - @_ ayarlanmamıştır.

benim @squares = harita { $_ * $_ } 1..10;   # map ve grep "alt" anahtar kelimesini kullanmazbenim @ kare2 = harita $_ * $_, 1..10;      # bir ifade için gereksiz küme ayracıbenim @Kötü örnek = harita { Yazdır için @_ } 1..10; # değer normal Perl işlevi gibi aktarılmaz

PHP

4.0.1'den önce, PHP anonim işlev desteği yoktu.[38]

PHP 4.0.1 - 5.3

PHP 4.0.1, create_function başlangıçtaki anonim işlev desteğiydi. Bu işlev çağrısı, rastgele adlandırılmış yeni bir işlev oluşturur ve adını (bir dizge olarak) döndürür.

$ foo = create_function('$ x', '$ x * $ x; döndür');$ bar = create_function("$x ", "dönüş $x *$x; ");Eko $ foo(10);

Bağımsız değişken listesi ve işlev gövdesi tek tırnak içinde olmalıdır veya dolar işaretlerinden kaçınılmalıdır. Aksi takdirde, PHP "$ x"değişken anlamına gelir $ x ve onu dizeden ayrılmak yerine (muhtemelen mevcut olmamasına rağmen) değiştirecektir "$ xTırnak işaretli işlevler veya çok değişkenli işlevler için, PHP'nin yorumladığı işlevin amaçlanan işlev gövdesi olduğundan emin olmak oldukça sıkıcı olabilir.

Her çağrı create_function programın geri kalanı için var olan yeni bir işlev yapar ve olamaz toplanan çöp, programdaki belleği geri alınamaz şekilde kullanmak. Bu, birçok kez anonim işlevler oluşturmak için kullanılırsa, örneğin bir döngüde, bellek şişmesi gibi sorunlara neden olabilir.

PHP 5.3

PHP 5.3 adında yeni bir sınıf ekledi Kapanış ve sihirli yöntem __çağırmak() bu, bir sınıf örneğini çağırılabilir yapar.[39]

$ x = 3;$ func = işlevi($ z) { dönüş $ z *= 2; };Eko $ func($ x); // 6 yazdırır

Bu örnekte, $ func bir örneği Kapanış ve echo $ func ($ x) eşdeğerdir echo $ func -> __ çağır ($ x).PHP 5.3 anonim işlevleri taklit eder ancak gerçek anonim işlevleri desteklemez çünkü PHP işlevleri hala birinci sınıf nesneler değildir.

PHP 5.3, kapatmaları destekler, ancak değişkenler şu şekilde açıkça belirtilmelidir:

$ x = 3;$ func = işlevi() kullanım(&$ x) { $ x *= 2; };$ func();Eko $ x; // 6 yazdırır

Değişken $ x referansla bağlıdır, bu nedenle çağrısı $ func değiştirir ve değişiklikler işlevin dışında görünür.

Prolog'un lehçeleri

Logtalk

Logtalk anonim tahminler için aşağıdaki sözdizimini kullanır (lambda ifadeleri):

{FreeVar1, FreeVar2, ...}/[LambdaParameter1, LambdaParameter2, ...]>>Hedef

Serbest değişken içermeyen ve bir liste eşleme koşulu kullanan basit bir örnek:

| ?- meta::harita([X,Y]>>(Y dır-dir 2*X), [1,2,3], Ys).Ys = [2,4,6]Evet

Currying de desteklenmektedir. Yukarıdaki örnek şu şekilde yazılabilir:

| ?- meta::harita([X]>>([Y]>>(Y dır-dir 2*X)), [1,2,3], Ys).Ys = [2,4,6]Evet

Görsel Prolog

Anonim işlevler (genel olarak anonim yüklemler) tanıtıldı Görsel Prolog 7.2 sürümünde.[40] Anonim tahminler, bağlamdaki değerleri yakalayabilir. Bir nesne üyesinde oluşturulmuşsa, nesne durumuna da erişebilir (yakalayarak Bu).

mkAdder argümanı yakalayan anonim bir işlevi döndürür X kapanışta. Döndürülen işlev ekleyen bir işlevdir X argümanına göre:

maddeleri    mkAdder(X) = { (Y) = X+Y }.

Python

Python lambda formu aracılığıyla basit anonim işlevleri destekler.[28] Lambda'nın çalıştırılabilir gövdesi bir ifade olmalıdır ve bir ifade olamaz, bu da onun kullanımını sınırlayan bir kısıtlamadır. Lambda tarafından döndürülen değer, içerilen ifadenin değeridir. Lambda formları, sıradan işlevlerin yapabildiği her yerde kullanılabilir. Ancak bu kısıtlamalar, onu normal bir işlevin çok sınırlı bir versiyonu haline getirir. İşte bir örnek:

>>> foo = lambda x: x * x>>> Yazdır(foo(10))100

Genel olarak, Python kuralı, diğer dillerde tipik olarak anonim işlevler kullanılabileceğinden, aynı kapsamda tanımlanan adlandırılmış işlevlerin kullanımını teşvik eder. Bu, yerel olarak tanımlanmış işlevlerin tüm gücünü uyguladığı için kabul edilebilir. kapanışlar ve neredeyse Python'da bir lambda kullanımı kadar etkilidir. In this example, the built-in power function can be said to have been körili:

>>> def make_pow(n):...     def fixed_exponent_pow(x):...         dönüş pow(x, n)...     dönüş fixed_exponent_pow...>>> sqr = make_pow(2)>>> Yazdır (sqr(10))100>>> yavru = make_pow(3)>>> Yazdır (yavru(10))1000

R

In R the anonymous functions are defined using the syntax function(argument-list)expression .

> f <- işlevi(x)x*x; f(8)[1] 64> (işlevi(x,y)x+y)(5,6)[1] 11

Raku

İçinde Raku, all blocks (even those associated with if, while, etc.) are anonymous functions. A block that is not used as an rvalue is executed immediately.

  1. fully anonymous, called as created
    { söyle "I got called" };
  2. assigned to a variable
    benim $squarer1 = -> $ x { $ x * $ x };             # 2a. pointy blockbenim $squarer2 = { $^x * $^x };                 # 2b. twigilbenim $squarer3 = { benim $ x = vardiya @_; $ x * $ x }; # 2c. Perl 5 style
  3. köri
    alt Ekle ($ m, $n) { $ m + $n }benim $seven   = Ekle(3, 4);benim $add_one = &add.varsaymak(m => 1);my $eight   = $add_one($seven);
  4. WhateverCode object
    benim $w = * - 1;       # WhateverCode objectbenim $b = { $_ - 1 };  # same functionality, but as Callable block

Yakut

Ruby supports anonymous functions by using a syntactical structure called blok. There are two data types for blocks in Ruby. Procs behave similarly to kapanışlar, buna karşılık lambdas behave more analogous to an anonymous function.[41] When passed to a method, a block is converted into a Proc in some circumstances.

irb(main):001:0># Example 1:irb(main):002:0* # Purely anonymous functions using blocks.irb(main):003:0* eski = [16.2, 24.1, 48.3, 32.4, 8.5]=> [16.2, 24.1, 48.3, 32.4, 8.5]irb(main):004:0>eski.göre sırala { |x| x - x.to_i } # Sort by fractional part, ignoring integer part.=> [24.1, 16.2, 48.3, 32.4, 8.5]irb(main):005:0># Example 2:irb(main):006:0* # First-class functions as an explicit object of Proc -irb(main):007:0* eski = Proc.yeni { koyar "Selam Dünya!" }=> #irb(main):008:0>eski.telefon etmekHello, world!=> nilirb (ana): 009: 0># Example 3:irb (ana): 010: 0 * # Function that returns lambda function object with parametersirb(main):011:0* def is_multiple_of(n)irb(main):012:1>  lambda{|x| x % n == 0}irb(main):013:1>son=> nilirb(main):014:0>multiple_four = is_multiple_of(4)=> #irb(main):015:0>multiple_four.telefon etmek(16)=> trueirb(main):016:0>multiple_four[15]=> false

Pas, paslanma

İçinde Pas, paslanma, anonymous functions are called closures.[42] They are defined using the following syntax:

|<parametre-isim>: <tip>|-> <dönüş-tip>{<vücut>};

Örneğin:

İzin Vermekf=|x: i32|-> i32 {x*2};

With type inference, however, the compiler is able to infer the type of each parameter and the return type, so the above form can be written as:

İzin Vermekf=|x|{x*2};

With closures with a single expression (i.e. a body with one line), the curly braces may be omitted:

İzin Vermekf=|x|x*2;

Closures with no input parameter are written like so:

İzin Vermekf=||println!("Selam Dünya!");

Closures may be passed as input parameters of functions that expect a function pointer:

// A function which takes a function pointer as an argument and calls it with// the value `5`.fn uygulamak(f: fn(i32)-> i32)-> i32 {// No semicolon to indicate an implicit returnf(5)}fn ana(){// Defining the closureİzin Vermekf=|x|x*2;println!("{}",uygulamak(f));// 10println!("{}",f(5));// 10}

However, one may need complex rules to describe how values in the body of the closure are captured. They are implemented using the Fn, FnMut, ve FnOnce özellikler:[43]

  • Fn: the closure captures by reference (&T). They are used for functions that can still be called if they only have reference access (with &) to their environment.
  • FnMut: the closure captures by mutable reference (&mut T). They are used for functions that can be called if they have mutable reference access (with &mut) to their environment.
  • FnOnce: the closure captures by value (T). They are used for functions that are only called once.

With these traits, the compiler will capture variables in the least restrictive manner possible.[44] They help govern how values are moved around between scopes, which is largely important since Rust follows a lifetime construct to ensure values are "borrowed" and moved in a predictable and explicit manner.[45]

The following demonstrates how one may pass a closure as an input parameter using the Fn trait:

// A function that takes a value of type F (which is defined as// a generic type that implements the `Fn` trait, e.g. a closure)// and calls it with the value `5`.fn apply_by_ref<F>(f: F)-> i32    neredeF: Fn(i32)-> i32{f(5)}fn ana(){İzin Vermekf=|x|{println!("I got the value: {}",x);x*2};// Applies the function before printing its return valueprintln!("5 * 2 = {}",apply_by_ref(f));}// ~~ Program output ~~// I got the value: 5// 5 * 2 = 10

Scala

İçinde Scala, anonymous functions use the following syntax:[46]

(x: Int, y: Int) => x + y

In certain contexts, like when an anonymous function is a parameter being passed to another function, the compiler can infer the types of the parameters of the anonymous function and they can be omitted in the syntax. In such contexts, it is also possible to use a shorthand for anonymous functions using the underscore character to introduce unnamed parameters.

val liste = Liste(1, 2, 3, 4)liste.reduceLeft( (x, y) => x + y ) // Here, the compiler can infer that the types of x and y are both Int. // Thus, it needs no type annotations on the parameters of the anonymous function.liste.reduceLeft( _ + _ )   // Each underscore stands for a new unnamed parameter in the anonymous function. // This results in an even shorter equivalent to the anonymous function above.

Smalltalk

İçinde Smalltalk anonymous functions are called bloklar and they are invoked (called) by sending them a "value" message. If arguments are to be passed, a "value:...value:" message with a corresponding number of value arguments must be used.

[:x | x*x ] değer: 4"returns 16"

Smalltalk blocks are technically closures, allowing them to outlive their defining scope and still refer to the variables declared therein.

[:a |    [:n | a + n ] ] değer: 10"returns the inner block, which adds 10 to its argument."

Swift

İçinde Swift, anonymous functions are called closures.[47] The syntax has following form:

{ (parametreleri) -> returnType içinde  Beyan}

Örneğin:

{ (s1: Dize, s2: Dize) -> Bool içinde  dönüş s1 > s2}

For sake of brevity and expressiveness, the parameter types and return type can be omitted if these can be inferred:

{ s1, s2 içinde dönüş s1 > s2 }

Similarly, Swift also supports implicit return statements for one-statement closures:

{ s1, s2 içinde s1 > s2 }

Finally, the parameter names can be omitted as well; when omitted, the parameters are referenced using shorthand argument names, consisting of the $ symbol followed by their position (e.g. $0, $1, $2, etc.):

{ $0 > $1 }

Tcl

İçinde Tcl, applying the anonymous squaring function to 2 looks as follows:[48]

uygulamak {x {expr {$ x*$ x}}} 2# returns 4

This example involves two candidates for what it means to be a işlevi in Tcl. The most generic is usually called a command prefix, and if the variable f holds such a function, then the way to perform the fonksiyon uygulaması f(x) would be

{*}$f $ x

nerede {*} is the expansion prefix (new in Tcl 8.5). The command prefix in the above example is apply {x {expr {$x*$x}}} Command names can be bound to command prefixes by means of the interp alias komut. Command prefixes support köri. Command prefixes are very common in Tcl API'ler.

The other candidate for "function" in Tcl is usually called a lambda, and appears as the {x {expr {$x*$x}}} part of the above example. This is the part which caches the compiled form of the anonymous function, but it can only be invoked by being passed to the uygulamak komut. Lambdas do not support currying, unless paired with an uygulamak to form a command prefix. Lambdas are rare in Tcl APIs.

Visual Basic .NET

Visual Basic .NET 2008 introduced anonymous functions through the lambda form. Combined with implicit typing, VB provides an economical syntax for anonymous functions. As with Python, in VB.NET, anonymous functions must be defined on one line; they cannot be compound statements. Further, an anonymous function in VB.NET must truly be a VB.NET Fonksiyon - it must return a value.

Karart foo = Fonksiyon(x) x * xKonsol.Yazı çizgisi(foo(10))

Visual Basic.NET 2010 added support for multiline lambda expressions and anonymous functions without a return value. For example, a function for use in a Thread.

Karart t Gibi Yeni Sistem.Diş çekme.Konu(Alt ()                                         İçin n Gibi Tamsayı = 0 İçin 10   'Count to 10                                             Konsol.Yazı çizgisi(n)     'Print each number                                         Sonraki                                     Son Alt                                     )t.Başlat()

Ayrıca bakınız

Referanslar

  1. ^ "Higher order functions". Learnyouahaskell.com. Alındı 3 Aralık 2014.
  2. ^ Fernandez, Maribel (2009), Models of Computation: An Introduction to Computability Theory, Undergraduate Topics in Computer Science, Springer Science & Business Media, p. 33, ISBN  9781848824348, The Lambda calculus ... was introduced by Alonzo Church in the 1930s as a precise notation for a theory of anonymous functions
  3. ^ "Bash lambda". 2019-03-08.
  4. ^ BillWagner. "Lambda expressions - C# reference". docs.microsoft.com. Alındı 2020-11-24.
  5. ^ "Closure support". Arşivlenen orijinal 2014-01-06 tarihinde. Alındı 2014-01-05.
  6. ^ "Whats new in ColdFusion 10". Arşivlenen orijinal 2014-01-06 tarihinde. Alındı 2014-01-05.
  7. ^ "Managed COBOL Reference". Micro Focus Documentation. Mikro Odak. Alındı 25 Şubat 2014.
  8. ^ a b "A tour of the Dart language". dart.dev. Alındı 2020-11-24.
  9. ^ "Anonymous Methods in Delphi - RAD Studio". docwiki.embarcadero.com. Alındı 2020-11-24.
  10. ^ a b "Erlang/Elixir Syntax: A Crash Course". elixir-lang.github.com. Alındı 2020-11-24.
  11. ^ a b "Erlang -- Funs". erlang.org. Alındı 2020-11-24.
  12. ^ a b cartermp. "Lambda Expressions: The fun Keyword - F#". docs.microsoft.com. Alındı 2020-11-24.
  13. ^ "Quotations - Factor Documentation". Alındı 26 Aralık 2015. A quotation is an anonymous function (a value denoting a snippet of code) which can be used as a value and called using the Fundamental combinators.
  14. ^ "Frink". frinklang.org. Alındı 2020-11-24.
  15. ^ a b "Anonymous Functions in GoLang". GoLang Docs. Alındı 2020-11-24.
  16. ^ "Gosu Documentation" (PDF). Alındı 4 Mart 2013.
  17. ^ "Groovy Documentation". Arşivlenen orijinal 22 Mayıs 2012 tarihinde. Alındı 29 Mayıs 2012.
  18. ^ "Functions · The Julia Language". docs.julialang.org. Alındı 2020-11-24.
  19. ^ "Higher-Order Functions and Lambdas - Kotlin Programming Language". Kotlin. Alındı 2020-11-24.
  20. ^ "Programming in Lua : 6". www.lua.org. Alındı 2020-11-24.
  21. ^ "Maple Programming: 1.6: Anonymous functions and expressions - Application Center". www.maplesoft.com. Alındı 2020-11-24.
  22. ^ "Maxima 5.17.1 Manual: 39. Function Definition". maths.cnam.fr. Alındı 2020-11-24.
  23. ^ "Nim Manual, Anonymous Procs".
  24. ^ "Code Examples – OCaml". ocaml.org. Alındı 2020-11-24.
  25. ^ "GNU Octave: Anonymous Functions". octave.org. Alındı 2020-11-24.
  26. ^ a b "perlsub - Perl subroutines - Perldoc Browser". perldoc.perl.org. Alındı 2020-11-24.
  27. ^ "PHP: Anonymous functions - Manual". www.php.net. Alındı 2020-11-24.
  28. ^ a b "6. Expressions — Python 3.9.0 documentation". docs.python.org. Alındı 2020-11-24.
  29. ^ "4.4 Functions: lambda". docs.racket-lang.org. Alındı 2020-11-24.
  30. ^ a b "Projects/Vala/Tutorial - GNOME Wiki!". wiki.gnome.org. Alındı 2020-11-24.
  31. ^ Järvi, Jaakko; Powell, Gary (n.d.). "Chapter 16. Boost.Lambda". Boost Documentation. Boost. Alındı 22 Aralık 2014.
  32. ^ C# 4.0 Language Specification, section 5.3.3.29
  33. ^ "What's New in JDK 8".
  34. ^ a b The Java Tutorials: Lambda Expressions, docs.oracle.com
  35. ^ "Programming in Lua - More about Functions". Arşivlendi 14 Mayıs 2008 tarihinde orjinalinden. Alındı 2008-04-25.
  36. ^ https://www.cs.cornell.edu/courses/cs3110/2019sp/textbook/basics/anonymous_functions.html
  37. ^ https://nim-lang.github.io/Nim/manual.html#procedures-anonymous-procs
  38. ^ http://php.net/create_function the top of the page indicates this with "(PHP 4 >= 4.0.1, PHP 5)"
  39. ^ "PHP: rfc:closures".
  40. ^ "Anonymous Predicates". in Visual Prolog Language Reference
  41. ^ Sosinski, Robert (2008-12-21). "Understanding Ruby Blocks, Procs and Lambdas". Reactive.IO. Arşivlenen orijinal 2014-05-31 tarihinde. Alındı 2014-05-30.
  42. ^ "Closures - Rust by Example".
  43. ^ "As input parameters - Rust by Example".
  44. ^ "As input parameters - Rust by Example".
  45. ^ "Lifetimes - Rust by Example".
  46. ^ "Anonymous Function Syntax - Scala Documentation". Arşivlenen orijinal 2013-07-23 tarihinde. Alındı 2010-12-31.
  47. ^ "The Swift Programming Language (Swift 3.0.1): Closures".
  48. ^ apply manual page, retrieved 2012-09-06.

Dış bağlantılar