แลมบ์ดา (ฟังก์ชั่น) คืออะไร?


743

สำหรับบุคคลที่ไม่มีพื้นฐานความรู้แลมบ์ดาในโลกของวิทยาศาสตร์คอมพิวเตอร์คืออะไร?


3
นิพจน์ amda อธิบายที่นี่ อย่างสวยงาม
Jameer Mulani

1
ดูสิ่งนี้สำหรับฟังก์ชั่นแลมบ์ดาในภาษาต่างๆและในปีใดที่มีการนำเสนอในภาษาเหล่านั้น
Philip Schwarz

คำตอบ:


1081

แลมบ์ดามาจากแลมบ์ดาแคลคูลัสและอ้างถึงฟังก์ชั่นนิรนามในการเขียนโปรแกรม

ทำไมสิ่งนี้ถึงเจ๋ง? ช่วยให้คุณสามารถเขียนฟังก์ชั่นการโยนทิ้งอย่างรวดเร็วโดยไม่ต้องตั้งชื่อ นอกจากนี้ยังเป็นวิธีที่ดีในการเขียนการปิด ด้วยพลังนั้นคุณสามารถทำสิ่งนี้ได้

หลาม

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

ดังที่คุณเห็นได้จากตัวอย่างของ Python ฟังก์ชั่น adder ใช้ในการโต้แย้ง x และส่งกลับฟังก์ชันที่ไม่ระบุชื่อหรือแลมบ์ดาซึ่งรับอาร์กิวเมนต์อีกตัว ฟังก์ชั่นไม่ระบุชื่อนั้นให้คุณสร้างฟังก์ชั่นจากฟังก์ชั่น นี่เป็นตัวอย่างง่ายๆ แต่ควรถ่ายทอดพลัง lambdas และการปิดได้

ตัวอย่างในภาษาอื่น ๆ

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

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 = fn () => $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

Kotlin

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 มีชวเลขสำหรับ lambdas ดังนั้นคุณสามารถกำหนดadderวิธีนี้ได้:

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

R

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

3
แล้วอะไรคือความแตกต่างระหว่างฟังก์ชั่นแลมบ์ดาและนักแสดง ?
Maxpm

1
@ Maxpm functor สามารถเป็นวัตถุมาตรฐานที่มีเขตข้อมูลและฟังก์ชั่นอินสแตนซ์ในขณะที่ฟังก์ชั่นแลมบ์ดาโดยทั่วไปประกอบด้วยเพียงหนึ่งบรรทัดของคำแนะนำ สิ่งนี้อาจแตกต่างกันไปขึ้นอยู่กับภาษาของหลักสูตร
zdimension

1
ฉันไม่คิดว่ามันแม่นยำที่จะบอกว่าฟังก์ชั่นแลมบ์ดาเหมือนกับฟังก์ชั่นนิรนาม สำหรับบางภาษาเช่น JavaScript นิพจน์แลมบ์ดาเป็นรูปแบบเฉพาะของฟังก์ชันที่ไม่ระบุตัวตน ตัวอย่าง JavaScript ที่คุณให้นั้นเป็นฟังก์ชั่นนิรนามโดยไม่มีไวยากรณ์แลมบ์ดาขณะที่ตัวอย่าง JavaScript (ES6) ที่คุณให้ไว้คือนิพจน์แลมบ์ดา
Kyle Delaney

1
@ KyleDelaney แน่นอนไม่ระบุชื่อไม่จำเป็นต้องเป็นแลมบ์ดาแน่นอนมีฟังก์ชั่นแลมบ์ดาที่ไม่ระบุชื่อตามที่คุณชี้มีหนึ่งแม้ในตัวอย่าง
Carmine Tambascia

@AliAnkarali หรือคุ้นเคยกับการใช้ rubys lambda;)
Jimmy MG Lim

107

แลมบ์ดาเป็นฟังก์ชันประเภทหนึ่งที่กำหนดไว้แบบอินไลน์ พร้อมกับแลมบ์ดาคุณมักจะมีประเภทตัวแปรบางประเภทที่สามารถเก็บการอ้างอิงถึงฟังก์ชันแลมบ์ดาหรืออย่างอื่น

ตัวอย่างเช่นนี่คือโค้ด 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);
}

แทนที่จะกำหนดผู้รับมอบสิทธิ์อย่างชัดเจนคนOpๆ หนึ่งอาจใช้Func<int, int>
Mateen Ulhaq

ฉันขอแนะนำConsole.WriteLine("Calculator: op " + op.Method.Name + " (" + a + ", " + b + ") = " + op(a, b));ตัวอย่างแรก
Marc.2377

น่าอัศจรรย์ที่คำตอบที่ได้รับการยอมรับคือการช่วยเหลือผู้คนในหลายภาษาฉันรู้สึกว่าคำตอบนี้ช่วยให้ฉันเข้าใจถึงประโยชน์ของ lambdas ได้ดีขึ้นและพวกเขาแตกต่างจากฟังก์ชั่นมาตรฐานอย่างไร ฉันเห็นได้อย่างชัดเจนถึงข้อดีของแลมบ์ดาเหนือวิธีก่อนหน้านี้เพื่อให้ได้ผลลัพธ์ที่คล้ายกัน
RTHarston

ขอบคุณสำหรับตัวอย่างของคุณการมีฟังก์ชั่นที่ซับซ้อนมากขึ้นช่วยให้เข้าใจถึงข้อดีของ lambdas ได้มากกว่าฟังก์ชั่นธรรมดาที่ดูเหมือนว่าคุณจะไม่ได้รับการปรับแต่งมากมาย
Sarah

71

ชื่อ "แลมบ์ดา" เป็นเพียงสิ่งประดิษฐ์ทางประวัติศาสตร์ ทั้งหมดที่เรากำลังพูดถึงคือนิพจน์ที่มีค่าเป็นฟังก์ชัน

ตัวอย่างง่ายๆ (ใช้ 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)

สัญกรณ์ที่แน่นอนแตกต่างกันไปในแต่ละภาษา กรีกไม่จำเป็นต้องใช้เสมอ! ;-)


62

มันหมายถึงแคลคูลัสแลมบ์ดาซึ่งเป็นระบบที่เป็นทางการที่เพิ่งมีการแสดงออกแลมบ์ดาซึ่งเป็นตัวแทนของฟังก์ชั่นที่ใช้ฟังก์ชั่นสำหรับอาร์กิวเมนต์เดียวและส่งกลับฟังก์ชั่น λ : λ → λฟังก์ชั่นทั้งหมดในแคลคูลัสแลมบ์ดาเป็นชนิดที่คือ

เสียงกระเพื่อมใช้แนวคิดแลมบ์ดาเพื่อตั้งชื่อตัวอักษรฟังก์ชั่นที่ไม่ระบุชื่อ แลมบ์ดานี้แสดงถึงฟังก์ชั่นที่รับอาร์กิวเมนต์สองตัวคือ x และ y และส่งคืนผลิตภัณฑ์:

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

มันสามารถนำมาใช้ในบรรทัดเช่นนี้ (ประเมินถึง50 ):

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

ฉันคิดว่าการใช้งานของคุณλ : λ -> λสร้างความสับสน (และไม่ถูกต้องจริง)
einpoklum

51

แคลคูลัสแลมบ์ดาเป็นทฤษฎีทางคณิตศาสตร์ที่สอดคล้องกันของการทดแทน ในวิชาคณิตศาสตร์โรงเรียนหนึ่งเห็นเช่นจับคู่กับ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 เป็นพารามิเตอร์ที่เป็นทางการซึ่งถูกแทนที่ด้วยค่าจริงที่จะยกกำลังสองเมื่อเรียกใช้ฟังก์ชัน ในฟังก์ชั่นภาษา (Scheme) ฟังก์ชั่นเดียวกันจะถูกกำหนด:

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

สิ่งนี้แตกต่างกันในหลาย ๆ ทาง แต่ก็ยังคงใช้พารามิเตอร์ที่เป็นทางการ x ในวิธีเดียวกัน


เพิ่มแล้ว: http://imgur.com/a/XBHub

แลมบ์ดา


14

oversimplified เล็กน้อย: ฟังก์ชั่นแลมบ์ดาเป็นสิ่งหนึ่งที่สามารถส่งผ่านไปยังฟังก์ชั่นอื่น ๆ และเข้าถึงตรรกะได้

ในไวยากรณ์ C # lambda มักจะรวบรวมวิธีการง่าย ๆ ในลักษณะเดียวกับผู้ได้รับมอบหมายที่ไม่ระบุชื่อ แต่ก็สามารถแยกย่อยและอ่านตรรกะได้

ตัวอย่างเช่น (ใน 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 # จะแยกสิ่งนี้ออกเป็นวิธีอินสแตนซ์ใหม่ด้วยชื่อที่สร้างอัตโนมัติ

วิธีการที่ไม่ระบุชื่อไม่สามารถอ่านได้และดังนั้นจึงไม่สามารถแปลลอจิกได้เช่นเดียวกับฟังก์ชั่นแลมบ์ดา


7

ผมชอบคำอธิบาย Lambdas ในบทความนี้: วิวัฒนาการของ LINQ และผลกระทบต่อการออกแบบของ C # มันสมเหตุสมผลมากสำหรับฉันเพราะมันแสดงให้เห็นถึงโลกแห่งความเป็นจริงของแลมบ์ดาและสร้างมันขึ้นมาเพื่อเป็นตัวอย่างในทางปฏิบัติ

คำอธิบายอย่างรวดเร็วของพวกเขา: Lambdas เป็นวิธีการปฏิบัติต่อโค้ด (ฟังก์ชั่น) เป็นข้อมูล


7

ตัวอย่างของแลมบ์ดาในทับทิมมีดังนี้:

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

hello.call

จะสร้างเอาต์พุตต่อไปนี้ให้เป็นของเดิม

Hello
I am inside a proc

5

@ Brian ฉันใช้ lambdas ตลอดเวลาใน 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 ยังสามารถส่งผ่านไปยังโอเปอเรเตอร์ของใบเสนอราคาแล้วทำการสำรวจเป็นรายการ มาโครที่ทรงพลังบางตัวเกิดขึ้นในลักษณะนี้


5

คำถามมีคำตอบอย่างเป็นทางการมากดังนั้นฉันจะไม่พยายามเพิ่มข้อมูลนี้อีก

ในคำง่ายๆอย่างไม่เป็นทางการกับคนที่รู้น้อยมากหรือไม่มีอะไรเกี่ยวกับคณิตศาสตร์หรือการเขียนโปรแกรมฉันจะอธิบายว่ามันเป็น "เครื่องจักร" หรือ "กล่อง" ขนาดเล็กที่รับอินพุตทำให้ทำงานและสร้างผลลัพธ์บางอย่างไม่มีชื่อเฉพาะ แต่เรารู้ว่ามันอยู่ที่ไหนและด้วยความรู้นี้เราใช้มัน

พูดจริงสำหรับคนที่รู้ว่าฟังก์ชั่นคืออะไรฉันจะบอกพวกเขาว่ามันเป็นฟังก์ชั่นที่ไม่มีชื่อมักจะใส่จุดในหน่วยความจำที่สามารถใช้งานได้เพียงแค่อ้างอิงถึงหน่วยความจำนั้น ตัวแปร - หากพวกเขาเคยได้ยินเกี่ยวกับแนวคิดของตัวชี้ฟังก์ชั่นฉันจะใช้พวกเขาเป็นแนวคิดที่คล้ายกัน) - คำตอบนี้ครอบคลุมพื้นฐานที่น่ารัก (ไม่เอ่ยถึงการปิด ฯลฯ )



4

เพียงเพราะฉันไม่เห็น 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();
}

3

ฉันมีปัญหาในการพันหน้าด้วยการแสดงออกแลมบ์ดาเพราะฉันทำงานใน Visual FoxPro ซึ่งมีการทดแทนมาโครและฟังก์ชัน ExecScript {} และ Evaluate () ซึ่งดูเหมือนว่าจะให้บริการตามวัตถุประสงค์เดียวกันมาก

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

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

ข้อดีอย่างหนึ่งของการใช้ lambdas อย่างเป็นทางการคือ (ฉันคิดว่า) การตรวจสอบคอมไพล์เวลา: Fox จะไม่รู้ว่าคุณพิมพ์สตริงข้อความด้านบนหรือไม่จนกว่าจะพยายามเรียกใช้

สิ่งนี้ยังมีประโยชน์สำหรับรหัสที่ใช้ข้อมูล: คุณสามารถจัดเก็บรูทีนทั้งหมดในเขตข้อมูลบันทึกในฐานข้อมูลแล้วเพียงแค่ประเมินผลในเวลาทำงาน นี่ช่วยให้คุณปรับแต่งส่วนของแอปพลิเคชันโดยไม่ต้องเข้าถึงแหล่งข้อมูล (แต่นั่นเป็นอีกหัวข้อทั้งหมด)


3

สำหรับบุคคลที่ไม่มีพื้นฐานความรู้แลมบ์ดาในโลกของวิทยาศาสตร์คอมพิวเตอร์คืออะไร?

ฉันจะอธิบายมันอย่างเป็นขั้นเป็นตอนโดยใช้รหัสหลามที่อ่านง่าย

ในระยะสั้นแลมบ์ดาเป็นเพียงฟังก์ชั่นนิรนามและอินไลน์

เริ่มจากงานที่มอบหมายเพื่อทำความเข้าใจ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

มันใช้งานได้แล้วจะเกิดอะไรขึ้นถ้าคุณยืนยันที่จะรวมสองบรรทัด seperarte เข้าด้วยกัน มาถึงแล้ว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

มันใช้งานได้กับ statement ง่ายๆมี 11 ชนิดใน python 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

ธาดา, วิเคราะห์, '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 ไม่ระบุชื่อ

หวังว่านี่จะช่วยได้


2

มันเป็นฟังก์ชั่นที่ไม่มีชื่อ เช่นใน c # คุณสามารถใช้

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

เพื่อส่งกลับตัวเลขที่มากกว่า 5

number => number > 5

เป็นส่วนแลมบ์ดาที่นี่ เพราะมันหมายถึงฟังก์ชั่นซึ่งใช้พารามิเตอร์ (จำนวน) และส่งกลับค่าบูลีน (หมายเลข> 5) GetMatchingItems วิธีการใช้แลมบ์ดานี้ในรายการทั้งหมดในคอลเลกชันและส่งกลับรายการที่ตรงกัน


2

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

2

ในบริบทของ CS ฟังก์ชั่นแลมบ์ดาเป็นแนวคิดทางคณิตศาสตร์ที่เป็นนามธรรมที่จัดการปัญหาของการประเมินเชิงสัญลักษณ์ของการแสดงออกทางคณิตศาสตร์ ในบริบทที่ฟังก์ชั่นแลมบ์ดาเป็นเช่นเดียวกับระยะแลมบ์ดา

แต่ในการเขียนโปรแกรมภาษามันเป็นสิ่งที่แตกต่าง มันเป็นรหัสชิ้นหนึ่งที่ถูกประกาศว่า "เข้าแทนที่" และสามารถส่งผ่านได้ในฐานะ "พลเมืองชั้นหนึ่ง" แนวคิดนี้ดูเหมือนจะมีประโยชน์เพื่อให้เป็นภาษาการเขียนโปรแกรมสมัยใหม่ที่เป็นที่นิยมเกือบทั้งหมด (ดูฟังก์ชั่นแลมบ์ดาทุกที่ที่โพสต์)


2

A Lambda Functionหรือ a Small Anonymous Functionเป็นบล็อกที่มีในตัวเองของฟังก์ชันการทำงานที่สามารถส่งผ่านและใช้ในรหัสของคุณ แลมบ์ดามีชื่อที่แตกต่างกันในการเขียนโปรแกรมภาษาที่แตกต่างกัน - LambdaในหลามและKotlin , Closureในสวิฟท์หรือBlockในCและวัตถุประสงค์ -C แม้ว่าความหมายของแลมบ์ดาจะค่อนข้างคล้ายกับภาษาเหล่านี้ แต่บางครั้งก็มีความแตกต่างเล็กน้อย

เรามาดูกันว่าแลมบ์ดา (การปิด) ทำงานใน Swift 4.2 ด้วยวิธีการเรียง () - จากฟังก์ชั่นปกติจนถึงการแสดงออกที่สั้นที่สุด:

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. ผลตอบแทนโดยนัยจากการปิด Single-Expression

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

6. ชื่ออาร์กิวเมนต์แบบย่อ

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

// $0 and $1 are closure’s first and second String arguments.

7. วิธีการใช้งาน

reverseOrder = coffee.sorted(by: >)

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

หวังว่านี่จะช่วยได้


1

ฉันก็เข้าใจเหมือนกัน ฉันเคยลองใช้ JS กับอันนี้แล้ว:

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

มันเพิ่ม 2 ถึง 4 จากนั้น mults ผลลัพธ์ด้วย 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 ถึงมีพลัง


1

ในการเขียนโปรแกรมคอมพิวเตอร์แลมบ์ดาเป็นชิ้นส่วนของรหัส (คำสั่งการแสดงออกหรือกลุ่มของพวกเขา) ซึ่งรับเอาอาร์กิวเมนต์บางอย่างจากแหล่งภายนอก มันจะต้องไม่ใช่ฟังก์ชั่นนิรนามเสมอไป - เรามีหลายวิธีในการนำไปใช้

เรามีการแยกชัดเจนระหว่างสำนวนคำสั่งและฟังก์ชั่นซึ่งนักคณิตศาสตร์ไม่ได้มี

คำว่า "ฟังก์ชั่น" ในการเขียนโปรแกรมก็แตกต่างกัน - เรามี "ฟังก์ชั่นเป็นชุดของขั้นตอนที่ต้องทำ" (จากภาษาละติน "ดำเนินการ") ในทางคณิตศาสตร์มันเกี่ยวกับความสัมพันธ์ระหว่างตัวแปร

ภาษาที่ใช้งานได้พยายามที่จะคล้ายกับสูตรคณิตศาสตร์มากที่สุดเท่าที่จะเป็นไปได้และคำของพวกเขาก็มีความหมายเหมือนกัน แต่ในภาษาโปรแกรมอื่นเรามีความแตกต่าง


0

ตอบคำถามแล้วฉันไม่ต้องการทราบรายละเอียด ฉันต้องการแบ่งปันการใช้งานเมื่อเขียนการคำนวณเชิงตัวเลขในสนิม

มีตัวอย่างของแลมบ์ดา (ฟังก์ชั่นนิรนาม)

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

เมื่อฉันกำลังเขียนโมดูลของวิธีการ Newton - Raphson มันถูกใช้เป็นอนุพันธ์อันดับหนึ่งและสอง (หากคุณต้องการทราบวิธีการของนิวตัน –Raphson คืออะไรโปรดไปที่ " 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

0

ลองนึกภาพว่าคุณมีร้านอาหารที่มีตัวเลือกการจัดส่งและคุณมีคำสั่งซื้อที่ต้องทำภายใน 30 นาที ประเด็นก็คือลูกค้ามักจะไม่สนใจว่าคุณส่งอาหารด้วยจักรยานด้วยรถยนต์หรือเท้าเปล่าตราบใดที่คุณยังอุ่นอาหารอยู่เสมอ ดังนั้นให้แปลงสำนวนนี้เป็น Javascript ด้วยฟังก์ชั่นการขนส่งที่ไม่ระบุชื่อและที่กำหนดไว้

ด้านล่างเรากำหนดวิธีการส่งมอบของเรา aka เรากำหนดชื่อให้กับฟังก์ชั่น:

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

จะเกิดอะไรขึ้นถ้าเราจะใช้ฟังก์ชั่น arrow / lambda เพื่อให้การถ่ายโอนนี้สำเร็จ:

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

คุณเห็นว่าไม่มีความแตกต่างสำหรับลูกค้าและไม่ต้องเสียเวลาคิดเกี่ยวกับวิธีการส่งอาหาร เพียงส่งมัน

Btw ฉันไม่แนะนำ kebap ด้วยโค้กนี่คือสาเหตุที่โค้ดด้านบนจะทำให้คุณมีข้อผิดพลาด มีความสุข.

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.