Bir lambda nedir ve neden faydalı olabilir? [kapalı]


56

Şimdiye kadar duydum:

  • Lambda hesabı
  • Lambda programlama
  • Lambda ifadeleri
  • Lambda fonksiyonları

Bunların hepsi işlevsel programlama ile ilgili görünüyor ...

Görünüşe göre C ++ 1x'e entegre olacak, şimdi daha iyi anlayabiliyorum:

http://en.wikipedia.org/wiki/C%2B%2B0x#Lambda_functions_and_expressions

Birisi kuzuların neler olduğunu kısaca tanımlayabilir ve faydalı olabileceği bir yere verebilir mi?


2
Terminolojinin tarihsel olarak, bir ifadenin temsil ettiği işlev hakkında konuşmak için iyi bir yol istemekten geldiğine dikkat edin. X + 1 ile temsil edilen fonksiyon, lambda x ile yazılır. x + 1.
kasterma

Lambda şekilde, bir işlev başka bir işlevi yiyor ve / veya bir girdi değeri başka bir işlev üretiyor. Bir işlev bir çözüm üretene kadar bu devam eder. Ayrıca, timsah yumurtaları .
SD,

Hepsi benim için Yunanca. Sanırım bir caydırıcılık yapacağım, kuzu severim, hah.

Yanıtlar:


44
  • Lambda hesabı

Lambda matematiği 30'lu yıllarda Alonzo Kilisesi tarafından icat edilen bir hesaplama modelidir. Çoğu işlevsel programlama dilinin sözdizimi ve anlambilimi, doğrudan veya dolaylı olarak lambda matematiğinden ilham almaktadır.

Lambda matematiğinin en temel haliyle iki işlemi vardır: Soyutlama (adsız bir fonksiyon oluşturma) ve uygulama (bir fonksiyon uygulama). Soyutlama λ operatörü kullanılarak gerçekleştirilir ve bu da lambda hesabına adını verir.

  • Lambda ifadeleri
  • Lambda fonksiyonları

Anonim işlevler genellikle "lambda", "lambda işlevler" veya "lambda ifadeler" olarak adlandırılır, çünkü yukarıda belirttiğim gibi λ, lambda hesabında anonim işlevler oluşturmanın simgesidir (ve kelime lambdabirçok lispta anonim işlevler oluşturmak için kullanılır) tabanlı aynı dilde).

  • Lambda programlama

Bu yaygın olarak kullanılan bir terim değildir, ancak anonim işlevler kullanarak programlama veya daha yüksek dereceli işlevler kullanarak programlama anlamına gelir.


C ++ 0x 'deki lambdalar, motivasyonları ve fonksiyon göstergeleri ile nasıl ilişkili oldukları hakkında biraz daha fazla bilgi (bunun çoğu zaten bildiklerinizin bir tekrarı olabilir, ancak umarım lambdaların motivasyonunu ve nasıl farklı olduklarını açıklamaya yardımcı olur. işlev işaretçilerinden):

C'de zaten var olan fonksiyon işaretçileri, örneğin bir sıralama fonksiyonuna bir karşılaştırma fonksiyonunu geçmek için oldukça kullanışlıdır. Bununla birlikte, yararlarının sınırları vardır:

Örneğin, bir vektörün vektörünü iher bir vektörün th elemanına göre sıralamak istiyorsanız ( içalışma zamanı parametresidir), bunu bir işlev işaretçisiyle çözemezsiniz. İki vektörü ith elemanlarıyla karşılaştıran bir fonksiyonun üç argüman alması gerekir ( ive iki vektör), ancak sıralama fonksiyonu iki argüman alan bir fonksiyona ihtiyaç duyar. İhtiyacımız olan şey, argümanı isıralama fonksiyonuna aktarmadan önce fonksiyona bir argüman sağlamanın bir yoludur , ancak bunu düz C fonksiyonlarıyla yapamayız.

Bunu çözmek için, C ++ "fonksiyon nesneleri" veya "işlev" kavramını ortaya koydu. Bir işlev, temelde bir operator()yöntemi olan bir nesnedir . Şimdi CompareByIthElementargümanı iyapıcı argüman olarak alan ve sonra argüman olarak karşılaştırılacak iki vektörü operator()metodla karşılaştıran bir sınıf tanımlayabiliriz . Bir vektör vektörünü ith öğesine göre sıralamak için şimdi argüman olarak bir CompareByIthElementnesne oluşturabilir ive sonra bu nesneyi sıralama işlevine geçirebiliriz.

İşlev nesneleri yalnızca nesneler olduğundan ve teknik olarak işlevler olmadığından (onlar gibi davranmak zorunda olsalar bile), işlev işaretçisini işlev nesnesine işaret edemezsiniz (elbette işlev nesnesine işaretçi olabilir, ancak gibi bir tür olurdu CompareByIthElement*ve bu nedenle bir işlev işaretçisi olamazdı).

İşlevleri argüman olarak alan C ++ standart kütüphanesindeki işlevlerin çoğu, işlev işaretçilerinin yanı sıra işlev nesneleriyle çalışabilmeleri için şablonlar kullanılarak tanımlanır.

Şimdi lambdas'a:

Bir iöğeyi sıralamak için yalnızca bir kez kullanacaksanız , th öğesiyle karşılaştırılacak bir sınıfı tanımlamak biraz ayrıntılıdır. Yalnızca bir işlev işaretçisine ihtiyaç duyduğunuz durumda bile, adlandırılmış bir işlevi tanımlamak, yalnızca bir kez kullanılırsa, en düşük düzeydedir; mantığı kendi işlevine soyutlamak için iyi bir neden (bunun dışında bir işlev tanımlamaksızın işlev işaretçilerine sahip olamamanız).

Böylece bu lambdaları düzeltmek için tanıtıldı. Lambdalar fonksiyon işaretçisi değil fonksiyon nesnesidir. Bir lambda kullanırsanız [x1, x2](y1,y2){bla}, temel olarak aşağıdakileri yapan hazır kod benzer bir kod üretilir:

  1. İki üye değişkenine ( x1ve x2) ve bir operator()de argümanlara ( y1ve y2) ve gövdeye sahip olan bir sınıf tanımlayın bla.
  2. Üye değişkenleri ayarlayarak, sınıfının bir örneğini oluşturun x1ve x2değişkenlerin değerlerine x1ve x2halen kapsamında.

Böylece lambdalar, fonksiyon nesneleri gibi davranırlar, ancak lambda kullanmak dışında bir lambda uygulamak için oluşturulan sınıfa erişemezsiniz. Sonuç olarak, fonk- siyonları argüman olarak kabul eden herhangi bir fonksiyon (temel olarak standart kütüphanedeki C olmayan herhangi bir fonksiyon anlamına gelir), lambdaları kabul eder, ancak sadece fonksiyon işaretçilerini kabul eden herhangi bir fonksiyon kabul etmez.


İşlev işaretçileriyle adsız işlevler mi kullanılıyor? Değilse fark nedir?
jokoon

1
@jokoon: Hayır, anonim işlevler, yalnızca işlev işaretçileri alan işlevlere parametre olarak iletilemez. Ancak argüman olarak işlev alan çoğu işlev, şablonlar kullanılarak tanımlanır, böylece yalnızca işlev işaretçisini değil, her türlü işlev nesnesini argüman olarak alabilirler. Diğer bir deyişle, işlev işaretçilerini ( std::sortörneğin) kullanabileceğiniz çoğu yerde bunun yerine adsız işlevleri kullanabileceksiniz. Ancak, anonim bir işlevi argüman olarak alması gereken bir işlevi tanımlarken, bir şablon kullanmanız veya std::functionargümanın türü olarak kullanmanız gerekir .
sepp2k

bu nedenle bir işlev işaretçisi bir lambda içeremez ...
jokoon

1
+1 Mükemmel açıklama - Bunu da öğrenemedim.
Michael K,

2
Bu işte Michael ile birlikteyim. Bu çok kapsamlı. +1benden.
sbi

18

Temel olarak, lambda işlevleri "anında" oluşturduğunuz işlevlerdir. C ++ 1x'te fonksiyonel programlama desteğini geliştirmek için kullanılabilirler:

std::for_each( begin, end, [](int i){std::cout << i << '\n';} );

Bu kabaca buna benzer bir kodla sonuçlanacaktır:

struct some_functor {
  void operator()(int i) {std::cout << i << '\n';}
};

std::for_each( begin, end, some_functor() );

Bunun some_functoriçin sadece bir çağrı yapmanız gerekiyorsa std::for_each(), o zaman lambda işlevinin üzerinde birkaç avantajı vardır:

  • döngüde ne yapılır, döngü işlevinin çağrıldığı yer tam olarak belirlenir.
  • bazı kazan plakası kodunu yazmanızı sağlar
  • Herkesin neye ihtiyaç duyduğunu merak ederek koda bakmasını sağlayan bazı isim-alanı kapsamı etrafında yatan bir işlev yok

7

Bir lambda işlevi, adsız bir işlev için başka bir addır - temelde adsız bir işlev.

Genellikle bunu sadece bir kez kullanmanız gerekecek dillerde kullanırsınız. Örneğin yerine

def add(a, b)
  return a+b

ve sonra bu işlevi bunun gibi başka bir işleve geçirmek

reduce(add, [5,3,2])

Bir lambda ile sadece yapardın

reduce(lambda x, y: a+b, [5,3,2])
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.