Apa itu lambda, dan mengapa itu berguna? [Tutup]

56

Sejauh ini saya mendengar tentang:

  • Kalkulus Lambda
  • Pemrograman Lambda
  • Ekspresi Lambda
  • Fungsi Lambda

Yang semuanya tampaknya terkait dengan pemrograman fungsional ...

Rupanya itu akan diintegrasikan ke dalam C ++ 1x, jadi saya mungkin lebih mengerti sekarang:

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

Adakah yang bisa mendefinisikan dengan singkat apa saja hal-hal lambdas dan memberikannya di tempat yang bermanfaat?

jokoon
sumber
2
Perhatikan bahwa terminologi secara historis berasal dari keinginan cara yang baik untuk berbicara tentang fungsi yang diwakili oleh ekspresi. Fungsi yang diwakili oleh x + 1 kemudian ditulis lambda x. x +1.
kasterma
Dengan cara lambda, suatu fungsi makan fungsi lain dan / atau nilai input, menghasilkan fungsi lain. Ini berlanjut sampai suatu fungsi menghasilkan solusi. Juga, telur buaya .
SD
Itu semua Yunani untuk saya. Saya pikir saya akan pergi memiliki lang, saya suka domba, ya.

Jawaban:

44
  • Kalkulus Lambda

Kalkulus lambda adalah model perhitungan yang ditemukan oleh Gereja Alonzo pada usia 30-an. Sintaks dan semantik dari sebagian besar bahasa pemrograman fungsional secara langsung atau tidak langsung terinspirasi oleh kalkulus lambda.

Kalkulus lambda dalam bentuk paling dasar memiliki dua operasi: Abstraksi (membuat fungsi (anonim)) dan aplikasi (menerapkan fungsi). Abstraksi dilakukan menggunakan operator λ, memberi nama lambda kalkulus.

  • Ekspresi Lambda
  • Fungsi Lambda

Fungsi anonim sering disebut "lambdas", "fungsi lambda" atau "ekspresi lambda" karena, seperti yang saya katakan di atas, λ adalah simbol untuk membuat fungsi anonim dalam kalkulus lambda (dan kata lambdaitu digunakan untuk membuat fungsi anonim di banyak bahasa) bahasa berbasis untuk alasan yang sama).

  • Pemrograman Lambda

Ini bukan istilah yang umum digunakan, tapi saya berasumsi itu berarti pemrograman menggunakan fungsi anonim atau pemrograman menggunakan fungsi tingkat tinggi.


Sedikit lebih banyak informasi tentang lambdas di C ++ 0x, motivasi mereka dan bagaimana mereka berhubungan dengan fungsi pointer (banyak dari ini mungkin merupakan pengulangan dari apa yang sudah Anda ketahui, tapi saya harap ini membantu menjelaskan motivasi lambdas dan bagaimana perbedaannya. dari pointer fungsi):

Pointer fungsi, yang sudah ada di C, cukup berguna untuk misal meneruskan fungsi perbandingan ke fungsi sortir. Namun ada batas kegunaannya:

Misalnya jika Anda ingin mengurutkan vektor vektor dengan ielemen th dari masing-masing vektor (di mana iparameter run-time), Anda tidak bisa menyelesaikan ini dengan pointer fungsi. Sebuah fungsi yang membandingkan dua vektor dengan ielemen th mereka , perlu mengambil tiga argumen ( idan dua vektor), tetapi fungsi pengurutan akan membutuhkan fungsi yang mengambil dua argumen. Apa yang kita perlukan adalah cara untuk menyediakan argumen ike fungsi sebelum meneruskannya ke fungsi sortir, tetapi kita tidak bisa melakukan ini dengan fungsi C biasa.

Untuk mengatasi ini, C ++ memperkenalkan konsep "objek fungsi" atau "functors". Functor pada dasarnya adalah objek yang memiliki operator()metode. Sekarang kita dapat mendefinisikan kelas CompareByIthElement, yang mengambil argumen isebagai argumen konstruktor dan kemudian mengambil dua vektor untuk dibandingkan sebagai argumen untuk operator()metode ini. Untuk mengurutkan vektor vektor dengan ielemen th kita sekarang dapat membuat CompareByIthElementobjek dengan isebagai argumen dan kemudian meneruskan objek itu ke fungsi pengurutan.

Karena objek fungsi hanya objek dan bukan fungsi teknis (meskipun mereka dimaksudkan untuk berperilaku seperti mereka), Anda tidak dapat membuat pointer fungsi menunjuk ke objek fungsi (Anda tentu saja dapat memiliki pointer ke objek fungsi, tetapi akan memiliki tipe like CompareByIthElement*dan karenanya tidak menjadi pointer fungsi).

Sebagian besar fungsi di pustaka standar C ++ yang mengambil fungsi sebagai argumen didefinisikan menggunakan templat sehingga berfungsi dengan pointer fungsi serta objek fungsi.

Sekarang untuk lambdas:

Mendefinisikan seluruh kelas untuk dibandingkan dengan ielemen th adalah sedikit bertele-tele jika Anda hanya akan menggunakannya sekali untuk mengurutkan vektor. Bahkan dalam kasus di mana Anda hanya memerlukan pointer fungsi, mendefinisikan fungsi bernama tidak optimal jika hanya digunakan sekali karena a) itu mencemari namespace dan b) fungsi biasanya akan sangat kecil dan tidak ada yang benar-benar alasan yang bagus untuk abstrak logika ke dalam fungsinya sendiri (selain itu Anda tidak dapat memiliki pointer fungsi tanpa mendefinisikan suatu fungsi).

Jadi untuk memperbaiki lambda ini diperkenalkan. Lambdas adalah objek fungsi, bukan pointer fungsi. Jika Anda menggunakan [x1, x2](y1,y2){bla}kode seperti lambda literal dihasilkan yang pada dasarnya melakukan hal berikut:

  1. Tentukan kelas yang memiliki dua variabel anggota ( x1dan x2) dan operator()dengan argumen ( y1dan y2) dan tubuh bla.
  2. Buat turunan dari kelas, pengaturan variabel anggota x1dan x2nilai-nilai variabel x1dan x2saat ini dalam ruang lingkup.

Jadi lambda berperilaku seperti objek fungsi, kecuali bahwa Anda tidak dapat mengakses kelas yang dihasilkan untuk mengimplementasikan lambda dengan cara apa pun selain menggunakan lambda. Akibatnya setiap fungsi yang menerima functors sebagai argumen (pada dasarnya berarti fungsi non-C di pustaka standar), akan menerima lambdas, tetapi fungsi apa pun yang hanya menerima pointer fungsi tidak akan.

sepp2k
sumber
Apakah fungsi anonim digunakan dengan pointer fungsi? Kalau tidak apa bedanya?
jokoon
1
@jokoon: Tidak, fungsi anonim tidak dapat diteruskan sebagai parameter ke fungsi yang hanya mengambil pointer fungsi. Namun sebagian besar fungsi yang mengambil fungsi sebagai argumen didefinisikan menggunakan templat sehingga mereka dapat mengambil segala jenis objek fungsi sebagai argumen, bukan hanya penunjuk fungsi. Artinya di sebagian besar tempat di mana Anda dapat menggunakan pointer fungsi ( std::sortmisalnya), Anda akan dapat menggunakan fungsi anonim. Namun ketika mendefinisikan fungsi yang harus mengambil fungsi anonim sebagai argumennya, Anda harus menggunakan templat atau menggunakan std::functionsebagai tipe argumen.
sepp2k
jadi pointer fungsi tidak boleh mengandung lambda ...
jokoon
1
+1 Penjelasan luar biasa - Saya juga tidak bisa mengetahuinya.
Michael K
2
Saya dengan Michael dalam hal ini. Ini sangat komprehensif. +1dari saya.
sbi
18

Pada dasarnya, fungsi lambda adalah fungsi yang Anda buat "on the fly". Dalam C ++ 1x mereka dapat digunakan untuk meningkatkan dukungannya untuk pemrograman fungsional:

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

Ini kira-kira akan menghasilkan kode yang mirip dengan yang ini:

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

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

Jika Anda some_functorhanya perlu untuk satu panggilan ini std::for_each(), maka fungsi lambda memiliki beberapa keunggulan daripada itu:

  • apa yang dilakukan dalam loop ditentukan tepat di mana fungsi looping dipanggil
  • itu membebaskan Anda dari menulis beberapa kode boiler-plate
  • tidak ada functor tergeletak di beberapa lingkup namespace yang membuat semua orang melihat kode bertanya-tanya apa yang dibutuhkan untuk itu
sbi
sumber
7

Fungsi lambda adalah nama lain untuk fungsi anonim - pada dasarnya fungsi tanpa nama.

Biasanya Anda menggunakan ini dalam bahasa di mana Anda hanya perlu menggunakan fungsi satu kali. Misalnya bukan

def add(a, b)
  return a+b

dan kemudian meneruskan fungsi itu ke fungsi lain seperti itu

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

Dengan lambda, Anda cukup melakukannya

reduce(lambda x, y: a+b, [5,3,2])
Martin Konecny
sumber