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

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

21 ответов


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

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

Python

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

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

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

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

C# 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);

Свифт

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

Хаскелл

(\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

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

например, вот фрагмент кода C#, который не использует лямбду:

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

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

В C# 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;
    });
}

и затем в C# 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);
}

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

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

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

Он может применяется в строку (значение 50):

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

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

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

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

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

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

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

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

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

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

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

println(2 * a + b)

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


лямбда-исчисление является последовательной математической теории замещения. Например, в школьной математике 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


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

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

например (в C#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

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

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

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

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

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

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

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

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


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

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


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

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

hello.call

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

Hello
I am inside a proc

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

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

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

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

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

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


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

в очень простой, неофициальном

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


вы можете думать об этом как об анонимной функции-вот еще информация:Википедия - Анонимная Функция


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

Привет, лямбда, Версия 1

template<typename F>

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

Привет, лямбда, версия 2:

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

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

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

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

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

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


для человека без комп-sci фона, что такое лямбда в мире информатики?

я проиллюстрирую это интуитивно шаг за шагом в простых и читаемых кодах 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 типов 7. Простые утверждения - 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

Тада, проанализируй это, " м "- это имя, "Н**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 анонимный

надеюсь, это помогает.


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

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

возвратить числа больше 5.

number => number > 5

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


Я тоже понял. Я пробовал это в 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]) (консоль.log);

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


в 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]()()();

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

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


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

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

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

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


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

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

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

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

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

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

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

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

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

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