Что такое лямбда в мире компьютерных наук для человека без опыта работы в области компьютерных технологий?
Что такое лямбда в мире компьютерных наук для человека без опыта работы в области компьютерных технологий?
Ответы:
Лямбда происходит от лямбда-исчисления и относится к анонимным функциям в программировании.
Почему это круто? Это позволяет вам писать функции быстрого выбрасывания, не называя их. Это также обеспечивает хороший способ писать замыкания. С этой силой вы можете делать такие вещи.
питон
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
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 = fn () => $a + $b;
echo $lambda();
Haskell
(\x y -> x + y)
Ява увидеть этот пост
// 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
р
adder <- function(x) {
function(y) x + y
}
add5 <- adder(5)
add5(1)
#> [1] 6
Лямбда - это тип функции, определенный в строке. Наряду с лямбдой у вас также обычно есть некоторый тип переменной, который может содержать ссылку на функцию, лямбду или другое.
Например, вот фрагмент кода 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 мы получили лямбды, которые делают код еще короче:
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);
}
Op
, можно просто использоватьFunc<int, int>
Console.WriteLine("Calculator: op " + op.Method.Name + " (" + a + ", " + b + ") = " + op(a, b));
для первого примера.
Название «лямбда» - это просто исторический артефакт. Все, о чем мы говорим, это выражение, значением которого является функция.
Простой пример (используя 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)
Точная запись варьируется от языка к языку; Греческий не всегда требуется! ;-)
Это относится к лямбда-исчислению , которое является формальной системой, которая просто имеет лямбда-выражения, которые представляют функцию, которая принимает функцию в качестве единственного аргумента и возвращает функцию. Все функции в лямбда-исчислении относятся к этому типу, т.е.λ : λ → λ
.
Лисп использовал лямбда-концепцию для именования литералов своих анонимных функций. Эта лямбда представляет функцию, которая принимает два аргумента, x и y, и возвращает их произведение:
(lambda (x y) (* x y))
Это может быть применено в строке, как это (оценивается до 50 ):
((lambda (x y) (* x y)) 5 10)
λ : λ -> λ
сбивает с толку (и фактически недействительно).
Лямбда-исчисление является последовательной математической теорией замещения. В школьной математике можно увидеть, например, в 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
Немного упрощено: лямбда-функция - это функция, которая может быть передана другим функциям, и ее логика доступна.
В 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 # разделит это на новый метод экземпляра с автоматически сгенерированным именем.
Анонимные методы не могут быть прочитаны, и поэтому логика не может быть переведена, как это возможно для лямбда-функций.
Мне нравится объяснение Lambdas в этой статье: Эволюция LINQ и ее влияние на дизайн C # . Это имело большой смысл для меня, поскольку показывает реальный мир для Lambdas и создает его в качестве практического примера.
Их быстрое объяснение: лямбда-выражения - это способ обработки кода (функций) как данных.
Пример лямбды в Ruby выглядит следующим образом:
hello = lambda do
puts('Hello')
puts('I am inside a proc')
end
hello.call
Будет генерировать следующий вывод:
Hello
I am inside a proc
На вопрос формально дан большой ответ, поэтому я не буду пытаться добавить больше к этому.
В очень простой, неформальной словах для тех, кто очень мало знает или вообще ничего не знает по математике или программированию, я бы объяснил это как маленький «компьютер» или «ящик», который принимает некоторый ввод, выполняет некоторую работу и производит вывод, не имеет конкретного имени , но мы знаем, где это, и только этим знанием мы используем его.
Практически говоря, для человека, который знает, что такое функция, я бы сказал им, что это функция без имени, обычно помещаемая в точку памяти, которую можно использовать, просто ссылаясь на эту память (обычно с помощью переменная - если бы они слышали о концепции указателей на функции, я бы использовал их как похожую концепцию) - этот ответ охватывает довольно простые основы (без упоминаний о замыканиях и т. д.), но можно легко понять суть.
@ Брайан Я все время использую лямбды в C #, в операторах LINQ и не 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 выполняют свою «интегрированную в язык» магию).
Лямбды в LISP также можно передать оператору цитаты, а затем проследить в виде списка списков. Некоторые мощные макросы сделаны таким образом.
Вы можете думать об этом как об анонимной функции - вот еще немного информации: Википедия - Анонимная функция
Просто потому, что я не могу увидеть пример C ++ 11 здесь, я продолжу и выложу этот хороший пример отсюда . После поиска, это самый ясный пример конкретного языка, который я смог найти.
template<typename F>
void Eval( const F& f ) {
f();
}
void foo() {
Eval( []{ printf("Hello, Lambdas\n"); } );
}
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 не будет знать, если вы опечатаете текстовую строку выше, пока не попытается ее запустить.
Это также полезно для кода, управляемого данными: вы можете хранить целые процедуры в памятных полях в базе данных, а затем просто оценивать их во время выполнения. Это позволяет настраивать часть приложения, фактически не имея доступа к источнику. (Но это совсем другая тема.)
Что такое лямбда в мире компьютерных наук для человека без опыта работы в области компьютерных технологий?
Я проиллюстрирую это интуитивно шаг за шагом в простых и удобочитаемых кодах 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 7 их 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
Это называется «анонимная функция»
В заключении,
lambda
в встроенной функции, которая позволяет вам написать функцию в одну прямую линию, как в математикеlambda
является анонимнымНадеюсь это поможет.
Это функция, которая не имеет имени. Например, в C # вы можете использовать
numberCollection.GetMatchingItems<int>(number => number > 5);
вернуть числа, которые больше 5.
number => number > 5
это лямбда-часть здесь. Он представляет функцию, которая принимает параметр (число) и возвращает логическое значение (число> 5). Метод GetMatchingItems использует эту лямбду для всех элементов в коллекции и возвращает соответствующие элементы.
В 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 лямбда-функция - это абстрактная математическая концепция, которая решает проблему символической оценки математических выражений. В этом контексте лямбда-функция совпадает с лямбда-термином .
Но в языках программирования это нечто другое. Это кусок кода, который объявлен «на месте», и который может быть передан как «первоклассный гражданин». Эта концепция оказалась полезной для того, чтобы она вошла почти во все популярные современные языки программирования (см. Функции лямбда везде ).
A
Lambda Function
или aSmall Anonymous Function
- это автономный блок функций, который можно передавать и использовать в вашем коде. У лямбды разные названия в разных языках программирования -Lambda
в Python и Kotlin ,Closure
в Swift илиBlock
в C и Objective-C . Хотя значение лямбда для этих языков довольно схоже, иногда оно имеет небольшие различия.
let coffee: [String] = ["Cappuccino", "Espresso", "Latte", "Ristretto"]
func backward(_ n1: String, _ n2: String) -> Bool {
return n1 > n2
}
var reverseOrder = coffee.sorted(by: backward)
// RESULT: ["Ristretto", "Latte", "Espresso", "Cappuccino"]
reverseOrder = coffee.sorted(by: { (n1: String, n2: String) -> Bool in
return n1 > n2
})
reverseOrder = coffee.sorted(by: { (n1: String, n2: String) -> Bool in return n1 > n2 } )
reverseOrder = coffee.sorted(by: { n1, n2 in return n1 > n2 } )
reverseOrder = coffee.sorted(by: { n1, n2 in n1 > n2 } )
reverseOrder = coffee.sorted(by: { $0 > $1 } )
// $0 and $1 are closure’s first and second String arguments.
reverseOrder = coffee.sorted(by: >)
// RESULT: ["Ristretto", "Latte", "Espresso", "Cappuccino"]
Надеюсь это поможет.
Я тоже это получил. Я попробовал это в 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);
Этот метод выполняет итерацию массива и выполняет действие - в случае печати на консоль. Теперь я тоже понимаю, почему лабмды сильны.
В компьютерном программировании лямбда - это кусок кода (оператор, выражение или группа из них), который принимает некоторые аргументы из внешнего источника. Это не всегда должна быть анонимная функция - у нас есть много способов их реализовать.
У нас есть четкое разделение между выражениями, утверждениями и функциями, которого нет у математиков.
Слово «функция» в программировании также отличается - у нас есть «функция - это последовательность шагов для выполнения» (от латинского «выполнять»). В математике речь идет о корреляции между переменными.
Функциональные языки стараются быть максимально похожими на математические формулы, и их слова означают почти то же самое. Но в других языках программирования у нас все по-другому.
На вопрос дан полный ответ, я не хочу вдаваться в подробности. Я хочу поделиться использованием при написании численных расчетов в ржавчине.
Есть пример лямбды (анонимная функция)
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);
};
Что если бы мы использовали стрелки / лямбда-функции для выполнения этой передачи:
// ES6
const food = (kebap, coke) => { return kebap + coke };
Вы видите, что для клиента нет разницы и нет времени тратить время на размышления о том, как отправить еду. Просто отправь это.
Кстати, я не рекомендую кебаб с коксом, поэтому верхние коды будут давать вам ошибки. Радоваться, веселиться.