Что такое лямбда (функция)?

Для человека без comp-sci фона, что такое лямбда в мире компьютерных наук?

Ответ 1

Лямбда взята из лямбда-исчисления и относится к анонимным функциям в программировании.

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

Python

def adder(x):
    return lambda y: x + y
add5 = adder(5)
add5(1)
6

Как видно из фрагмента Python, функция adder принимает аргумент x и возвращает анонимную функцию или лямбду, которая принимает другой аргумент y. Эта анонимная функция позволяет вам создавать функции из функций. Это простой пример, но он должен передать силу лямбды и замыкания.

Примеры на других языках

Perl 5

sub adder {
    my ($x) = @_;
    return sub {
        my ($y) = @_;
        $x + $y
    }
}

my $add5 = adder(5);
print &$add5(1) == 6 ? "ok\n" : "not ok\n";

JavaScript

var adder = function (x) {
    return function (y) {
        return x + y;
    };
};
add5 = adder(5);
add5(1) == 6

JavaScript (ES6)

const adder = x => y => x + y;
add5 = adder(5);
add5(1) == 6

Схема

(define adder
    (lambda (x)
        (lambda (y)
           (+ x y))))
(define add5
    (adder 5))
(add5 1)
6

С# 3.5 или выше

Func<int, Func<int, int>> adder = 
    (int x) => (int y) => x + y; // 'int' declarations optional
Func<int, int> add5 = adder(5);
var add6 = adder(6); // Using implicit typing
Debug.Assert(add5(1) == 6);
Debug.Assert(add6(-1) == 5);

// Closure example
int yEnclosed = 1;
Func<int, int> addWithClosure = 
    (x) => x + yEnclosed;
Debug.Assert(addWithClosure(2) == 3);

Swift

func adder(x: Int) -> (Int) -> Int{
   return { y in x + y }
}
let add5 = adder(5)
add5(1)
6

PHP

$a = 1;
$b = 2;

$lambda = function () use (&$a, &$b) {
    echo $a + $b;
};

echo $lambda();

Haskell

(\x y -> x + y) 

Java см. этот пост

// The following is an example of Predicate : 
// a functional interface that takes an argument 
// and returns a boolean primitive type.

Predicate<Integer> pred = x -> x % 2 == 0; // Tests if the parameter is even.
boolean result = pred.test(4); // true

Lua

adder = function(x)
    return function(y)
        return x + y
    end
end
add5 = adder(5)
add5(1) == 6        -- true

Котлин

val pred = { x: Int -> x % 2 == 0 }
val result = pred(4) // true

рубин

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

def adder(x)
  lambda { |y| x + y }
end
add5 = adder(5)
add5[1] == 6

Ruby - это Ruby, для ламбд есть сокращение, поэтому вы можете определить adder следующим образом:

def adder(x)
  -> y { x + y }
end

R

adder <- function(x) {
  function(y) x + y
}
add5 <- adder(5)
add5(1)
#> [1] 6

Ответ 2

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

Например, здесь кусок кода С#, который не использует lambda:

public Int32 Add(Int32 a, Int32 b)
{
    return a + b;
}

public Int32 Sub(Int32 a, Int32 b)
{
    return a - b;
}

public delegate Int32 Op(Int32 a, Int32 b);

public void Calculator(Int32 a, Int32 b, Op op)
{
    Console.WriteLine("Calculator: op(" + a + ", " + b + ") = " + op(a, b));
}

public void Test()
{
    Calculator(10, 23, Add);
    Calculator(10, 23, Sub);
}

Это вызывает калькулятор, передавая не только два числа, но и какой метод вызывать внутри калькулятора для получения результатов расчета.

В С# 2.0 мы получили анонимные методы, которые сокращают указанный выше код до:

public delegate Int32 Op(Int32 a, Int32 b);

public void Calculator(Int32 a, Int32 b, Op op)
{
    Console.WriteLine("Calculator: op(" + a + ", " + b + ") = " + op(a, b));
}

public void Test()
{
    Calculator(10, 23, delegate(Int32 a, Int32 b)
    {
        return a + b;
    });
    Calculator(10, 23, delegate(Int32 a, Int32 b)
    {
        return a - b;
    });
}

И затем в С# 3.0 мы получили lambdas, который делает код еще короче:

public delegate Int32 Op(Int32 a, Int32 b);

public void Calculator(Int32 a, Int32 b, Op op)
{
    Console.WriteLine("Calculator: op(" + a + ", " + b + ") = " + op(a, b));
}

public void Test()
{
    Calculator(10, 23, (a, b) => a + b);
    Calculator(10, 23, (a, b) => a - b);
}

Ответ 3

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

Простой пример (используя Scala для следующей строки):

args.foreach(arg => println(arg))

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

void printThat(Object that) {
  println(that)
}
...
args.foreach(printThat)

за исключением того, что вам не нужно беспокоиться:

  • Объявление функции в другом месте (и ее нужно искать, когда вы снова просмотрите код).
  • Именование чего-то, что вы используете только один раз.

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

int tempVar = 2 * a + b
...
println(tempVar)

вместо того, чтобы просто писать выражение там, где оно вам нужно:

println(2 * a + b)

Точная нотация варьируется от языка к языку; Греческий язык не всегда требуется!; -)

Ответ 4

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

Lisp использовал лямбда-концепцию для именования литералов анонимных функций. Эта лямбда представляет функцию, которая принимает два аргумента, x и y, и возвращает их произведение:

(lambda (x y) (* x y)) 

Он может быть применен в строке, как это (оценивается до 50):

((lambda (x y) (* x y)) 5 10)

Ответ 5

Лямбда-исчисление является последовательной математической теорией замещения. В школьной математике мы видим, например, x+y=5 в паре с x−y=1. Наряду с путями манипулирования отдельными уравнениями также можно объединить информацию из этих двух, если логические подходы к перекрестному уравнению выполняются. Исчисление лямбда кодирует правильный способ выполнения этих подстановок.

Учитывая, что y = x−1 является действительной перестановкой второго уравнения, это: λ y = x−1 означает функцию, заменяющую символы x−1 символом y. Теперь представьте себе применение λ y к каждому слагаемому в первом уравнении. Если термин y, то выполните подстановку; в противном случае ничего не делать. Если вы сделаете это на бумаге, вы увидите, как применение этого λ y сделает первое уравнение разрешимым.

Это ответ без какой-либо компьютерной науки или программирования.

Самый простой пример программирования, о котором я могу думать, исходит из http://en.wikipedia.org/wiki/Joy_(programming_language)#How_it_works:

вот как квадратная функция может быть определена в императиве язык программирования (C):

int square(int x)
{
    return x * x;
}

Переменная x является формальным параметром, который заменяется фактическим значение, которое должно быть квадратично при вызове функции. В функциональном языка (схема) будет определена одна и та же функция:

(define square
  (lambda (x) 
    (* x x)))

Это по-разному, но он по-прежнему использует формальный параметр x таким же образом.


Добавлено: http://imgur.com/a/XBHub

lambda

Ответ 6

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

В синтаксисе С# lambda часто компилируется в простые методы так же, как анонимные делегаты, но его также можно разбить и прочитать его логику.

Например (в С# 3):

LinqToSqlContext.Where( 
    row => row.FieldName > 15 );

LinqToSql может читать эту функцию (x > 15) и преобразовывать ее в фактический SQL для выполнения с использованием деревьев выражений.

Утверждение выше:

select ... from [tablename] 
where [FieldName] > 15      --this line was 'read' from the lambda function

Это отличается от обычных методов или анонимных делегатов (которые действительно являются манерой компилятора), потому что они не могут быть прочитаны.

Не все методы на С#, которые используют синтаксис лямбда, могут быть скомпилированы в деревья выражений (т.е. фактические функции лямбда). Например:

LinqToSqlContext.Where( 
    row => SomeComplexCheck( row.FieldName ) );

Теперь дерево выражений не может быть прочитано - SomeComplexCheck не может быть разбит. Оператор SQL будет выполняться без того, где и каждая строка данных будет помещена через SomeComplexCheck.

Лямбда-функции не следует путать с анонимными методами. Например:

LinqToSqlContext.Where( 
    delegate ( DataRow row ) { 
        return row.FieldName > 15; 
    } );

У этого также есть встроенная функция, но на этот раз это просто магия компилятора - компилятор С# разделит это на новый метод экземпляра с автогенерированным именем.

Анонимные методы не могут быть прочитаны, и поэтому логика не может быть переведена так, как может, для лямбда-функций.

Ответ 7

Мне нравится объяснение Lambdas в этой статье: Эволюция LINQ и ее влияние на дизайн С#. Это имело для меня большой смысл, поскольку он показывает реальный мир для Лямбдаса и создает его в качестве практического примера.

Их быстрое объяснение: Lambdas - это способ обработки кода (функций) в качестве данных.

Ответ 8

Пример lambda в Ruby выглядит следующим образом:

hello = lambda do
    puts('Hello')
    puts('I am inside a proc')
end

hello.call

Будет генерировать следующий вывод:

Hello
I am inside a proc

Ответ 9

@Brian Я все время использую lambdas в С#, в операциях LINQ и non-LINQ. Пример:

string[] GetCustomerNames(IEnumerable<Customer> customers)
 { return customers.Select(c=>c.Name);
 }

До С# я использовал анонимные функции в JavaScript для обратных вызовов для функций AJAX до того, как был добавлен термин Ajax:

getXmlFromServer(function(result) {/*success*/}, function(error){/*fail*/});

Интересная вещь с синтаксисом С# лямбда заключается в том, что сами по себе их тип не может быть выведен (т.е. вы не можете ввести var foo = (x, y) = > x * y), но в зависимости от того, какой тип они будут назначены, они будут скомпилированы как делегаты или абстрактные синтаксические деревья, представляющие выражение (как это делают объекты-объекты объектов LINQ для своей "языковой интеграции" ).

Lambdas в LISP также может быть передан оператору котировки, а затем пройден как список списков. Некоторые мощные макросы сделаны таким образом.

Ответ 10

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

В очень простых неформальных словах кто-то, кто знает очень мало или ничего по математике или программированию, я бы объяснил это как небольшую "машину" или "ящик", которая принимает некоторый вклад, работать и выпускать некоторый результат, не имеет определенного имени, но мы знаем, где он находится и только этим знанием мы его используем.

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

Ответ 12

Просто потому, что я не могу увидеть пример С++ 11 здесь, я продолжу и выложу этот хороший пример отсюда. После поиска, это самый ясный пример конкретного языка, который я смог найти.

Здравствуйте, Lambdas, версия 1

template<typename F>

void Eval( const F& f ) {
        f();
}
void foo() {
        Eval( []{ printf("Hello, Lambdas\n"); } );
}

Здравствуйте, Lambdas, версия 2:

void bar() {
    auto f = []{ printf("Hello, Lambdas\n"); };
    f();
}

Ответ 13

У меня проблемы с обмоткой вокруг лямбда-выражений, потому что я работаю в Visual FoxPro, у которого есть подстановка Macro и функции ExecScript {} и Evaluate(), которые, похоже, выполняют ту же самую цель.

? Calculator(10, 23, "a + b")
? Calculator(10, 23, "a - b");

FUNCTION Calculator(a, b, op)
RETURN Evaluate(op)

Одно из преимуществ использования формальных lambdas - это (я предполагаю) проверка времени компиляции: Fox не будет знать, если вы опечатаете текстовую строку выше, пока она не попытается ее запустить.

Это также полезно для кода, управляемого данными: вы можете хранить целые процедуры в полях memo в базе данных, а затем просто оценивать их во время выполнения. Это позволяет вам настроить часть приложения без фактического доступа к источнику. (Но эта другая тема вообще.)

Ответ 14

Что такое лямбда в мире компьютерных наук для человека, не имеющего опыта в области компьютерных технологий?

Я проиллюстрирую это интуитивно шаг за шагом в простых и удобочитаемых кодах Python.

Короче говоря, лямбда - это просто анонимная и встроенная функция.

Давайте начнем с задания, чтобы понять lambdas как первокурсника с основами арифметики.

План присвоения "имя = значение", см.:

In [1]: x = 1
   ...: y = 'value'
In [2]: x
Out[2]: 1
In [3]: y
Out[3]: 'value'

"x", "y" - это имена, а 1, "value" - значения. Попробуйте функцию по математике

In [4]: m = n**2 + 2*n + 1
NameError: name 'n' is not defined

Отчеты об ошибках,
Вы не можете написать математику непосредственно как код, "n" должно быть определено или присвоено значению.

In [8]: n = 3.14
In [9]: m = n**2 + 2*n + 1
In [10]: m
Out[10]: 17.1396

Теперь это работает, что если вы настаиваете на объединении двух отдельных строк в одну. Приходит lambda

In [13]: j = lambda i: i**2 + 2*i + 1
In [14]: j
Out[14]: <function __main__.<lambda>>

Об ошибках не сообщается.

Это взгляд на lambda, он позволяет вам написать функцию в одну строку, как вы делаете это в математике непосредственно на компьютере.

Мы увидим это позже.

Давайте продолжим копать глубже на "назначение".

Как показано выше, символ равенства = работает для простого типа данных (1 и "значение") и простого выражения (n ** 2 + 2 * n + 1).

Попробуй это:

In [15]: x = print('This is a x')
This is a x
In [16]: x
In [17]: x = input('Enter a x: ')
Enter a x: x

Он работает для простых операторов, в Python их 11 типов . Простые операторы - документация Python 3.6.3.

Как насчет сложного заявления,

In [18]: m = n**2 + 2*n + 1 if n > 0
SyntaxError: invalid syntax
#or
In [19]: m = n**2 + 2*n + 1, if n > 0
SyntaxError: invalid syntax

Приходит def включите его

In [23]: def m(n):
    ...:     if n > 0:
    ...:         return n**2 + 2*n + 1
    ...:
In [24]: m(2)
Out[24]: 9

Тада, проанализируй, m - это имя, n ** 2 + 2 * n + 1 - значение. : это вариант '='.
Найдите это, если только для понимания, все начинается с назначения и все является назначением.

Теперь вернемся к lambda, у нас есть функция с именем 'm'

Пытаться:

In [28]: m = m(3)
In [29]: m
Out[29]: 16

Здесь есть два имени "m", функция m уже имеет дублированное имя.

Это форматирование как:

In [27]: m = def m(n):
    ...:         if n > 0:
    ...:             return n**2 + 2*n + 1
    SyntaxError: invalid syntax

Это не умная стратегия, поэтому сообщения об ошибках

Мы должны удалить один из них, установить функцию без имени.

m = lambda n:n**2 + 2*n + 1

Это называется "анонимная функция"

В заключение,

  1. lambda во встроенной функции, которая позволяет вам написать функцию в одну прямую линию, как в математике
  2. lambda аноним

Надеюсь это поможет.

Ответ 15

Это функция, которая не имеет имени. Напр. в С# вы можете использовать

numberCollection.GetMatchingItems<int>(number => number > 5);

чтобы вернуть числа, превышающие 5.

number => number > 5

- здесь лямбда-часть. Он представляет функцию, которая принимает параметр (число) и возвращает логическое значение (число > 5). Метод GetMatchingItems использует эту лямбду для всех элементов коллекции и возвращает соответствующие элементы.

Ответ 16

В Javascript, например, функции рассматриваются как один и тот же смешанный тип, как и все остальные (int, string, float, bool). Таким образом, вы можете создавать функции "на лету", назначать их вещам и называть их позже. Это полезно, но не то, что вы хотите использовать, или вы будете путать всех, кто должен поддерживать ваш код после вас...

Это какой-то код, с которым я играл, чтобы увидеть, насколько глубока эта кроличья нора:

var x = new Object;
x.thingy = new Array();
x.thingy[0] = function(){ return function(){ return function(){ alert('index 0 pressed'); }; }; }
x.thingy[1] = function(){ return function(){ return function(){ alert('index 1 pressed'); }; }; }
x.thingy[2] = function(){ return function(){ return function(){ alert('index 2 pressed'); }; }; }

for(var i=0 ;i<3; i++)
    x.thingy[i]()()();

Ответ 17

В контексте CS лямбда-функция представляет собой абстрактную математическую концепцию, которая решает проблему символической оценки математических выражений. В этом контексте функция лямбда такая же, как лямбда-термин.

Но в языках программирования это что-то другое. Это фрагмент кода, который объявлен "на месте", и который может передаваться как "первоклассный гражданин". Эта концепция оказалась полезной, так что она вошла в почти все популярные современные языки программирования (см. lambda functions everwhere post).

Ответ 18

Я тоже понял. Я пробовал в JS с этим:

var addAndMult = function(x) {
        return (function(y) {
            return (function(z) {
                return (x+y)*z; 
                });
            });
        };

Он добавляет от 2 до 4, а затем результат получается на 6. Однако мне иногда трудно прочитать: (

Также я сделал интересную функцию forEach:

var forEach = function(arr) {
            return (function(x) {
            for (var i=0; arr[i]; i++) {
                 x(arr[i]);
             }
        });
    }

Foreach ([1,2,3,4,5]) (console.log);

Этот метод будет перебирать массив и выполняет действие - в случае печати на консоли. Теперь я тоже понимаю, почему labmdas являются мощными.

Ответ 19

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

У нас есть четкое разделение между выражениями, утверждениями и функциями, которых нет у математиков.

Слово "функция" в программировании также различно - у нас есть "функция - это последовательность шагов" (от латинского "выполнить" ). В математике это что-то о корреляции между переменными.

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

Ответ 20

Lambda Function или Small Anonymous Function - это автономный блок функций, который можно передавать и использовать в вашем коде. У лямбды разные названия в разных языках программирования - Lambda в Python и Kotlin, Closure в Swift или Block в C и Objective-C. Хотя лямбда-значение для этих языков очень похоже, иногда оно имеет небольшие различия.

Давайте посмотрим, как Lambda (Closure) работает в Swift 4.2 с методом sorted() - от обычной функции до кратчайшего выражения:

let coffee: [String] = ["Cappuccino", "Espresso", "Latte", "Ristretto"]

1. Нормальная функция

func backward(_ n1: String, _ n2: String) -> Bool {
    return n1 > n2
}
var reverseOrder = coffee.sorted(by: backward)


// RESULT: ["Ristretto", "Latte", "Espresso", "Cappuccino"]

2. Закрытие Выражение

reverseOrder = coffee.sorted(by: { (n1: String, n2: String) -> Bool in
    return n1 > n2
})

3. Встроенное выражение закрытия

reverseOrder = coffee.sorted(by: { (n1: String, n2: String) -> Bool in return n1 > n2 } )

4. Вывод типа из контекста

reverseOrder = coffee.sorted(by: { n1, n2 in return n1 > n2 } )

5. Неявные возвраты из замыканий с одним выражением

reverseOrder = coffee.sorted(by: { n1, n2 in n1 > n2 } )

6. Сокращенные имена аргументов

reverseOrder = coffee.sorted(by: { $0 > $1 } )

// $0 and $1 are closures first and second String arguments.

7. Операторские методы

reverseOrder = coffee.sorted(by: >)

// RESULT: ["Ristretto", "Latte", "Espresso", "Cappuccino"]

Надеюсь это поможет.

Ответ 21

На вопрос дан полный ответ, я не хочу вдаваться в подробности. Я хочу поделиться использованием при написании численных расчетов в ржавчине.

Есть пример лямбды (анонимная функция)

let f = |x: f32| -> f32 { x * x - 2.0 };
let df = |x: f32| -> f32 { 2.0 * x };

Когда я писал модуль метода Ньютона-Рафсона, он использовался как производная первого и второго порядка. (Если вы хотите узнать, что такое метод Ньютона-Рафсона, посетите страницу " https://en.wikipedia.org/wiki/Newton%27s_method ").

Выход как следующий

println!("f={:.6}      df={:.6}", f(10.0), df(10.0))

f=98.000000       df=20.000000

Ответ 22

Представьте, что у вас есть ресторан с возможностью доставки, и у вас есть заказ, который нужно сделать менее чем за 30 минут. Суть в том, что клиенты обычно не заботятся о том, отправляете ли вы еду на велосипеде на машине или босиком, если вы сохраняете еду теплой и связанной. Итак, давайте преобразуем эту идиому в Javascript с анонимными и определенными транспортными функциями.

Ниже мы определили способ доставки, мы также определили имя функции:

// ES5 
var food = function withBike(kebap, coke) {
return (kebap + coke); 
};

Что если бы мы использовали стрелки/лямбда-функции для выполнения этой передачи:

// ES6    
const food = (kebap, coke) => { return kebap + coke };

Вы видите, что для клиента нет разницы и нет времени тратить время на размышления о том, как отправить еду. Просто отправь это.

Кстати, я не рекомендую кебаб с коксом, поэтому верхние коды будут давать вам ошибки. Повеселись.