Что это за «лямбда», о которой все говорят? Кажется, многим это нравится, но все, что я могу извлечь из этого, - это просто способ втиснуть множество строк кода в одно выражение.
Может ли кто-нибудь объяснить мне его истинную ценность?
Лямбды относятся к миру функционального программирования (декларативного программирования).
RBT
Ответы:
179
Функции без имени
Проще говоря, лямбда - это функция без имени или анонимная функция. Небольшой фрагмент исполняемого кода, который можно передавать, как если бы это была переменная. В JavaScript:
function () {}; // very simple
Давайте теперь посмотрим, как использовать эти лямбды.
Абстрагирование шаблонного кода
Лямбды можно использовать для абстрагирования шаблонного кода. Например петли. Мы привыкли писатьfor и whileзацикливаться целый день. Но это код, который не пишется. Мы могли бы извлечь код внутри цикла, наиболее важной части цикла, и абстрагироваться от остального:
for (var i=0; i<array.length; i++) {
// do what something useful with array[i]
}
array.forEach(function (element, index) {
// do something useful with element// element is the equivalent of array[i] from above
});
Вышеупомянутая абстракция может быть не такой полезной, но есть и другие функции более высокого порядка, например forEach , которые выполняют гораздо более полезные задачи. Например filter:
var numbers = [1, 2, 3, 4];
var even = [];
// keep all even numbers from above arrayfor (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);
Задержка выполнения кода
В некоторых средах, в которых доступна концепция события, мы могли бы использовать лямбда-выражения для ответа на события, которые могут произойти в определенный момент времени.
window.onload = function () {
alert("Loaded");
};
window.setTimeout(function () {
alert("Code executed after 2 seconds.");
}, 2000);
Это можно было сделать и другими способами, но они довольно многословны. Например, в Java естьRunnable интерфейс.
Фабрики функций
До этого момента мы использовали лямбда-выражения в основном из-за его синтаксических возможностей сахара. Но бывают ситуации, когда лямбды могут быть намного полезнее. Например, у нас могут быть функции, возвращающие лямбды. Допустим, у нас есть функция, возвращаемые значения которой должны быть кэшированы.
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];
};
Позже мы можем заметить, что у нас есть похожая функция:
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];
};
Здесь явно есть шаблон, поэтому давайте абстрагируемся от него. Воспользуемся мемоизацией .
/**
* @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 lambdareturnfunction (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
});
Как видите, с помощью лямбда-выражений мы смогли абстрагироваться от логики кеширования / запоминания. Если бы для другого примера были какие-то обходные пути, я считаю, что эту конкретную проблему вряд ли можно решить с помощью других методов. Нам удалось собрать важный шаблонный код в одном месте. Не говоря уже о том, что мы избавились отusers и photosглобальных переменных.
Глядя на ваш профиль, я вижу, что вы в основном пользователь Python. Для вышеприведенного шаблона в Python есть концепция декораторов. В сети есть множество примеров для декораторов мемоизации . Единственная разница в том, что в Python у вас, скорее всего, есть именованный вложенная функция внутри этой функции-декоратора. Причина в том, что Python поддерживает только лямбды с одним выражением. Но концепция та же.
В качестве примера использования лямбда-выражения Python. Приведенный выше код, в котором мы отфильтровали четные числа, может быть представлен в Python следующим образом:
filter(lambda x: x % 2 == 0, [1, 2, 3, 4])
В любом случае, лямбды не так эффективны без замыканий. Замыкания - вот что делает концепцию лямбда настолько сильной. В моем примере с мемоизацией я использовал замыкания, чтобы создать замыкание вокруг storeпараметра. Таким образом, у меня есть доступ к этому параметру даже после того, как memoizeфункция вернула свой результат (лямбда).
Термин «лямбда» используется для обозначения анонимной функции, обычно замыкания . Они полезны, потому что позволяют писать функции, использующие другие функции, без ненужного раздувания кода. Например, в Ruby:
(1..100).select {|num| num % 2 == 0}
Это создаст массив, содержащий четные числа от 1 до 100. Нам не нужно писать явный цикл - метод select принимает функцию, которую он использует для проверки значений, поэтому все, что нам нужно, это наша настраиваемая логика. Это позволяет нам значительно настроить метод практически без усилий и накладных расходов. По сути, мы можем составлять функции из более мелких функций.
Это простой пример того, что они могут сделать. Возможность передавать функции в виде данных - это действительно мощный инструмент, и программисты на функциональных языках обычно делают с ними действительно удивительные вещи.
Может быть, вам стоит добавить, что в трубках есть параметр. Я один из тех, кто плохо читает рубин.
Skurmedel 06
Это хороший ответ. Единственная причина, по которой Ионут получил мой голос, заключается в том, что он рассказал нам, почему мы должны заботиться (подробно) о лямбдах.
Frank Shearar
Я бы не согласился, что лямбды обычно закрываются.
jwg 08
6
«Лямбда» может быть слишком мало. Взгляните на лямбда-исчисление . Это полезно в функциональном программировании.
А функциональное программирование - это еще одна парадигма программирования (например, процедурная или объектно-ориентированная).
Затем люди говорят о «лямбде», скорее всего, они имеют в виду анонимную функцию, указатели функций, замыкание или что-то подобное. Практически никогда не упоминайте о реальном исчислении лямбда.
J-16 SDiZ 06
Рад, что вы упомянули лямбда-исчисление! +1.
RBT
5
Лямбды в .NET довольно часто называют «синтаксическим сахаром». Они не влияют напрямую на функциональность, но упрощают использование языка людьми.
Когда вы поймете силу их использования, я уверен, вы обнаружите, что будете писать меньше кода по сравнению со старым способом с использованием делегатов / анонимных методов.
Я не думаю, что кто-то упоминал .NET, поэтому OP, вероятно, лучше с более общим ответом.
molf 06
2
вот почему я пояснил, отвечая на вопрос о .net. Если другие будут щебетать с их реализацией языка, тогда вопросы и ответы помогут многим людям, независимо от того, какой язык они выберут.
redsquare 06
Эти ответы выглядят так, как будто вы что-то слышали о лямбдах, но сами еще не понимаете их.
В статье также объясняются некоторые другие применения лямбда-выражений.
Я думаю, что ключевой момент в статье DDJ : «Обычно лямбда-выражения используются, когда на месте вызова требуются небольшие и не слишком сложные функции. Если бы функция была нетривиальной, вам бы не понадобилось лямбда-выражение, а обычная функция или функциональный объект ".
Если вы когда-либо работали с функциями / методами, которые используют указатели на функции, делегаты, стратегию или шаблон наблюдателя / обработку событий, и думали про себя: «Я пишу всю эту функцию, чтобы использовать ее только один раз - чтобы передать ее этому методу. ; Хотел бы я просто написать это на месте, а не загромождать свой код »- вот где вы можете использовать лямбда-функции. Языки, поддерживающие эту конструкцию, также обычно в значительной степени используют преимущества концепции передачи функций в качестве параметров, особенно в отношении работы со списками (функции первого класса и функции более высокого порядка). Это особенно верно для функциональных языков, которые для вычислений полагаются на композицию функций, а не на изменение памяти. В некоторых случаях (в таких языках, как Python),
«лямбда» как слово - это терминология тех времен, когда люди, занимающиеся информатикой, могли обучаться математике или логике с большей вероятностью, чем иметь степень в области компьютерных наук. Некоторые из них придумали парадигму под названием «функциональное программирование», весьма отличную от императивного и весьма мощную. Насколько мне известно , это среда, в которой термин вошел в употребление.
Математики и логики склонны использовать странные слова.
«лямбда» звучит действительно эзотерически - как будто это очень странная и особенная вещь. На самом деле, если вы пишете JavaScript для приложения веб-браузера и используете идиому «var foo = function () {...}», вы всегда использовали лямбда-функции.
Лямбда-выражение - это простая форма функции. Идея состоит в том, что что-то от формы слева (эквивалентное параметрам) становится чем-то вроде формы справа (эквивалентным телу).
например, до-диез:
x => x * x
лямбда для вычисления квадрата значения. Что-то в форме
«Лямбда-выражение - это анонимная функция, которая может содержать выражения и инструкции, и может использоваться для создания делегатов или типов дерева выражений.
Во всех лямбда-выражениях используется лямбда-оператор =>, который читается как «переходит к». Левая часть лямбда-оператора определяет входные параметры (если есть), а правая часть содержит блок выражения или оператора. Лямбда-выражение x => x * x читается как «x переходит в x, умноженное на x».
Да, Microsoft заставляет всех думать, что они это изобрели. Однако лямбда-выражения появились раньше Microsoft. Это математический термин, который применялся к нескольким языкам программирования. (Что возможно, поскольку математика сама по себе может считаться компьютерным языком.)
Вим тен Бринк
4
Обратите внимание, что это характерно для реализации Microsoft .Net. Это не большое отклонение от общей идеи лямбда, но я думаю, что функциональность, реализованная в Лиспе, является более «стандартной».
Чак
2
Этот ответ вообще не объясняет, что такое лямбда (требуются определения анонимной функции, делегата, типа дерева выражения) и, конечно, не объясняет, каково его значение.
danio 06
0
Полное объяснение лямбда-выражений можно найти в Википедии . (Прокрутите вниз до раздела « Лямбда-исчисление и языки программирования» .) Лямбда-выражения не новы, и они не просто часть C #, а то, что было введено в вычисления почти 80 лет назад! Лямбда-выражения являются основой функционального программирования.
Это ценность? Что ж, учитывая, что он на самом деле довольно старый, я бы сказал: очень ценный для любого, кто делает вычисления.
Если вы занимаетесь Java, вы много слышали о лямбдах или замыканиях за последние пару месяцев, потому что были разные предложения по добавлению этой функции в Java 7. однако, я думаю, что участник отказался от нее. Одно из предложений сделано Нилом Гафтером и подробно описано здесь: javac.info . Это помогло мне понять варианты использования и преимущества (особенно по сравнению с внутренними классами).
Да, это просто способ втиснуть множество строк кода в одно выражение. Но, будучи настолько эффективным, он позволяет по-новому структурировать вашу программу.
Часто можно избежать написания делегатов или обратных вызовов и вернуться к процедурному стилю просто потому, что объявлять новые функции или классы для одного выражения слишком много.
Лямбда-выражения делают целесообразным использование обратных вызовов даже для самых крошечных задач, что может сделать код более понятным. Может не.
Ответы:
Функции без имени
Проще говоря, лямбда - это функция без имени или анонимная функция. Небольшой фрагмент исполняемого кода, который можно передавать, как если бы это была переменная. В JavaScript:
function () {}; // very simple
Давайте теперь посмотрим, как использовать эти лямбды.
Абстрагирование шаблонного кода
Лямбды можно использовать для абстрагирования шаблонного кода. Например петли. Мы привыкли писать
for
иwhile
зацикливаться целый день. Но это код, который не пишется. Мы могли бы извлечь код внутри цикла, наиболее важной части цикла, и абстрагироваться от остального:for (var i=0; i<array.length; i++) { // do what something useful with array[i] }
используя
forEach
объектов массива становится:array.forEach(function (element, index) { // do something useful with element // element is the equivalent of array[i] from above });
Вышеупомянутая абстракция может быть не такой полезной, но есть и другие функции более высокого порядка, например
forEach
, которые выполняют гораздо более полезные задачи. Например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);
Задержка выполнения кода
В некоторых средах, в которых доступна концепция события, мы могли бы использовать лямбда-выражения для ответа на события, которые могут произойти в определенный момент времени.
window.onload = function () { alert("Loaded"); }; window.setTimeout(function () { alert("Code executed after 2 seconds."); }, 2000);
Это можно было сделать и другими способами, но они довольно многословны. Например, в Java есть
Runnable
интерфейс.Фабрики функций
До этого момента мы использовали лямбда-выражения в основном из-за его синтаксических возможностей сахара. Но бывают ситуации, когда лямбды могут быть намного полезнее. Например, у нас могут быть функции, возвращающие лямбды. Допустим, у нас есть функция, возвращаемые значения которой должны быть кэшированы.
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]; };
Позже мы можем заметить, что у нас есть похожая функция:
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]; };
Здесь явно есть шаблон, поэтому давайте абстрагируемся от него. Воспользуемся мемоизацией .
/** * @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 });
Как видите, с помощью лямбда-выражений мы смогли абстрагироваться от логики кеширования / запоминания. Если бы для другого примера были какие-то обходные пути, я считаю, что эту конкретную проблему вряд ли можно решить с помощью других методов. Нам удалось собрать важный шаблонный код в одном месте. Не говоря уже о том, что мы избавились от
users
иphotos
глобальных переменных.Глядя на ваш профиль, я вижу, что вы в основном пользователь Python. Для вышеприведенного шаблона в Python есть концепция декораторов. В сети есть множество примеров для декораторов мемоизации . Единственная разница в том, что в Python у вас, скорее всего, есть именованный вложенная функция внутри этой функции-декоратора. Причина в том, что Python поддерживает только лямбды с одним выражением. Но концепция та же.
В качестве примера использования лямбда-выражения Python. Приведенный выше код, в котором мы отфильтровали четные числа, может быть представлен в Python следующим образом:
filter(lambda x: x % 2 == 0, [1, 2, 3, 4])
В любом случае, лямбды не так эффективны без замыканий. Замыкания - вот что делает концепцию лямбда настолько сильной. В моем примере с мемоизацией я использовал замыкания, чтобы создать замыкание вокруг
store
параметра. Таким образом, у меня есть доступ к этому параметру даже после того, какmemoize
функция вернула свой результат (лямбда).источник
Термин «лямбда» используется для обозначения анонимной функции, обычно замыкания . Они полезны, потому что позволяют писать функции, использующие другие функции, без ненужного раздувания кода. Например, в Ruby:
Это создаст массив, содержащий четные числа от 1 до 100. Нам не нужно писать явный цикл - метод select принимает функцию, которую он использует для проверки значений, поэтому все, что нам нужно, это наша настраиваемая логика. Это позволяет нам значительно настроить метод практически без усилий и накладных расходов. По сути, мы можем составлять функции из более мелких функций.
Это простой пример того, что они могут сделать. Возможность передавать функции в виде данных - это действительно мощный инструмент, и программисты на функциональных языках обычно делают с ними действительно удивительные вещи.
источник
«Лямбда» может быть слишком мало. Взгляните на лямбда-исчисление . Это полезно в функциональном программировании.
А функциональное программирование - это еще одна парадигма программирования (например, процедурная или объектно-ориентированная).
источник
Лямбды в .NET довольно часто называют «синтаксическим сахаром». Они не влияют напрямую на функциональность, но упрощают использование языка людьми.
Когда вы поймете силу их использования, я уверен, вы обнаружите, что будете писать меньше кода по сравнению со старым способом с использованием делегатов / анонимных методов.
источник
В Dr Dobbs Journal есть полезная статья о лямбда-выражениях. (в контексте C ++, но я думаю, что вы можете применить эти принципы к любому языку).
Как говорится в статье: «Лямбда-выражение - это очень компактное выражение, которое не требует отдельного определения класса / функции».
Поэтому, используя примеры листингов 1 и 2 из DDJ вместо записи:
Для этого требуется отдельное определение класса, например:
Используя лямбда-библиотеку Boost, это может стать:
Что сохраняет определение встроенным.
В статье также объясняются некоторые другие применения лямбда-выражений.
Я думаю, что ключевой момент в статье DDJ : «Обычно лямбда-выражения используются, когда на месте вызова требуются небольшие и не слишком сложные функции. Если бы функция была нетривиальной, вам бы не понадобилось лямбда-выражение, а обычная функция или функциональный объект ".
источник
Если вы когда-либо работали с функциями / методами, которые используют указатели на функции, делегаты, стратегию или шаблон наблюдателя / обработку событий, и думали про себя: «Я пишу всю эту функцию, чтобы использовать ее только один раз - чтобы передать ее этому методу. ; Хотел бы я просто написать это на месте, а не загромождать свой код »- вот где вы можете использовать лямбда-функции. Языки, поддерживающие эту конструкцию, также обычно в значительной степени используют преимущества концепции передачи функций в качестве параметров, особенно в отношении работы со списками (функции первого класса и функции более высокого порядка). Это особенно верно для функциональных языков, которые для вычислений полагаются на композицию функций, а не на изменение памяти. В некоторых случаях (в таких языках, как Python),
источник
«лямбда» как слово - это терминология тех времен, когда люди, занимающиеся информатикой, могли обучаться математике или логике с большей вероятностью, чем иметь степень в области компьютерных наук. Некоторые из них придумали парадигму под названием «функциональное программирование», весьма отличную от императивного и весьма мощную. Насколько мне известно , это среда, в которой термин вошел в употребление.
Математики и логики склонны использовать странные слова.
«лямбда» звучит действительно эзотерически - как будто это очень странная и особенная вещь. На самом деле, если вы пишете JavaScript для приложения веб-браузера и используете идиому «var foo = function () {...}», вы всегда использовали лямбда-функции.
источник
Лямбда-выражение - это простая форма функции. Идея состоит в том, что что-то от формы слева (эквивалентное параметрам) становится чем-то вроде формы справа (эквивалентным телу).
например, до-диез:
лямбда для вычисления квадрата значения. Что-то в форме
становится чем-то вроде
источник
«Лямбда-выражение - это анонимная функция, которая может содержать выражения и инструкции, и может использоваться для создания делегатов или типов дерева выражений.
Во всех лямбда-выражениях используется лямбда-оператор =>, который читается как «переходит к». Левая часть лямбда-оператора определяет входные параметры (если есть), а правая часть содержит блок выражения или оператора. Лямбда-выражение x => x * x читается как «x переходит в x, умноженное на x».
из MSDN
источник
Полное объяснение лямбда-выражений можно найти в Википедии . (Прокрутите вниз до раздела « Лямбда-исчисление и языки программирования» .) Лямбда-выражения не новы, и они не просто часть C #, а то, что было введено в вычисления почти 80 лет назад! Лямбда-выражения являются основой функционального программирования.
Это ценность? Что ж, учитывая, что он на самом деле довольно старый, я бы сказал: очень ценный для любого, кто делает вычисления.
источник
Если вы занимаетесь Java, вы много слышали о лямбдах или замыканиях за последние пару месяцев, потому что были разные предложения по добавлению этой функции в Java 7. однако, я думаю, что участник отказался от нее. Одно из предложений сделано Нилом Гафтером и подробно описано здесь: javac.info . Это помогло мне понять варианты использования и преимущества (особенно по сравнению с внутренними классами).
источник
Вы найдете все, что вам нужно знать (о C # Lambdas) для начала здесь:
Lambda-выражения
источник
Для java-лямбд это может быть хорошей отправной точкой:
http://rodrigouchoa.wordpress.com/2014/09/10/java-8-lambda-expressions-tutorial/
источник
Да, это просто способ втиснуть множество строк кода в одно выражение. Но, будучи настолько эффективным, он позволяет по-новому структурировать вашу программу.
Часто можно избежать написания делегатов или обратных вызовов и вернуться к процедурному стилю просто потому, что объявлять новые функции или классы для одного выражения слишком много.
Лямбда-выражения делают целесообразным использование обратных вызовов даже для самых крошечных задач, что может сделать код более понятным. Может не.
источник