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


54

ฉันสับสนเล็กน้อยเกี่ยวกับ 'ฟังก์ชั่น' และ 'แลมบ์ดา' ฉันเคยเห็นตัวอย่างบางส่วนที่แสดงว่าคำหลักแบบแผนlambdaทำงานคล้ายกับคำหลัก JavaScript functionแต่ฉันไม่รู้ว่าเกี่ยวข้องกันอย่างไร

ฉันบอกว่า 'function' และ 'method' สามารถใช้แทนกันได้เมื่อพูดถึงวัตถุใน. net ฉันสงสัยว่า 'แลมบ์ดา' และ 'ฟังก์ชั่น' ในทำนองเดียวกันหมายถึงสิ่งเดียวกัน ฉันสงสัยว่า 'แลมบ์ดา' มีความหมายลึกลับบางอย่างหรือไม่เนื่องจากเห็นว่าตัวอักษรกรีกแลมบ์ดา (λ) ปรากฏในอวตารมากมายในไซต์นี้ ในการทำให้สิ่งต่าง ๆ สับสนมากขึ้นใน. net ส่วนการทำงานของ C # หมายถึงนิพจน์ฟังก์ชันที่ส่งผ่านไปยังฟังก์ชันอื่นเป็น 'แลมบ์ดานิพจน์' ดังนั้นคำนี้ดูเหมือนจะอยู่ทั่วทุกแห่ง

ฉันยังคุ้นเคยกับคำว่า 'lambda แคลคูลัส' ด้วย

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


3
Nitpick - พวกเขาถูกเรียกว่า "การแสดงออกแลมบ์ดา" ไม่ใช่ "ฟังก์ชั่นแลมบ์ดา" อย่างน้อยที่สุดเท่าที่ C # /. เอกสาร NET จะดำเนินต่อไป
Oded

@ TWith2Sugars - อ่านข้อความ คำตอบของคุณมีคุณภาพต่ำเนื่องจากมันเป็นเพียงลิงก์ดังนั้นจึงเปลี่ยนเป็นความคิดเห็น
Oded

17
I wonder if 'lambda' has some esoteric meaning, seeing that the Greek letter lambda (λ) appears in so many avatars on this site.ใครจะหวังว่ามันจะเป็นการอ้างอิงถึงแคลคูลัสแลมบ์ดา แต่ฉันมีความรู้สึกแปลก ๆ ที่Half Lifeคือการตำหนิอวตารแลมบ์ดา
yannis

3
ยุติธรรมพอนี่คือลิงก์ไปยังคำตอบของstackoverflow
TWith2Sugars

@ZaphodBeeblebrox: ฉันสงสัยว่าคุณถูกต้องเกี่ยวกับ Half-Life อิทธิพล : /
FrustratedWithFormsDesigner

คำตอบ:


44

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

ความแตกต่างระหว่างคีย์เวิร์ด lambda ของสกีมและคีย์เวิร์ดฟังก์ชันของ Javascript คือสามารถใช้เพื่อสร้างทั้งฟังก์ชั่นที่ไม่ระบุชื่อและฟังก์ชั่นที่มีชื่อในขณะที่ในอดีตจะสร้างฟังก์ชั่นที่ไม่ระบุdefineชื่อเท่านั้น

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


1
นั่นหยาบมาก คุณใช้define(หรือletหรือหนึ่งในญาติของมันหรือการกำหนดภายใน) เพื่อสร้างชื่อ - นั่นคือทั้งหมดที่ ไม่มีอะไรพิเศษdefineเกี่ยวกับฟังก์ชั่น
Eli Barzilay

2
@EliBarzilay ดีdefine ไม่ได้มีรูปแบบพิเศษสำหรับการกำหนดฟังก์ชั่น (เช่นคุณสามารถเขียน(define (f x) (foo))แทน(define f (lambda (x) (foo)))) แต่จุดของฉันคือการที่คุณไม่สามารถสร้างชื่อฟังก์ชั่นการใช้lambdaเพียงอย่างเดียวคือคุณไม่สามารถเขียนสิ่งที่ชอบ(lambda f (x) (foo))ที่จะกำหนดฟังก์ชั่นที่มีชื่อว่าfที่ใช้เวลาหนึ่งอาร์กิวเมนต์อย่างที่คุณสามารถทำได้กับfunctionคำหลักของ Javascript
sepp2k

1
defineมีที่เป็นน้ำตาล syntactic ดังนั้นจึงไม่สำคัญเท่ากับบทบาทของมันเป็นเครื่องมือผูกชื่อสำหรับค่าทั้งหมด สำหรับการlambdaไม่สร้างชื่อด้วยตัวเอง: นั่นเป็นคุณสมบัติที่สำคัญเนื่องจากแยกชื่อที่ให้จากรูปแบบฟังก์ชัน ... IMO JS กำลังทำสิ่งที่ถูกต้องเพื่อให้สามารถแยกได้ในขณะเดียวกันก็ยอมรับชื่อที่เป็นตัวเลือกสำหรับคนที่น่ากลัว แนวคิดของฟังก์ชันที่ไม่มีชื่อ (และโชคดีที่ขนาดของมวลชนเหล่านั้นตกต่ำทั่วไป ... )
Eli Barzilay

18

แลมบ์ดาเป็นเพียงฟังก์ชั่นนิรนาม - ฟังก์ชั่นที่ไม่มีชื่อ


4
หมายเหตุค่อนข้างดี: แลมบ์ดาสามารถมีสถานะ (ตามที่ปิด) ที่พวกเขาขัดขวางจากบริบทที่พวกเขาจะประกาศ
Martin York

7
ฟังก์ชั่นที่มีชื่อดังนั้นถ้าภาษาช่วยให้คุณประกาศฟังก์ชันที่ซ้อนกัน
cHao

4
ความรุ่งโรจน์ที่ทำให้มันกลายเป็นแท็บรีวิว "โพสต์คุณภาพต่ำ" พร้อมคำตอบที่ยกระดับขึ้น
yannis

@ZaphodBeeblebrox - ไม่ได้ตั้งใจฉันรับรองได้เลยว่า
Oded

ไม่จริงการlambdaแสดงออกใน Scheme นั้นเหมือนกับการfunctionแสดงออกที่ไม่มีชื่อ - แต่ไม่มีอะไรหยุดคุณจากการตั้งชื่อพวกเขาในภายหลัง var f = [function(x){return x;}][0]เช่น คุณสามารถยืนยันว่าค่าฟังก์ชั่นของตัวเองไม่มีชื่อ แต่ที่จะเป็นจริงสำหรับฟังก์ชั่นทั้งหมด ...
อีไล Barzilay


8

ในฟังก์ชั่น C # Anonymousเป็นคำศัพท์ทั่วไปที่มีทั้งการแสดงออกแลมบ์ดาและวิธีการไม่ระบุชื่อ

การแสดงออกของแลมบ์ดาสามารถแยกออกเป็นนิพจน์แลมบ์ดาและแลมบ์ดารายงานได้

แลมบ์ดาแสดงออก:

(int x, string y) => x == y.Length 

แลมบ์ดาแถลงจะคล้ายกับนิพจน์แลมบ์ดายกเว้นคำแถลงที่อยู่ในเครื่องหมายวงเล็บ:

(int x, string y) => {
         if (x == y.Length) {
             Console.WriteLine(y);
         }
}

เมื่อเราพูดถึงแลมบ์ดานิพจน์ใน JavaScript นั้นโดยพื้นฐานแล้วหมายถึงการใช้ฟังก์ชั่นเป็นอาร์กิวเมนต์ในการเรียกไปยังฟังก์ชั่นอื่น

var calculate = function(x, y, operation){
    return operation(x, y);
}

// we're passing anonymous function as a third argument
calculate(10, 15, function(x, y) {
    return x + y;
}); // 25

+1 ผู้คนจำนวนมากได้กล่าวว่า lambdas เป็นฟังก์ชันที่ไม่ระบุตัวตน แต่มีมากกว่านั้น ร่างกาย (ด้านขวา) ของแลมบ์ดามักจะแสดงออกมากกว่าเป็นบล็อกข้อความ เนื้อความของฟังก์ชั่นที่ตั้งชื่อว่าเป็นนิพจน์นั้นได้รับอนุญาต (หรือจำเป็น) ในภาษาที่ใช้งานได้ แต่ไม่ใช่ภาษาที่จำเป็น
Zantier

4

TL; DR ในขณะที่คนอื่น ๆ ชี้: สัญกรณ์แลมบ์ดาเป็นเพียงวิธีการกำหนดฟังก์ชั่นโดยไม่ต้องถูกบังคับให้ตั้งชื่อพวกเขา

รุ่นยาว

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

ขอเริ่มต้นด้วยการแสดงออกเช่นและ1 + 2 x + 2ตัวอักษรเช่น1และ2เรียกว่าค่าคงที่เพราะมันถูกผูกไว้กับค่าคงที่ที่เฉพาะเจาะจง

ตัวระบุเช่นxเรียกว่าตัวแปรและเพื่อประเมินคุณต้องผูกมันกับค่าบางอย่างก่อน ดังนั้นโดยทั่วไปคุณไม่สามารถประเมินได้x + 1ตราบใดที่คุณไม่รู้ว่าxเป็นอะไร

สัญกรณ์แลมบ์ดาให้สคีมาสำหรับการผูกค่าอินพุตเฉพาะกับตัวแปร แสดงออกแลมบ์ดาสามารถเกิดขึ้นโดยการเพิ่มในหน้าของการแสดงออกที่มีอยู่เช่นλx . λx . x + 1ตัวแปรxกล่าวจะฟรีในx + 1และผูกพันในλx . x + 1

สิ่งนี้ช่วยในการประเมินนิพจน์ได้อย่างไร หากคุณป้อนค่าให้กับนิพจน์แลมบ์ดาเช่นนั้น

(λx . x + 1) 2

จากนั้นคุณสามารถประเมินนิพจน์ทั้งหมดโดยการแทนที่ (การผูก) การเกิดขึ้นทั้งหมดของตัวแปรxด้วยค่า 2:

(λx . x + 1) 2
      2 + 1
      3

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

  • ในภาษาที่ใช้งานได้อย่างหมดจดเช่น Haskell นิพจน์แลมบ์ดาเป็นตัวแทนของฟังก์ชันในแง่คณิตศาสตร์: ค่าอินพุตจะถูกส่งเข้าไปในร่างกายของแลมบ์ดาและสร้างค่าเอาต์พุต
  • ในหลายภาษา (เช่น JavaScript, Python, Scheme) การประเมินเนื้อความของแลมบ์ดานิพจน์สามารถมีผลข้างเคียง ในกรณีนี้เราสามารถใช้คำว่าโพรซีเดอร์เพื่อทำเครื่องหมายความแตกต่างของฟังก์ชั่น wrt pure

นอกเหนือจากความแตกต่างสัญกรณ์แลมบ์ดานั้นเกี่ยวกับการกำหนดพารามิเตอร์ที่เป็นทางการและผูกเข้ากับพารามิเตอร์ที่แท้จริง

ขั้นตอนต่อไปคือการตั้งชื่อฟังก์ชั่น / ขั้นตอน ในหลายภาษาฟังก์ชันมีค่าเหมือนกันดังนั้นคุณจึงสามารถตั้งชื่อฟังก์ชั่นได้ดังนี้

(define f (lambda (x) (+ x 1)))      ;; Scheme

f = \x -> x + 1                      -- Haskell

val f: (Int => Int) = x => x + 1     // Scala

var f = function(x) { return x + 1 } // JavaScript

f = lambda x: x + 1                  # Python

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

(define n 42)   ;; Scheme

n = 42          -- Haskell

val n: Int = 42 // Scala

var n = 42      // JavaScript

n = 42          # Python

ในภาษาเหล่านี้คุณสามารถผูกฟังก์ชันกับชื่อโดยใช้สัญลักษณ์ที่คุ้นเคย (แต่เทียบเท่า):

(define (f x) (+ x 1))         ;; Scheme

f x = x + 1                    -- Haskell

def f(x: Int): Int = x + 1     // Scala

function f(x) { return x + 1 } // JavaScript

def f(x): return x + 1         # Python

บางภาษาเช่น C สนับสนุนเฉพาะเครื่องหมายหลังเพื่อกำหนด (ชื่อ) ฟังก์ชั่น

ปิด

บางข้อสังเกตขั้นสุดท้ายเกี่ยวกับการปิด x + yพิจารณาการแสดงออก สิ่งนี้มีตัวแปรอิสระสองตัว หากคุณผูกxโดยใช้เครื่องหมายแลมบ์ดาคุณจะได้รับ:

\x -> x + y

นี้ไม่ได้ (ยัง) yฟังก์ชั่นเนื่องจากยังคงมีตัวแปรฟรี คุณสามารถสร้างฟังก์ชั่นจากฟังก์ชั่นนี้โดยการผูกyเช่นกัน:

\x -> \y -> x + y

หรือ

\x y -> x + y

ซึ่งเป็นเช่นเดียวกับ+ฟังก์ชั่น

แต่คุณสามารถผูกพูดyด้วยวิธีอื่น (*):

incrementBy y = \x -> x + y

ผลลัพธ์ของการใช้ฟังก์ชัน incrementBy กับตัวเลขคือการปิดเช่นฟังก์ชัน / โพรซีเดอร์ที่เนื้อความมีตัวแปรอิสระ (เช่นy) ที่ถูกผูกไว้กับค่าจากสภาพแวดล้อมที่กำหนดการปิด

ดังนั้นincrementBy 5เป็นฟังก์ชั่น (ปิด) ที่เพิ่มขึ้นจำนวน 5

บันทึก (*)

ฉันกำลังโกงที่นี่:

incrementBy y = \x -> x + y

เทียบเท่ากับ

incrementBy = \y -> \x -> x + y

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


ฉันแค่ขอทาน แต่ฉันคิดว่ามันอาจจะสับสนเล็กน้อยถ้าคุณพยายามเข้าใจแคลคูลัสในแง่คณิตศาสตร์เนื่องจากสิ่งที่คุณเรียกว่าค่าคงที่เรียกว่าตัวแปรและแสดงโดยสัญลักษณ์ a, b, c ... เรียกตัวแปรจะเป็นตัวแปรบึกบึน x บนมืออื่น ๆ 1 λ x x 2 คือλ x f ( f x ) และอื่น ๆ
jinawee

@ Jinawee: ฉันยอมรับว่าฉันไม่ได้ค้นหาคำจำกัดความที่แน่นอน ฉันจำได้ว่าใช้ตัวแปรเงื่อนไขและค่าคงที่ในตรรกะ ที่นั่นค่าคงที่คือสัญลักษณ์ที่ถูกแมปกับโดเมนในขณะที่ตัวแปรเป็นสัญลักษณ์ที่คุณสามารถหาปริมาณได้ แต่อีกครั้ง (1) มันเป็นเวลานานแล้วตั้งแต่ฉันเรียนวิชาตรรกะและ (2) แลมบ์ดา - แคลคูลัสไม่จำเป็นต้องทำตามแนวคิดของคณิตศาสตร์ตรรกะ 1-1 หากคุณชี้ให้ฉันอ้างอิงฉันสามารถลองและแก้ไขคำศัพท์ของฉัน
Giorgio

0

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

ใน JavaScript ES6 (2015) มีไวยากรณ์สั้นเพื่อกำหนด lambdas เรียกว่า"ฟังก์ชั่นลูกศร" ใน C # ไวยากรณ์ดังกล่าวเป็นที่รู้จักใน .NET 3.0 (ประมาณ 2006)

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

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