什麼是lambda(函數)? (What is a lambda (function)?)


問題描述

什麼是 lambda(函數)? (What is a lambda (function)?)

對於沒有計算機科學背景的人來說,計算機科學界的 lambda 是什麼?


參考解法

方法 1:

Lambda comes from the Lambda Calculus and refers to anonymous functions in programming.

Why is this cool? It allows you to write quick throw away functions without naming them. It also provides a nice way to write closures. With that power you can do things like this.

Python

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

As you can see from the snippet of Python, the function adder takes in an argument x, and returns an anonymous function, or lambda, that takes another argument y. That anonymous function allows you to create functions from functions. This is a simple example, but it should convey the power lambdas and closures have.

Examples in other languages

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

Scheme

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

C# 3.5 or higher

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 = fn () => $a + $b;

echo $lambda();

Haskell

(\x y ‑> x + y) 

Java see this post

// 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

Kotlin

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

Ruby

Ruby is slightly different in that you cannot call a lambda using the exact same syntax as calling a function, but it still has lambdas.

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

Ruby being Ruby, there is a shorthand for lambdas, so you can define adder this way:

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

R

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

方法 2:

A lambda is a type of function, defined inline. Along with a lambda you also usually have some kind of variable type that can hold a reference to a function, lambda or otherwise.

For instance, here's a C# piece of code that doesn't use a 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);
}

This calls Calculator, passing along not just two numbers, but which method to call inside Calculator to obtain the results of the calculation.

In C# 2.0 we got anonymous methods, which shortens the above code to:

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

And then in C# 3.0 we got lambdas which makes the code even shorter:

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:

The name "lambda" is just a historical artifact. All we're talking about is an expression whose value is a function.

A simple example (using Scala for the next line) is:

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

where the argument to the foreach method is an expression for an anonymous function. The above line is more or less the same as writing something like this (not quite real code, but you'll get the idea):

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

except that you don't need to bother with:

  1. Declaring the function somewhere else (and having to look for it when you revisit the code later).
  2. Naming something that you're only using once.

Once you're used to function values, having to do without them seems as silly as being required to name every expression, such as:

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

instead of just writing the expression where you need it:

println(2 * a + b)

The exact notation varies from language to language; Greek isn't always required! ;‑)

方法 4:

It refers to lambda calculus, which is a formal system that just has lambda expressions, which represent a function that takes a function for its sole argument and returns a function. All functions in the lambda calculus are of that type, i.e., λ : λ → λ.

Lisp used the lambda concept to name its anonymous function literals. This lambda represents a function that takes two arguments, x and y, and returns their product:

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

It can be applied in‑line like this (evaluates to 50):

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

方法 5:

The lambda calculus is a consistent mathematical theory of substitution. In school mathematics one sees for example x+y=5 paired with x−y=1. Along with ways to manipulate individual equations it's also possible to put the information from these two together, provided cross‑equation substitutions are done logically. Lambda calculus codifies the correct way to do these substitutions.

Given that y = x−1 is a valid rearrangement of the second equation, this: λ y = x−1 means a function substituting the symbols x−1 for the symbol y. Now imagine applying λ y to each term in the first equation. If a term is y then perform the substitution; otherwise do nothing. If you do this out on paper you'll see how applying that λ y will make the first equation solvable.

That's an answer without any computer science or programming.

The simplest programming example I can think of comes from http://en.wikipedia.org/wiki/Joy_(programming_language)#How_it_works:

here is how the square function might be defined in an imperative programming language (C):

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

The variable x is a formal parameter which is replaced by the actual value to be squared when the function is called. In a functional language (Scheme) the same function would be defined:

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

This is different in many ways, but it still uses the formal parameter x in the same way.


Added: http://imgur.com/a/XBHub

lambda

(by Brian Warshawmk.Lasse V. Karlsenjoel.neelyMark Cidadeisomorphismes)

參考文件

  1. What is a lambda (function)? (CC BY‑SA 2.5/3.0/4.0)

#terminology #lambda #theory #computer-science #language-agnostic






相關問題

抽象 ViewModel 在被繼承時是否被視為模型? (Is an abstract ViewModel considered a Model when it is inherited?)

什麼是 Lambda? (What is a Lambda?)

具體確定項目順序的排序的正確術語是什麼? (What is the proper term for an ordering where the order of items is concretely determined?)

在 Ruby 中,“接收者”指的是什麼? (In Ruby what does the "receiver" refer to?)

錯誤跟踪和問題跟踪系統有什麼區別? (What's the difference between a bug tracking and an issue tracking system?)

為什麼術語 API 和 SDK 似乎可以互換使用? (Why do the terms API and an SDK seem to be used interchangeably?)

Java 中的對等類是什麼? (What is a peer class in Java?)

模擬和模擬有什麼區別? (what is the difference between Emulate and Simulate?)

協議術語:消息與數據包 (Protocol Terminology: Message versus Packet)

表示“目錄”或“文件”的詞是什麼? (What is the word that means "directory" or "file"?)

C ++中復合語句和塊之間的區別? (Difference between a compound statement and a block in C++?)

gnu八度中gnu的含義? (Meaning of gnu in gnu octave?)







留言討論