Чим відрізняється функція від лямбда?


54

Я трохи заплутаний у відношенні «функція» та «лямбда». Я бачив кілька прикладів, що показують, що ключове слово схеми lambdaпрацює дуже схоже на ключове слово JavaScript function, але я не знаю, як вони пов'язані.

Мені кажуть, що "функцію" та "метод" можна взаємозамінно використовувати, коли говорити про об'єкти в .net. Мені цікаво, чи означають "лямбда" та "функція" те саме. Цікаво, чи має «лямбда» якесь езотеричне значення, бачачи, що грецька літера лямбда (λ) з’являється у багатьох аватарах на цьому сайті. Щоб зробити речі ще більш заплутаними, в .net, функціональні частини C # відносять до функціональних виразів, переданих іншій функції, як "лямбда-вирази", тому слово справді здається повсюдно.

Я також невиразно знайомий з терміном "лямбда-числення".

Чим відрізняється функція від лямбда?


3
Nitpick - їх називають "лямбда-виразами", а не "лямбда-функціями", принаймні, що стосується документації на C # /. NET.
Одід

@ TWith2Sugars - Прочитайте повідомлення. Ваша відповідь низької якості, оскільки вона, як правило, є лише посиланням, тому перейшла до коментаря.
Oded

17
I wonder if 'lambda' has some esoteric meaning, seeing that the Greek letter lambda (λ) appears in so many avatars on this site.Можна сподіватися, що це буде посиланням на обчислення лямбда, але у мене є дивне відчуття, що Half Life винен у лямбда-аватарах.
янніс

3
Справедливо, ось посилання на StackOverflow відповідь: stackoverflow.com/questions/16501/what-is-a-lambda-function
TWith2Sugars

@ZaphodBeeblebrox: Я підозрюю, що ви правильні щодо впливу напівжиття. : /
FrustratedWithFormsDesigner

Відповіді:


44

Слово "лямбда" або "лямбда-вирази" найчастіше відноситься до анонімних функцій. Отже, в цьому сенсі лямбда - це певна функція, але не кожна функція - це лямбда (тобто названі функції зазвичай не називають лямбдами). Залежно від мови, анонімні функції часто реалізуються інакше, ніж названі функції (особливо на мовах, де анонімні функції закриваються, а названі функції не є), тому посилання на них з різними термінами може мати сенс.

Різниця між ключовим словом лямбда-схеми та ключовим ключовим словом функції Javascript полягає в тому, що останнє можна використовувати для створення як анонімних функцій, так і іменованих функцій, тоді як перші створюють лише анонімні функції (і ви б використовували їх defineдля створення названих функцій).

Обчислення лямбда - це мінімальна мова програмування / математична модель обчислення, яка використовує функції як єдину "структуру даних". У обчисленні lamdba лямбда-символ використовується для створення (анонімних) функцій. Звідси походить використання терміна "лямбда" в інших мовах.


1
Це надзвичайно грубо. Ви використовуєте define(або letкогось із його родичів чи внутрішнє визначення) для створення імен - ось і все. У defineфункціях немає нічого особливого .
Елі Барзілай

2
@EliBarzilay Ну, define дійсно мають спеціальну форму для визначення функцій (наприклад , ви можете написати (define (f x) (foo))замість (define f (lambda (x) (foo)))), але моя точка зору в тому , що ви не можете створити іменований функцію , використовуючи lambdaодин, тобто ви не можете написати що - щось на зразок (lambda f (x) (foo))визначити функцію з ім'ям fщо бере один аргумент, як ви можете, за допомогою functionключового слова Javascript .
sepp2k

1
defineмає це як синтаксичний цукор, тому це не так важливо, як його роль як інструмент зв’язування імен для всіх значень. Що стосується lambdaне створення імені самостійно: це важлива особливість, оскільки воно відокремлює надання імен від функціональних форм ... IMO JS робить правильно, дозволяючи розділити, а також приймає необов'язкове ім'я для тих мас, які будуть жахати ідея функції без імені. (І на щастя розмір цих мас загалом занепадає ...)
Елі Барзілай

18

Лямбда - це просто анонімна функція - функція без імені.


4
Примітка Досить: лямбда можуть містити стан (як у закритті), який вони перетинають із контексту, де вони оголошені.
Мартін Йорк

7
Так може бути названа функція, якщо мова дозволяє вам оголошувати вкладені функції.
cHao

4
Kudos для того, щоб перейти на вкладку огляду "постів низької якості" із схваленою відповіддю.
янніс

@ZaphodBeeblebrox - Не навмисно, можу вас запевнити.
Одід

Насправді, lambdaвираз у схемі - це як functionвираз без імені - але ніщо не заважає вам згодом дати ім’я. Наприклад var f = [function(x){return x;}][0]. Ви можете стверджувати, що саме значення функції не має імені, але це було б справедливо для всіх функцій ...
Елі Барзілай


8

У функції C # Anonymous - загальний термін, що включає в себе як лямбда-вирази, так і анонімні методи (анонімні методи - це делеговані екземпляри без фактичного оголошення способу).

Лямбда-вирази можуть бути розбиті на вираз лямбда та виклад лямбда

Вираз лямбда:

(int x, string y) => x == y.Length 

Заява lambda схожа на вираз lambda, за винятком того, що твердження (и) містяться в дужках:

(int x, string y) => {
         if (x == y.Length) {
             Console.WriteLine(y);
         }
}

Коли ми говоримо про лямбда-вирази в JavaScript, це в основному означає використання функції в якості аргументу при виклику до іншої функції.

var calculate = function(x, y, operation){
    return operation(x, y);
}

// we're passing anonymous function as a third argument
calculate(10, 15, function(x, y) {
    return x + y;
}); // 25

+1 Дуже багато людей згадували, що лямбди - це анонімні функції, але в цьому є більше. Тіло (права сторона) лямбда часто є виразом, а не блоком висловлювань. Тіло названої функції, яка є виразом, як правило, дозволено (або потрібно) у функціональних мовах, але не обов'язкових мовах.
Зантієр

4

TL; DR Як зазначали інші: позначення лямбда - це лише спосіб визначити функції, не змушуючи їх давати ім'я.

Довга версія

Я хотів би трохи детальніше розглянути цю тему, тому що я вважаю це дуже цікавим. Відмова: Я давно взяв курс на обчислення лямбда. Якщо хтось з кращими знаннями виявить у моїй відповіді неточності, не соромтесь допомогти мені покращити її.

Почнемо з виразів, наприклад, 1 + 2і x + 2. Літерали, такі як 1і 2називаються константами, оскільки вони прив'язані до певних фіксованих значень.

Такий ідентифікатор, як, наприклад, xназивається змінним, і для його оцінки потрібно спочатку прив'язати його до якогось значення. Отже, ви не можете оцінити x + 1, доки не знаєте, що xтаке.

Позначення лямбда надає схему прив'язки певних вхідних значень до змінних. Лямбда - вираз може бути сформовано шляхом додавання λx .в передній частині існуючого вираження, наприклад λx . x + 1. Мінлива xназивається вільним в x + 1і пов'язані вλx . x + 1

Як це допомагає в оцінці виразів? Якщо ви вводите значення для виразу лямбда, так

(λx . x + 1) 2

то ви можете оцінити весь вираз, замінивши (прив’язуючи) всі входи змінної xзначенням 2:

(λx . x + 1) 2
      2 + 1
      3

Отже, лямбда-позначення забезпечує загальний механізм прив'язки речей до змінних, які відображаються в блоці вираження / програми. Залежно від контексту, це створює надзвичайно різні поняття в мовах програмування:

  • У чисто функціональній мові, як Haskell, лямбда-вирази представляють функції в математичному сенсі: вхідне значення вводиться в тіло лямбда і виробляється вихідне значення.
  • У багатьох мовах (наприклад, JavaScript, Python, Scheme) оцінка тіла лямбда-виразу може мати побічні ефекти. У цьому випадку можна використовувати термін процедура для позначення різниці wrt чистих функцій.

Крім відмінностей, лямбда-позначення стосується визначення формальних параметрів та прив'язки їх до фактичних параметрів.

Наступним кроком є ​​надання імені функції / процедури. У кількох мовах функції є значеннями, як і будь-які інші, тому ви можете надати функцію імені наступним чином:

(define f (lambda (x) (+ x 1)))      ;; Scheme

f = \x -> x + 1                      -- Haskell

val f: (Int => Int) = x => x + 1     // Scala

var f = function(x) { return x + 1 } // JavaScript

f = lambda x: x + 1                  # Python

Як зазначав Елі Барзілай, це визначення просто пов'язує ім'я fзі значенням, яке, можливо, є функцією. Тож у цьому відношенні функції, числа, рядки, символи - це всі значення, які можна зв'язати з іменами однаково:

(define n 42)   ;; Scheme

n = 42          -- Haskell

val n: Int = 42 // Scala

var n = 42      // JavaScript

n = 42          # Python

У цих мовах ви також можете прив’язати функцію до імені, використовуючи більш звичне (але еквівалентне) позначення:

(define (f x) (+ x 1))         ;; Scheme

f x = x + 1                    -- Haskell

def f(x: Int): Int = x + 1     // Scala

function f(x) { return x + 1 } // JavaScript

def f(x): return x + 1         # Python

Деякі мови, наприклад, C, підтримують лише останні позначення для визначення (названих) функцій.

Закриття

Кінцеві зауваження щодо закриття . Розглянемо вираз x + y. Це містить дві вільні змінні. Якщо ви зв’яжете xза допомогою лямбда-позначення, ви отримаєте:

\x -> x + y

Це ще не є функцією, оскільки вона все ще містить вільну змінну y. Ви можете зробити з нього функцію, yтакож зв’язавши:

\x -> \y -> x + y

або

\x y -> x + y

що так само, як і +функція.

Але ви можете зв’язати, скажімо, yіншим способом (*):

incrementBy y = \x -> x + y

Результатом застосування функції incrementBy до числа є закриття, тобто функція / процедура, тіло якої містить вільну змінну (наприклад y), яка була прив'язана до значення із середовища, в якому було визначено закриття.

Так incrementBy 5само функція (закриття), що збільшує числа на 5.

ПРИМІТКА (*)

Я тут трохи обманюю:

incrementBy y = \x -> x + y

еквівалентно

incrementBy = \y -> \x -> x + y

тому механізм зв’язування однаковий. Інтуїтивно я вважаю, що закриття є частиною більш складного лямбдаського виразу. Коли це представлення створено, деякі з прив'язок материнського вираження вже встановлені, і закриття використовує їх пізніше, коли його оцінюють / викликають.


Я просто початковець, але я думаю, що це може бути трохи заплутаним, якщо ви намагаєтесь зрозуміти λ обчислення в математичному сенсі, оскільки те, що ви називаєте константи, називаються змінними і позначаються символами a, b, c ... Що ви змінні виклику були б невизначеною змінною x . З іншого боку, 1 - λ f x . f x , 2 - λ f x . f ( f x ) тощо.
jinawee

@jinawee: Я визнаю, я не шукав точного визначення. Я пам’ятаю, що використовував у логіці терміни змінні та константи. Там константа - це символ, який відображається у домені, тоді як змінна - символ, який можна кількісно оцінити. Але, знову ж таки, (1) це дуже давно, коли я взяв курс з логіки, і (2) лямбда-числення не потрібно слідувати 1-1 поняттям математичної логіки. Якщо ви вказуєте мені на посилання, я можу спробувати виправити свою термінологію.
Джорджіо

0

"Лямбда" в програмуванні зазвичай означає "лямбда-функція" (або також "лямбда-вираз", "лямбда-термін"). Коли функція - це названий блок коду, визначений до його використання, "лямбда-функція" - це блок коду (або виразу), визначений замість використання, який може бути використаний як громадянин першого класу на мові програмування.

У JavaScript ES6 (2015) є короткий синтаксис для визначення лямбдаз під назвою "Функції стрілки" . У C # такий синтаксис був введений у .NET 3.0 (близько 2006 року) .

У математиці поняття "функція" має кілька значень, де одне із значень стосується позначення функції (тобто, як записати її), тоді "лямбда-функція" (в обчисленні) - це особливий вид позначення функції. Для більш детального обговорення перевірте функції лямбда в мовах програмування .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.