Herkesin bahsettiği bu 'Lambda' nedir?


93

Herkesin bahsettiği bu 'Lambda' nedir? Görünüşe göre pek çok insan onu seviyor, ancak ondan anlayabildiğim tek şey, çok sayıda kod satırını tek bir ifadeye sığdırmanın bir yolu.

Birisi beni bunun gerçek değeri konusunda aydınlatabilir mi?


16
Ben sorgulayıcı hiçbir yerde .net söz ettiği cevap verenlere karşı işaret edebilir


Çatlak soru. Sorduğunuz için teşekkürler.
Peanut

Lambdalar, fonksiyonel programlama dünyasına aittir (Bildirime dayalı programlama).
RBT

Yanıtlar:


179

İsimsiz işlevler

Basitçe söylemek gerekirse, bir lambda, adı olmayan bir işlev veya anonim bir işlevdir. Sanki bir değişkenmiş gibi aktarılabilen küçük bir yürütülebilir kod parçası. JavaScript'te:

function () {}; // very simple

Şimdi bu lambdaların bazı kullanımlarına bakalım.

Soyutlama standart kodu

Lambdalar, standart kodu soyutlamak için kullanılabilir. Örneğin döngüler. Gün boyu yazmaya forve whiledöngü yapmaya alışkınız. Ancak bu yazılamayan koddur. Döngünün en önemli parçası olan döngünün içindeki kodu çıkarabilir ve geri kalanını soyutlayabiliriz:

for (var i=0; i<array.length; i++) {
    // do what something useful with array[i]
}

forEachdizi nesnelerini kullanarak şu hale gelir:

array.forEach(function (element, index) {
   // do something useful with element
   // element is the equivalent of array[i] from above
});

Yukarıdaki soyutlama o kadar yararlı olmayabilir, ancak forEachçok daha yararlı görevleri yerine getiren daha üst düzey işlevler de vardır . Örneğin filter:

var numbers = [1, 2, 3, 4];
var even    = [];

// keep all even numbers from above array
for (var i=0; i<numbers.length; i++) {
    if (numbers[i] % 2 === 0) {
        even.push(numbers[i]);
    }
}

alert(even);

// Using the filter method
even = [1, 2, 3, 4].filter(function (number) {
    return number % 2 === 0;
});

alert(even);

Kod yürütme gecikmesi

Olay kavramının mevcut olduğu bazı ortamlarda, zamanın bir noktasında meydana gelebilecek olaylara yanıt vermek için lambdaları kullanabiliriz.

window.onload = function () {
    alert("Loaded");
};

window.setTimeout(function () {
    alert("Code executed after 2 seconds.");
}, 2000);

Bu başka yollarla da yapılabilirdi, ancak bunlar oldukça ayrıntılı. Örneğin, Java'da Runnablearayüz var.

Fonksiyon fabrikaları

Bu noktaya kadar, çoğunlukla sadece sözdizimsel şeker yetenekleri için lambdaları kullandık. Ancak lambdaların çok daha faydalı olabileceği durumlar vardır. Örneğin, lambdaları döndüren işlevlerimiz olabilir. Diyelim ki dönüş değerlerinin önbelleğe alınmasını istediğimiz bir fonksiyonumuz var.

var users = [];
var getUser = function (name) {
    if (! users[name]) {
        // expensive operations to get a user. Ajax for example
        users[name] = user_from_ajax;
    }

    return users[name];
};

Daha sonra benzer bir işleve sahip olduğumuzu fark edebiliriz:

var photos = [];
var getPhoto = function (name) {
    if (! photo[name]) {
        // expensive operations to get a user. Ajax for example
        photos[name] = photo_from_ajax;
    }

    return photos[name];
};

Orada açıkça bir model var, o yüzden onu soyutlayalım. Memoization kullanalım .

/**
 * @param {Array}     store Data structure in which we cache lambda's return values
 * @param {Function}  lambda
 * @return {Function} A function that caches the result of calling the lambda param
 */
var memoize = function (store, lambda) {
    // return a new lambda
    return function (name) {
        if (! store[name]) {
            // Execute the lambda and cache the result
            store[name] = lambda(name);
        }

        return store[name];
    };
};

var getUsers = memoize([], function (name) {
    // expensive operations to get a user. Ajax for example
});

var getPhotos = memoize([], function (name) {
    // expensive operations to get a photo. Ajax for example
});

Gördüğünüz gibi, lambdas kullanarak, önbelleğe alma / not etme mantığını soyutlamayı başardık. Diğer örnek için bazı geçici çözümler olsaydı, bu özel sorunun diğer teknikler kullanılarak pek çözülmediğine inanıyorum. Bazı önemli standart kodları tek bir yere çıkarmayı başardık. usersVe photosküresel değişkenlerden kurtulduğumuzdan bahsetmiyorum bile .

Profilinize baktığımda, çoğunlukla bir Python kullanıcısı olduğunuzu görüyorum. Yukarıdaki model için Python, dekoratör kavramına sahiptir. Memoization dekoratörleri için internette birçok örnek var . Tek fark, Python'da büyük olasılıkla bu dekoratör işlevinin içinde adlandırılmış iç içe geçmiş bir işleve sahip olmanızdır . Python'un yalnızca tek ifadeli lambdaları desteklemesinin nedeni. Ancak konsept aynı.

Python lambda kullanımına bir örnek olarak. Çift sayıları filtrelediğimiz yukarıdaki kod Python'da şu şekilde temsil edilebilir:

filter(lambda x: x % 2 == 0, [1, 2, 3, 4])

Her neyse, lambdalar kapanmadan o kadar güçlü değildir. Lambda kavramını bu kadar güçlü yapan şey kapanışlardır. Memoization örneğimde, storeparam etrafında bir kapanış oluşturmak için kapanışlar kullandım . Bu şekilde, memoizeişlev sonucunu (bir lambda) döndürdükten sonra bile bu parametreye erişebilirim .


3
Vay canına, buna çok zaman ayırdın.
mk12

4
@ Mk12, cevabın gerçek yazımında, gerçekten değil. Bu şeyleri öğrenirken, evet, başladığımdan bu yana
epey

İyi yanıt, ancak "işlevsel arayüzler" hakkında eksik bilgi (Java açısından).
djangofan

"Özetleme standart kodunuzdaki" bu "===" operatörleri nelerdir?
Don


19

"Lambda" terimi, genellikle bir kapanış olan anonim bir işleve atıfta bulunmak için kullanılır . Kullanışlılar çünkü kodunuzu gereksiz yere şişirmeden başka işlevleri kullanan işlevler yazmanıza izin veriyorlar. Örneğin, Ruby'de:

(1..100).select {|num| num % 2 == 0}

Bu, 1 ile 100 arasındaki çift sayıları içeren bir dizi oluşturacaktır. Açık bir döngü yazmak zorunda değiliz - seçme yöntemi, değerleri test etmek için kullandığı bir işlevi alır, bu nedenle tek ihtiyacımız olan özel mantığımızdır. Bu, neredeyse hiç çaba harcamadan veya ek yük olmadan yöntemi büyük ölçüde özelleştirmemize olanak tanır. Temel olarak, işlevleri daha küçük işlevlerden oluşturabiliriz.

Bu, yapabileceklerinin basit bir örneği. İşlevleri veri olarak geçirme yeteneği gerçekten güçlüdür ve işlevsel dil programcıları rutin olarak onunla gerçekten harika şeyler yaparlar.


6
Belki de boruların içindeki şeyin parametre olduğunu eklemelisiniz. Yakut okumakta güçlük çeken insanlardan biriyim.
Skurmedel

Bu güzel bir cevap. Ionut'un oyumu almasının tek nedeni, bize lambdaları neden (ayrıntılı olarak) önemsememiz gerektiğini söylemesidir.
Frank Shearar

Lambdaların genellikle kapalı olduğu konusunda hemfikir değilim.
jwg

6

"Lambda" belki çok az. Lambda hesabına bir göz atın . Fonksiyonel programlamada kullanışlıdır.

Ve işlevsel programlama, bir başka programlama paradigmasıdır (prosedürel veya nesne yönelimli gibi).


5
Sonra insanlar "Lambda" hakkında konuşurlar, büyük olasılıkla anonim işlev, işlev işaretçileri, kapanış veya benzeri bir şeyden bahsederler. Neredeyse hiçbir zaman gerçek lambda hesabına değinmeyin.
J-16 SDiZ

Lambda hesabından bahsetmenize sevindim.! +1.
RBT

5

.NET'teki Lambdalar genellikle "sözdizimsel şeker" olarak adlandırılır. İşlevselliği doğrudan etkilemezler ancak dili insanların kullanmasını kolaylaştırırlar.

Bunları kullanmanın gücünü anladığınızda, delegeler / anonim yöntemler kullanarak eski stil yöntemlere kıyasla daha az kod yazdığınızı göreceksiniz.


1
Kimsenin .NET'ten bahsettiğini sanmıyorum, bu yüzden OP muhtemelen daha genel bir cevapla daha iyi durumda.
molf

2
bu yüzden .net hakkında olduğu cevabıyla açıkladım. Başkaları dil uygulamalarıyla cıvıl cıvıl cıvıl cıvıl cıvıl cıvıl cıvıl cıvıl cıvıl cıvıl cıvıl cıvıl cıvıl cıvıl cıvıl cıvıl cıvıl olsun, o zaman soru ve cevap birçok kişiye dil seçimi ne olursa olsun yardımcı olacaktır.
redsquare

Bu cevaplar, lambdalar hakkında bir şeyler duymuşsunuz gibi okur, ancak siz henüz onları anlamıyorsunuz.
jwg

2

Dr Dobbs Journal'ın lambda ifadelerini tanıtan faydalı bir makalesi var (C ++ bağlamında ancak ilkeleri herhangi bir dile uygulayabileceğinizi düşünüyorum).

Makalede belirtildiği gibi: "Bir lambda ifadesi, ayrı bir sınıf / işlev tanımı gerektirmeyen oldukça kompakt bir ifadedir."

Dolayısıyla , yazmak yerine DDJ'deki 1 ve 2 liste örneklerini kullanarak :

std::for_each( vec.begin(), vec.end(), print_to_stream<std::string>(std::cout));

Aşağıdakiler gibi ayrı bir sınıf tanımı gerektirir:

template <typename T, typename Stream> class print_to_stream_t {
  Stream& stream_;
public:
  print_to_stream_t(Stream& s):stream_(s) {}
  void operator()(const T& t) const {
    stream_ << t;
  }
};
template <typename T,typename Stream> 
print_to_stream_t<T,Stream>   print_to_stream(Stream& s) {
  return print_to_stream_t<T,Stream>(s);
}

Boost lambda kitaplığını kullanarak bu şu hale gelebilir:

std::for_each(vec.begin(),vec.end(),std::cout << _1);

Bu tanımı satır içi tutar.

Makale ayrıca lambda ifadelerinin bazı başka uygulamalarını da açıklamaktadır.

Bence DDJ makalesindeki kilit nokta "Tipik olarak, arama sitesinde küçük ve aşırı karmaşık olmayan işlevlere ihtiyaç duyulduğunda lambda ifadeleri kullanılır. İşlev önemsiz olsaydı, bir lambda ifadesi istemezdiniz, normal bir işlev veya bir işlev nesnesi. "


2

Daha önce işlev işaretçileri, temsilciler, strateji veya gözlemci örüntü / olay işleme kullanan işlevler / yöntemlerle çalıştıysanız ve kendi kendinize "Bu işlevi yalnızca bir kez kullanmak için yazıyorum - bu yönteme geçirmek için ; Keşke kodumu karıştırmaktansa yerinde yazabilseydim "- Lambda işlevlerini burada kullanabilirsiniz. Bu yapıyı destekleyen diller ayrıca, özellikle listelerle (birinci sınıf işlevler ve daha yüksek dereceli işlevler) çalışmaya ilişkin olarak, genellikle işlevlerin parametre olarak geçirilmesi kavramından büyük ölçüde yararlanır. Bu özellikle, hesaplamalar için bellek modifikasyonundan çok işlev kompozisyonuna dayanan işlevsel diller için geçerlidir. Bazı durumlarda (Python gibi dillerde),


2

'lambda' qua kelimesi, bilgisayar bilimi türlerinin bilgisayar bilimi derecesine sahip olmaktan çok matematik veya mantıkta eğitilme olasılığının yüksek olduğu günlerden kalma bir terminolojidir. Bazıları, zorunludan oldukça farklı ve oldukça güçlü olan 'işlevsel programlama' adı verilen bir paradigma oluşturdu. AFAIK , terimin kullanıma girdiği ortamdır.

Matematikçiler ve mantıkçılara tuhaf kelimeler veriliyor.

'lambda' kulağa gerçekten ezoterik geliyor - sanki çok garip ve özel bir şeymiş gibi. Gerçekten, bir web tarayıcı uygulaması için JavaScript yazarsanız ve "var foo = function () {...}" deyimini kullanırsanız, başından beri lambda işlevlerini kullanıyorsunuzdur.


1

Lambda ifadesi basit bir işlev biçimidir. Buradaki fikir, soldaki formdaki bir şeyin (parametrelere eşdeğer) sağdaki formun (vücuda eşdeğer) bir şey haline gelmesidir.

örneğin, c diyez:

x => x * x

bir değerin karesini almak için bir lambda'dır. Formda bir şey

x

formda bir şey olur

x * x

0

"Lambda ifadesi, ifadeler ve ifadeler içerebilen ve temsilciler veya ifade ağacı türleri oluşturmak için kullanılabilen anonim bir işlevdir.

Tüm lambda ifadeleri, "gider" olarak okunan lambda operatörü => kullanır. Lambda operatörünün sol tarafı giriş parametrelerini (varsa) belirtir ve sağ tarafı ifade veya ifade bloğunu tutar. Lambda ifadesi x => x * x okunur "x, x çarpı x'e gider."

dan MSDN


4
Evet, Microsoft herkesin onu icat ettiğini düşündürüyor. Lambda ifadeleri Microsoft'tan öncedir. Birkaç programlama diline uygulanan matematiksel bir terimdir. (Bu mümkün, çünkü matematik kendi başına bir bilgisayar dili olarak kabul edilebilir.)
Wim ten Brink

4
Bunun Microsoft'un .Net uygulamasına özgü olduğunu unutmayın. Bu genel bir lambda fikrinden çok büyük bir sapma değil, ancak Lisp'de uygulanan işlevselliğin daha "standart" olduğunu düşünüyorum.
Chuck

2
Bu cevap, bir Lambda'nın ne olduğunu hiç açıklamıyor (anonim işlev, temsilci, ifade ağacı türü tanımlarına ihtiyaç duyuyor) ve kesinlikle değerinin ne olduğunu açıklamıyor.
danio

0

Lambda ifadeleri hakkında tam bir açıklama için Wikipedia'ya da göz atın . ( Lambda hesabı ve programlama dilleri bölümüne ilerleyin .) Lambda ifadeleri o kadar yeni değil ve sadece C # 'ın bir parçası değil, neredeyse 80 yıl önce hesaplamaya getirilen bir şey! Lambda ifadeleri, işlevsel programlamanın temelidir.

Değeri? Aslında oldukça eski olduğunu düşünürsek şunu söyleyebilirim: hesaplama yapan herkes için çok değerli.


0

Java ile ilgiliyseniz, son birkaç ay içinde lambdalar veya kapanışlar hakkında çok şey duymuşsunuzdur, çünkü bu özelliği Java 7'ye eklemek için farklı teklifler vardı, ancak bence komite bunu bıraktı. Önerilerden biri Neal Gafter'den ve burada ayrıntılı olarak açıklandı: javac.info . Bu, kullanım durumlarını ve avantajlarını anlamama yardımcı oldu (özellikle iç sınıflara göre)




-1

Evet, bu sadece bir çok kod satırını tek bir ifadeye sıkıştırmanın bir yoludur. Ancak bu kadar verimli bir çalışma olarak, programınızı yapılandırmanın bazı yeni yollarını etkinleştirir.

Çoğu zaman, delege veya geri arama yazmaktan kaçınılır ve yordamsal stile geri döner, çünkü tek bir ifade için yeni işlevler veya sınıflar bildirmek çok fazladır.

Lambda ifadeleri, en küçük görevler için bile geri aramaları kullanmayı değerli kılar, bu da kodu daha net hale getirebilir. Olmayabilir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.