О чем говорит этот "Лямбда"?

Что это за "Лямбда", о котором все говорят? Многие люди, похоже, любят его, но все, что я могу собрать, это просто способ кодирования множества строк кода в одно выражение.

Может кто-нибудь, пожалуйста, просветит меня по его истинному значению?

Ответ 1

Функции без имени

Проще говоря, лямбда - это функция без имени или анонимная функция. Небольшой фрагмент исполняемого кода, который можно передавать, как если бы он был переменной. В JavaScript:

function () {}; // very simple

Посмотрим теперь на некоторые виды использования этих лямбдов.

Тестирование шаблона кода

Lambdas может использоваться для абстрагирования кода шаблона. Например, петли. Мы привыкли писать циклы 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);

Задержка выполнения кода

В некоторых средах, в которых доступна концепция события, мы можем использовать lambdas для реагирования на события, которые могут произойти в некоторый момент времени.

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

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

Это могло быть сделано другими способами, но они довольно многословны. Например, в Java есть интерфейс Runnable.

Заводы функций

До этого момента мы использовали только lambdas для синтаксического сахара. Но есть ситуации, когда лямбды могут быть намного полезнее. Например, у нас могут быть функции, возвращающие лямбда. Пусть говорят, что у нас есть функция, в которой мы хотим, чтобы ее возвращаемые значения были кэшированы.

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

Там явно есть образец, поэтому пусть отвлечет его. Позвольте использовать memoization.

/**
 * @param {Array}     store Data structure in which we cache lambda 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
});

Как вы можете видеть, с помощью lambdas нам удалось абстрагироваться от логики кэширования /memoization. Если для другого примера были некоторые обходные пути, я считаю, что эта конкретная проблема вряд ли решается с использованием других методов. Нам удалось извлечь какой-то важный шаблонный код в одно место. Не говоря уже о том, что мы избавились от глобальных переменных users и photos.

Глядя на ваш профиль, я вижу, что вы в основном пользователь Python. Для вышеуказанного шаблона Python имеет концепцию декораторов. Есть много пример в сетке для memoization decorators. Единственное отличие состоит в том, что в Python у вас, скорее всего, есть встроенная функция с именем внутри этой функции декоратора. Причина в том, что Python поддерживает только lambdas с одним выражением. Но понятие одно и то же.

В качестве примера использования лямбды Python. Вышеприведенный код, в котором мы отфильтровали четные числа, может быть представлен в Python следующим образом:

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

Во всяком случае, лямбды не так сильны без закрытия. Закрытие - это то, что делает концепцию лямбда настолько мощной. В моем примере memoization я использовал замыкания для создания замыкания вокруг параметра store. Таким образом, у меня есть доступ к этому параметру, даже после того, как функция memoize вернула свой результат (лямбда).

Ответ 2

Термин "лямбда" используется для обозначения анонимной функции, обычно closure. Они полезны, потому что они позволяют вам писать функции, которые используют другие функции, без лишнего раздувания вашего кода. Например, в Ruby:

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

Это создаст массив, содержащий четные числа от 1 до 100. Нам не нужно выписывать явный цикл - метод select использует функцию, которую он использует для проверки значений, поэтому все, что нам нужно, это наш обычай логика. Это позволяет нам значительно настраивать метод практически без усилий или накладных расходов. В принципе, мы можем создавать функции из меньших функций.

Это просто легкий пример того, что они могут сделать. Возможность передавать функции в виде данных - действительно мощные и функциональные программисты языка, как правило, делают с ними действительно потрясающие вещи.

Ответ 3

"Лямбда", может быть, слишком мало. Взгляните на Lambda calculus. Он полезен при функциональном программировании.

И функциональное программирование - еще одна парадигма программирования (например, процедурная или объектно-ориентированная).

Ответ 4

Lambdas в .NET довольно часто упоминается как "синтаксический сахар". Они не оказывают непосредственного влияния на функциональность, однако они облегчают использование языка для людей.

Когда вы поняли силу их использования, я уверен, вы обнаружите, что вы будете писать меньше кода по сравнению со старым стилем с использованием делегатов/анонимных методов.

Ответ 5

Dr Dobbs Journal содержит полезную статью, в которой представлены лямбда-выражения (в контексте С++, но я думаю, что вы можете применить принципы к любому языку).

Как говорится в статье: "Лямбда-выражение представляет собой очень компактное выражение, которое не требует отдельного определения класса/функции".

Итак, используя примеры списков 1 и 2 из DDJ вместо записи:

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

Для этого требуется отдельное определение класса, например:

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

Используя Boost lambda library, это может стать:

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

Сохраняет определение в строке.

В статье также объясняется еще несколько приложений лямбда-выражений.

Я думаю, что ключевой момент в статье DDJ:" Обычно лямбда-выражения используются, когда небольшие и не слишком сложные функции необходимы при Если функция была нетривиальной, вам не нужно было бы лямбда-выражения, кроме нормальной функции или объекта функции.

Ответ 6

Если вы когда-либо работали с функциями/методами, использующими указатели функций, делегаты, стратегию или шаблоны наблюдателей/обработку событий, и подумали о себе: "Я пишу эту целую функцию только для ее использования только один раз - для ее прохождения к этому методу, мне хотелось бы просто написать его на месте, а не загромождать мой код", - где вы можете использовать функции лямбда. Языки, которые поддерживают эту конструкцию, обычно обычно используют концепцию передачи функций в качестве параметров, особенно в отношении работы со списками (функции первого класса и функции более высокого порядка). Это особенно справедливо для функциональных языков, которые полагаются на функциональную композицию, а не на модификацию памяти для вычислений. В некоторых случаях (в таких языках, как Python) использование лямбда-функций со списками также считается более читаемым, чем эквивалентный цикл foreach.

Ответ 7

'lambda' qua word - это терминология с тех пор, когда типы компьютерной науки были, скорее всего, подготовлены по математике или логике, а не по степени информатики. Некоторые из них подготовили парадигму под названием "функциональное программирование", совершенно отличную от императивной и достаточно сильной. AFAIK, который является средой, в которой этот термин использовался.

Математикам и логикам дается использование странных слов.

'лямбда' звучит действительно эзотерически - как будто это очень странная и особенная вещь. Действительно, если вы пишете JavaScript для приложения веб-браузера и используете "var foo = function() {...}", вы все время используете лямбда-функции.

Ответ 8

Лямбда-выражение является простой формой функции. Идея состоит в том, что что-то вроде формы слева (эквивалентно параметрам) становится чем-то вроде формы справа (эквивалентно телу).

например, в c sharp:

x => x * x

- это лямбда для квадратного значения. Что-то вроде формы

x

становится чем-то вроде

x * x

Ответ 9

"Лямбда-выражение представляет собой анонимную функцию, которая может содержать выражения и выражения и может использоваться для создания делегатов или типов дерева выражений.

Все лямбда-выражения используют лямбда-оператор = > , который читается как "идет". Левая часть оператора лямбда указывает входные параметры (если они есть), а правая сторона содержит блок выражения или оператора. Лямбда-выражение x = > x * x читается "x переходит в x раз x".

from MSDN

Ответ 10

Вы найдете все, что вам нужно знать (о С# Lambdas) для начала здесь:
Лямбда-выражения

Ответ 11

Для получения полного объяснения о лямбда-выражениях также проверьте Wikipedia. (Прокрутите вниз до части исчисления лямбда и части языков программирования.) Лямбда-выражения не такие новые, и они не просто часть С#, а то, что было введено для вычисления почти 80 лет назад! Лямбда-выражения являются основой для функционального программирования.

Это значение? Ну, учитывая, что он на самом деле довольно старый, я бы сказал: очень ценный для тех, кто делает расчеты.

Ответ 12

Если вы находитесь на Java, вы много слышали о lambdas или закрытиях за последние пару месяцев, потому что были разные предложения по добавлению этой функции в Java 7. Однако я думаю, что comitee отказался от нее. Одно из предложений от Нила Гафтера и подробно объяснено здесь: javac.info. Это помогло мне понять варианты использования и преимущества (особенно во внутренних классах).

Ответ 13

Да, это всего лишь способ кодирования множества строк кода в одно выражение. Но, будучи такой эффективной кодировкой, она позволяет создавать новые способы структурирования вашей программы.

Часто можно избежать написания делегатов или обратных вызовов и вернуться к процедурному стилю просто потому, что слишком много работы для объявления новых функций или классов для одного выражения.

Лямбда-выражения делают целесообразным использовать обратные вызовы даже для самых маленьких задач, что может сделать код более понятным. Не может.