กลับไปหน้าบทความ

อ่าน 8 นาที

ฟังก์ชันนิรนาม

ในการเขียนโปรแกรมคอมพิวเตอร์ฟังก์ชันนิรนาม ( ฟังก์ชันลิเทอรัลฟังก์ชันแลมบ์ดาหรือบล็อก ) คือ คำจำกัดความของ

ฟังก์ชันนิรนาม

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

ฟังก์ชันนิรนามมีต้นกำเนิดมาจากผลงานของAlonzo Churchในการคิดค้นแคลคูลัสแลมบ์ดาซึ่งฟังก์ชันทั้งหมดเป็นฟังก์ชันนิรนามในปี 1936 ก่อนที่จะมีคอมพิวเตอร์อิเล็กทรอนิกส์[ 2 ]ในภาษาโปรแกรมหลายภาษา ฟังก์ชันนิรนามจะถูกนำเสนอโดยใช้คำหลักlambdaและฟังก์ชันนิรนามมักถูกเรียกว่าlambdasหรือlambda abstractionsฟังก์ชันนิรนามเป็นคุณลักษณะของภาษาโปรแกรมมาตั้งแต่Lispในปี 1958 และภาษาโปรแกรมสมัยใหม่จำนวนมากขึ้นเรื่อยๆ รองรับฟังก์ชันนิรนาม

ชื่อ

ชื่อ "lambda abstraction", "lambda function" และ "lambda expression" หมายถึงสัญลักษณ์ของการสร้างฟังก์ชันในแคลคูลัสแลมบ์ดา โดยที่ฟังก์ชันปกติจะเขียนด้วยและคือนิพจน์ที่ใช้เปรียบเทียบกับไวยากรณ์ของ Python ที่ใช้ lambdax:M

ชื่อ "ฟังก์ชันลูกศร" หมายถึงสัญลักษณ์ทางคณิตศาสตร์ " แมปไปยัง " เปรียบเทียบกับไวยากรณ์ JavaScript ของ[ 3 ]x=>M

การใช้งาน

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

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

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

ตัวอย่างต่อไปนี้เขียนด้วยภาษา Python 3

การเรียงลำดับ

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

ลองพิจารณาโค้ด Python นี้ที่เรียงลำดับรายการสตริงตามความยาวของสตริง:

a : list [ str ] = [ "house" , "car" , "bike" ] a . sort ( key = lambda x : len ( x )) print ( a ) # พิมพ์ ['car', 'bike', 'house']

ฟังก์ชันนิรนามในตัวอย่างนี้คือ นิพจน์แลมบ์ดา:

แลมบ์ดาx : len ( x )

ฟังก์ชันนิรนามนี้รับอาร์กิวเมนต์หนึ่งตัวxและส่งคืนความยาวของอาร์กิวเมนต์ ซึ่งเมธอดจะใช้sort()เป็นเกณฑ์ในการเรียงลำดับ

ไวยากรณ์พื้นฐานของฟังก์ชันแลมบ์ดาใน Python คือ

แลมบ์ดาอาร์กิวเมนต์ 1 , อาร์กิวเมนต์ 2 , อาร์กิวเมนต์ 3 , ... : < การดำเนินการกับอาร์กิวเมนต์และส่งคืนค่า>

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

จากการพิมพ์นำเข้าCallableadd : Callable [[ int ], int ] = lambda a : a + a print ( add ( 20 )) # พิมพ์ 40

อีกตัวอย่างหนึ่งคือการเรียงลำดับรายการในลิสต์ตามชื่อคลาส (ใน Python ทุกอย่างมีคลาส):

a : list [ int | str ] = [ 10 , "number" , 11.2 ] a . sort ( key = lambda x : x . __class__ . __name__ ) print ( a ) # พิมพ์ [11.2, 10, 'number']

โปรดสังเกตว่า11.2มีชื่อคลาส " float", 10มีชื่อคลาส " int", และ'number'มีชื่อคลาส " str" ลำดับการเรียงคือ " float", " int", จากนั้น " str"

การปิด

Closure คือฟังก์ชันที่ถูกประเมินค่าในสภาพแวดล้อมที่มีตัวแปรที่ถูกผูกไว้ตัวอย่างต่อไปนี้ผูกตัวแปร "threshold" ไว้ภายในฟังก์ชันนิรนามที่เปรียบเทียบค่าอินพุตกับค่าเกณฑ์นี้

def comp ( threshold : int ) -> Callable [[ int ], bool ]: return lambda x : x < threshold

สิ่งนี้สามารถใช้เป็นตัวสร้างฟังก์ชันเปรียบเทียบได้:

func_a : Callable [[ int ], bool ] = comp ( 10 ) func_b : Callable [[ int ], bool ] = comp ( 20 )พิมพ์( func_a ( 5 ), func_a ( 8 ), func_a ( 13 ), func_a ( 21 )) # พิมพ์ True True False Falseพิมพ์( func_b ( 5 ), func_b ( 8 ), func_b ( 13 ), func_b ( 21 )) # พิมพ์ True True True False

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

เคอร์รี่

การใช้ Currying จะแปลงฟังก์ชันที่รับอาร์กิวเมนต์หลายตัวให้เป็นลำดับของฟังก์ชันแต่ละฟังก์ชันรับอาร์กิวเมนต์เพียงตัวเดียว ในตัวอย่างนี้ ฟังก์ชันที่ทำการหารด้วยจำนวนเต็มใดๆ จะถูกแปลงเป็นฟังก์ชันที่ทำการหารด้วยจำนวนเต็มที่กำหนดไว้

def divide ( x : int , y : int ) -> float : return x / ydef divisor ( d : int ) -> Callable [[ int ], float ]: return lambda x : divide ( x , d )ครึ่ง: Callable [[ int ], float ] = divisor ( 2 ) ที่สาม: Callable [[ int ], float ] = divisor ( 3 )พิมพ์( ครึ่ง( 32 ), ที่สาม( 32 )) # พิมพ์ 16.0 10.666666666666666พิมพ์( ครึ่ง( 40 ), สาม( 40 )) # พิมพ์ 20.0 13.333333333333334

แม้ว่าการใช้ฟังก์ชันนิรนามอาจจะไม่เป็นที่นิยมมากนักในการทำเคอร์รี แต่ก็ยังสามารถใช้งานได้ ในตัวอย่างข้างต้น ฟังก์ชัน divisor สร้างฟังก์ชันที่มีตัวหารที่กำหนดไว้ ฟังก์ชัน half และ third ทำเคอร์รีฟังก์ชัน divide ที่มีตัวหารคงที่

ฟังก์ชันตัวหารยังสร้างโคลสโดยการผูกตัวแปรอีกdด้วย

ฟังก์ชันลำดับสูงกว่า

ฟังก์ชันลำดับสูง (Higher-order function)คือฟังก์ชันที่รับฟังก์ชันอื่นเป็นอาร์กิวเมนต์ หรือส่งคืนฟังก์ชันอื่นเป็นผลลัพธ์ เทคนิคนี้มักใช้เพื่อปรับแต่งพฤติกรรมของฟังก์ชันที่กำหนดไว้ทั่วไป เช่น ลูปหรือรูปแบบการเรียกซ้ำ ฟังก์ชันนิรนามเป็นวิธีที่สะดวกในการระบุอาร์กิวเมนต์ของฟังก์ชันดังกล่าว ตัวอย่างต่อไปนี้เขียนด้วย Python 3

แผนที่

ฟังก์ชัน `map` จะเรียกใช้ฟังก์ชันกับแต่ละองค์ประกอบในลิสต์ ตัวอย่างต่อไปนี้จะยกกำลังสองทุกองค์ประกอบในอาร์เรย์โดยใช้ฟังก์ชันนิรนาม

a : list [ int ] = [ 1 , 2 , 3 , 4 , 5 , 6 ] print ( list ( map ( lambda x : x * x , a ))) # พิมพ์ [1, 4, 9, 16, 25, 36]

ฟังก์ชันนิรนามรับอาร์กิวเมนต์และส่งคืนค่ากำลังสองของอาร์กิวเมนต์นั้น รูปแบบข้างต้นไม่ได้รับการสนับสนุนจากผู้สร้างภาษา ซึ่งยืนยันว่ารูปแบบที่แสดงด้านล่างมีความหมายเดียวกันและสอดคล้องกับปรัชญาของภาษามากกว่า:

a : list [ int ] = [ 1 , 2 , 3 , 4 , 5 , 6 ] print ([ x * x for x in a ]) # พิมพ์ [1, 4, 9, 16, 25, 36]

กรอง

ฟังก์ชัน filter จะส่งคืนองค์ประกอบทั้งหมดจากลิสต์ที่ประเมินค่าเป็น True เมื่อส่งไปยังฟังก์ชันที่กำหนด

a : list [ int ] = [ 1 , 2 , 3 , 4 , 5 , 6 ] print ( list ( filter ( lambda x : x % 2 == 0 , a ))) # พิมพ์ [2, 4, 6]

ฟังก์ชันนิรนามจะตรวจสอบว่าค่าที่ส่งเข้ามาเป็นเลขคู่หรือไม่ เช่นเดียวกับฟังก์ชัน map รูปแบบด้านล่างนี้ถือว่าเหมาะสมกว่า:

a : list [ int ] = [ 1 , 2 , 3 , 4 , 5 , 6 ] print ([ x for x in a if x % 2 == 0 ]) # พิมพ์ [2, 4, 6]

พับ

ฟังก์ชัน `fold` จะวนซ้ำไปทีละองค์ประกอบในโครงสร้าง (สำหรับลิสต์มักจะวนจากซ้ายไปขวา เรียกว่า "left fold" reduceใน Python) โดยจะสะสมค่าไปเรื่อยๆ สามารถใช้เพื่อรวมองค์ประกอบทั้งหมดของโครงสร้างเข้าเป็นค่าเดียวได้ เช่น:

a : list [ int ] = [ 1 , 2 , 3 , 4 , 5 ] print ( functools . reduce ( lambda x , y : x * y , a )) # พิมพ์ 120

สิ่งนี้ทำงาน

ฟังก์ชันนิรนามในที่นี้คือการคูณของอาร์กิวเมนต์ทั้งสอง

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

รายชื่อภาษา

ต่อไปนี้คือรายชื่อภาษาโปรแกรมที่รองรับฟังก์ชันนิรนามที่ไม่มีชื่ออย่างสมบูรณ์ หรือบางส่วนในรูปแบบต่างๆ หรือไม่รองรับเลย

ตารางต่อไปนี้แสดงให้เห็นถึงรูปแบบทั่วไปหลายประการ ที่น่าสังเกตคือ ภาษาอย่างC , PascalและObject Pascalซึ่งโดยทั่วไปไม่รองรับฟังก์ชันนิรนามนั้น ล้วนเป็น ภาษา ที่มีการกำหนดประเภทข้อมูลแบบคงที่อย่างไรก็ตาม ภาษาที่มีการกำหนดประเภทข้อมูลแบบคงที่สามารถรองรับฟังก์ชันนิรนามได้ ตัวอย่างเช่น ภาษา MLเป็นภาษาที่มีการกำหนดประเภทข้อมูลแบบคงที่และโดยพื้นฐานแล้วมีฟังก์ชันนิรนามอยู่แล้ว และDelphiซึ่งเป็นภาษาถิ่นของObject Pascalได้รับการขยายให้รองรับฟังก์ชันนิรนาม เช่นเดียวกับC++ (ตาม มาตรฐาน C++11 ) ประการที่สอง ภาษาที่ถือว่าฟังก์ชันเป็นฟังก์ชันชั้นหนึ่ง ( Dylan , Haskell , JavaScript , Lisp , ML , Perl , Python , Ruby , Scheme ) โดยทั่วไปจะรองรับฟังก์ชันนิรนาม เพื่อให้สามารถกำหนดและส่งต่อฟังก์ชันได้ง่ายเหมือนกับชนิดข้อมูลอื่นๆ

ตัวอย่าง

ดูเพิ่มเติม

  • เมธอดนิรนาม - ควรใช้เมื่อใด? (บทความเกี่ยวกับฟังก์ชันนิรนามใน Delphi)
  • การคอมไพล์นิพจน์แลมบ์ดา: Scala เทียบกับ Java 8
  • ฟังก์ชันนิรนามของ PHPฟังก์ชันนิรนามของ PHP
  • ฟังก์ชันแลมบ์ดาในภาษาโปรแกรมต่างๆ
  • ฟังก์ชันในภาษาโก
ดึงข้อมูลมาจาก " https://en.wikipedia.org/w/index.php?title=Anonymous_function&oldid=1359095083 "

สรุปเนื้อหา

ข้อมูลสำคัญจากบทความ

ข้อมูลสำคัญเกี่ยวกับ ฟังก์ชันนิรนาม

ในการเขียนโปรแกรมคอมพิวเตอร์ฟังก์ชันนิรนาม ( ฟังก์ชันลิเทอรัลฟังก์ชันแลมบ์ดาหรือบล็อก ) คือ คำจำกัดความของ

ชื่อ

ชื่อ "lambda abstraction", "lambda function" และ "lambda expression" หมายถึงสัญลักษณ์ของการสร้างฟังก์ชันในแคลคูลัสแลมบ์ดา โดยที่ฟังก์ชันปกติจะเขียนด้วยและคือนิพจน์ที่ใช้เปรียบเทียบกับไวยากรณ์ของ Python ที่ใช้ เอฟ ( x ) = เอ็ม {\displaystyle f(x)=M} ( λ x .

การใช้งาน

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

การเรียงลำดับ

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