Apa ini 'Lambda' yang terus dibicarakan semua orang?

93

Apa ini 'Lambda' yang terus dibicarakan semua orang? Banyak orang tampaknya menyukainya, tetapi yang dapat saya kumpulkan darinya hanyalah cara menjejalkan banyak baris kode ke dalam satu ekspresi.

Bisakah seseorang mencerahkan saya tentang nilai sebenarnya?

Josh Hunt
sumber
16
Dapatkah saya menunjukkan kepada penjawab bahwa penanya tidak menyebutkan .net
Pertanyaan retak. Terima kasih untuk bertanya.
Peanut
Lambdas termasuk dalam dunia pemrograman fungsional (pemrograman deklaratif).
RBT

Jawaban:

179

Berfungsi tanpa nama

Sederhananya, lambda adalah fungsi tanpa nama, atau fungsi anonim. Sepotong kecil kode yang dapat dieksekusi, yang dapat diedarkan seolah-olah itu adalah variabel. Dalam JavaScript:

function () {}; // very simple

Mari kita lihat sekarang beberapa kegunaan lambda ini.

Mengabstraksi kode boilerplate

Lambdas dapat digunakan untuk mengabstraksi kode boilerplate. Misalnya loop. Kami terbiasa menulis fordan whilemengulang sepanjang hari. Tetapi ini adalah kode yang tidak tertulis. Kita bisa mengekstrak kode di dalam loop, bagian terpenting dari loop, dan memisahkan sisanya:

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

dengan menggunakan forEachobjek array, menjadi:

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

Abstraksi di atas mungkin tidak begitu berguna, tetapi ada fungsi tingkat tinggi lainnya, seperti forEach, yang menjalankan tugas yang jauh lebih berguna. Contoh 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);

Penundaan eksekusi kode

Di beberapa lingkungan, di mana konsep acara tersedia, kita dapat menggunakan lambda untuk menanggapi peristiwa yang mungkin terjadi di beberapa titik waktu.

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

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

Ini bisa saja dilakukan dengan beberapa cara lain, tetapi itu agak bertele-tele. Misalnya, di Java ada Runnableantarmuka.

Pabrik fungsi

Sampai saat ini, kami hanya menggunakan lambda untuk sebagian besar kemampuan gula sintaksisnya. Tetapi ada situasi di mana lambda bisa jauh lebih berguna. Misalnya kita mungkin memiliki fungsi yang mengembalikan lambda. Katakanlah kita memiliki fungsi yang nilai kembaliannya ingin di-cache.

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];
};

Nanti, kita mungkin memperhatikan bahwa kita memiliki fungsi yang serupa:

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];
};

Jelas ada pola di sana, jadi mari kita abstraksi. Mari gunakan memoization .

/**
 * @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
});

Seperti yang Anda lihat, dengan menggunakan lambda, kami dapat memisahkan logika caching / memoization. Jika untuk contoh lain ada beberapa solusi, saya yakin masalah khusus ini hampir tidak dapat diselesaikan dengan menggunakan teknik lain. Kami berhasil mengekstrak beberapa kode boilerplate penting ke satu tempat. Belum lagi kami menyingkirkan usersdan photosvariabel global.

Melihat profil Anda, saya melihat bahwa Anda sebagian besar adalah pengguna Python. Untuk pola di atas, Python memiliki konsep dekorator. Ada banyak contoh di internet untuk dekorator memoisasi . Satu-satunya perbedaan adalah bahwa di Python Anda kemungkinan besar memiliki fungsi bersarang bernama di dalam fungsi dekorator itu. Alasannya karena Python hanya mendukung lambda ekspresi tunggal. Tapi konsepnya sama.

Sebagai contoh penggunaan lambda Python. Kode di atas tempat kami memfilter angka genap dapat direpresentasikan dengan Python seperti ini:

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

Bagaimanapun, lambda tidak begitu kuat tanpa penutupan. Penutupan inilah yang membuat konsep lambda begitu kuat. Dalam contoh memoization saya, saya telah menggunakan closures untuk membuat closure di sekitar storeparam. Dengan cara ini, saya memiliki akses ke param itu bahkan setelah memoizefungsi mengembalikan hasilnya (lambda).

Ionuț G. Stan
sumber
3
Wow, Anda meluangkan banyak waktu untuk itu.
mk12
4
@ Mk12, dalam penulisan sebenarnya jawabannya, tidak juga. Dalam mempelajari hal ini, ya, sudah lama sejak saya mulai :)
Ionuț G. Stan
Jawaban bagus tapi kurang info tentang "antarmuka fungsional" (dari sudut pandang Java).
djangofan
Apa itu operator "===" di "Abstraking boilerplate code"?
Jangan
@Jangan lihat stackoverflow.com/questions/359494/…
Ionuț G. Stan
19

Istilah "lambda" digunakan untuk merujuk ke fungsi anonim, biasanya penutupan . Mereka berguna karena memungkinkan Anda untuk menulis fungsi yang menggunakan fungsi lain tanpa membengkak kode Anda yang tidak perlu. Misalnya, di Ruby:

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

Ini akan membuat array yang berisi bilangan genap antara 1 dan 100. Kita tidak perlu menulis loop eksplisit - metode select mengambil fungsi yang digunakannya untuk menguji nilai, jadi yang kita butuhkan hanyalah logika kustom kita. Hal ini memungkinkan kami untuk menyesuaikan metode dengan praktis tanpa usaha atau pengeluaran tambahan. Pada dasarnya, kita dapat menyusun fungsi dari fungsi yang lebih kecil.

Itu hanya contoh mudah tentang apa yang bisa mereka lakukan. Kemampuan untuk menyampaikan fungsi sebagai data sangat kuat dan pemrogram bahasa fungsional secara rutin melakukan beberapa hal yang sangat menakjubkan dengannya.

Membuang
sumber
6
Mungkin Anda harus menambahkan bahwa hal di dalam pipa adalah parameternya. Saya salah satu dari orang-orang ini yang kesulitan membaca ruby.
Skurmedel
Ini jawaban yang bagus. Satu-satunya alasan Ionut mendapatkan suara saya adalah karena dia memberi tahu kami mengapa kami harus peduli (secara rinci) tentang lambda.
Frank Shearar
Saya tidak setuju bahwa lambda biasanya penutupan.
jwg
6

"Lambda" mungkin terlalu sedikit. Lihatlah kalkulus Lambda . Ini berguna dalam pemrograman fungsional.

Dan pemrograman fungsional adalah paradigma pemrograman lain (seperti prosedural, atau berorientasi objek).

HAI
sumber
5
Kemudian orang-orang berbicara tentang "Lambda", kemungkinan besar mereka berbicara tentang fungsi anonim, penunjuk fungsi, penutupan atau yang serupa. Hampir tidak pernah mengacu pada kalkulus lambda yang sebenarnya.
J-16 SDiZ
Senang Anda menyebutkan kalkulus Lambda.! +1.
NSP
5

Lambdas di. NET cukup sering disebut sebagai "gula sintaksis". Mereka tidak secara langsung mempengaruhi fungsionalitas namun mereka membuat bahasanya lebih mudah untuk digunakan orang.

Ketika Anda telah memahami kekuatan penggunaannya, saya yakin Anda akan menemukan bahwa Anda akan menulis lebih sedikit kode dibandingkan dengan cara gaya lama menggunakan metode delegasi / anonim.

kotak merah
sumber
1
Saya tidak berpikir ada orang yang menyebutkan .NET, jadi OP mungkin lebih baik dengan jawaban yang lebih umum.
molf
2
itulah mengapa saya mengklarifikasi dengan menjawab tentang .net. Jika orang lain senang dengan penerapan bahasa mereka, maka q & a akan membantu banyak orang apa pun pilihan bahasa mereka.
redsquare
Jawaban ini terbaca seperti Anda telah mendengar sesuatu tentang lambda, tetapi Anda sendiri belum memahaminya.
jwg
2

Jurnal Dr Dobbs memiliki artikel bermanfaat yang memperkenalkan ekspresi lambda (dalam konteks C ++ tetapi saya pikir Anda dapat menerapkan prinsip-prinsip tersebut ke bahasa apa pun).

Seperti yang dikatakan artikel: "Ekspresi lambda adalah ekspresi yang sangat kompak yang tidak memerlukan definisi kelas / fungsi terpisah."

Jadi menggunakan contoh daftar 1 & 2 dari DDJ daripada menulis:

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

Yang membutuhkan definisi kelas terpisah seperti:

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);
}

Menggunakan pustaka Boost lambda, ini bisa menjadi:

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

Yang membuat definisi tetap sejalan.

Artikel tersebut juga menjelaskan beberapa aplikasi lagi dari ekspresi lambda.

Saya pikir poin kunci dalam artikel DDJ adalah "Biasanya, ekspresi lambda digunakan ketika fungsi kecil dan tidak terlalu kompleks diperlukan di situs panggilan. Jika fungsinya tidak sepele, Anda tidak akan menginginkan ekspresi lambda tetapi fungsi normal atau objek fungsi. "

danio
sumber
2

Jika Anda pernah bekerja dengan fungsi / metode yang menggunakan penunjuk fungsi, delegasi, strategi atau pola pengamat / penanganan peristiwa, dan berpikir "Saya menulis seluruh fungsi ini hanya untuk menggunakannya sekali saja - untuk meneruskannya ke metode ini ; Saya berharap saya bisa menulisnya di tempat, daripada mengacaukan kode saya "- di situlah Anda dapat menggunakan fungsi Lambda. Bahasa yang mendukung konstruksi ini juga biasanya sangat memanfaatkan konsep meneruskan fungsi sebagai parameter, terutama dalam hal bekerja dengan daftar (fungsi kelas satu dan fungsi urutan yang lebih tinggi). Hal ini terutama berlaku untuk bahasa fungsional, yang mengandalkan komposisi fungsi daripada modifikasi memori untuk komputasi. Dalam beberapa kasus (dalam bahasa seperti Python),

TR
sumber
2

Kata 'lambda' qua adalah terminologi dari zaman ketika jenis ilmu komputer lebih mungkin untuk dilatih dalam matematika atau logika daripada memiliki gelar ilmu komputer. Beberapa dari mereka membuat paradigma yang disebut 'pemrograman fungsional', sangat berbeda dari imperatif dan juga cukup kuat. AFAIK itulah lingkungan tempat istilah itu mulai digunakan.

Ahli matematika dan ahli logika terbiasa menggunakan kata-kata aneh.

'lambda' terdengar sangat esoteris - seolah-olah itu adalah hal yang sangat aneh dan istimewa. Sungguh, jika Anda menulis JavaScript untuk aplikasi browser web dan menggunakan idiom "var foo = function () {...}", Anda telah menggunakan fungsi lambda selama ini.

Peter Mortensen
sumber
1

Ekspresi lambda adalah bentuk fungsi yang sederhana. Idenya adalah sesuatu dari bentuk di sebelah kiri (setara dengan parameter) menjadi sesuatu dari bentuk di sebelah kanan (setara dengan tubuh).

misalnya, dalam c sharp:

x => x * x

adalah lambda untuk mengkuadratkan nilai. Sesuatu dari bentuknya

x

menjadi sesuatu dari bentuk

x * x
Dave Cousineau
sumber
0

"Ekspresi lambda adalah fungsi anonim yang bisa berisi ekspresi dan pernyataan, dan bisa digunakan untuk membuat delegasi atau tipe pohon ekspresi.

Semua ekspresi lambda menggunakan operator lambda =>, yang dibaca sebagai "pergi ke". Sisi kiri operator lambda menentukan parameter input (jika ada) dan sisi kanan memegang blok ekspresi atau pernyataan. Ekspresi lambda x => x * x dibaca "x pergi ke x kali x."

dari MSDN

Fermin
sumber
4
Ya, Microsoft membuat semua orang berpikir bahwa mereka yang menemukannya. Ekspresi Lambda mendahului Microsoft. Ini adalah istilah matematika yang telah diterapkan pada beberapa bahasa pemrograman. (Yang mungkin, karena matematika dapat dianggap sebagai bahasa komputer dengan sendirinya.)
Wim ten Brink
4
Perhatikan bahwa ini khusus untuk implementasi .Net Microsoft. Ini bukan penyimpangan besar dari gagasan umum lambda, tapi menurut saya fungsionalitas yang diterapkan di Lisp lebih "standar".
Chuck
2
Jawaban itu tidak menjelaskan sama sekali apa itu Lambda (membutuhkan definisi dari fungsi anonim, delegasi, tipe pohon ekspresi) dan tentunya tidak menjelaskan apa nilainya.
danio
0

Untuk penjelasan lengkap tentang ekspresi Lambda, lihat juga Wikipedia . (Gulir ke bawah ke bagian kalkulus dan bahasa pemrograman Lambda.) Ekspresi lambda bukanlah hal baru dan mereka bukan hanya bagian dari C # tetapi sesuatu yang telah diperkenalkan ke komputasi hampir 80 tahun yang lalu! Ekspresi lambda adalah dasar untuk pemrograman fungsional.

Itu nilainya? Nah, mengingat itu sebenarnya cukup tua, saya akan mengatakan: sangat berharga bagi siapa pun yang melakukan perhitungan.

Wim ten Brink
sumber
0

Jika Anda menggunakan Java, Anda telah mendengar banyak tentang lambda atau closure dalam beberapa bulan terakhir, karena ada usulan yang berbeda untuk menambahkan fitur ini ke Java 7. Namun, saya rasa comitee membatalkannya. Salah satu proposal berasal dari Neal Gafter dan dijelaskan dengan sangat rinci di sini: javac.info . Ini membantu saya memahami kasus penggunaan dan keuntungan (terutama di kelas dalam)

Tim Büthe
sumber
0

Anda akan menemukan semua yang perlu Anda ketahui (tentang C # Lambdas) untuk memulai di sini:
Ekspresi Lambda

Robert Koritnik
sumber
-1

Ya, ini hanyalah cara menjejalkan banyak baris kode menjadi satu ekspresi. Tetapi menjadi penjejalan yang efisien, ini memungkinkan beberapa cara baru untuk menyusun program Anda.

Seringkali seseorang akan menghindari penulisan delegasi atau callback dan kembali ke gaya prosedural hanya karena terlalu merepotkan untuk mendeklarasikan fungsi atau kelas baru untuk satu ekspresi.

Ekspresi lambda membuatnya bermanfaat untuk menggunakan callback bahkan untuk tugas-tugas terkecil, yang mungkin membuat kode lebih jelas. Mungkin tidak.

ima
sumber