ฟังก์ชั่นชั้นหนึ่ง


11

ฉันเริ่มดู Lisp อย่างจริงจังในสุดสัปดาห์นี้ (ซึ่งฉันหมายถึงฉันเพิ่งได้เรียนรู้ Lisp และไม่คืนกลับสู่โครงการใน C #) และต้องบอกว่าฉันรักมัน ฉันได้ขลุกกับภาษาอื่น ๆ ที่ใช้งานได้ (F #, Haskell, Erlang) แต่ไม่ได้รู้สึกว่า Lisp ให้ฉันมา

ตอนนี้เมื่อฉันเรียนรู้ LISP ฉันก็เริ่มสงสัยว่าทำไมภาษาที่ไม่สามารถใช้งานได้ไม่รองรับฟังก์ชั่นชั้นหนึ่ง ฉันรู้ว่าภาษาเช่น C # สามารถทำสิ่งที่คล้ายกันกับผู้ได้รับมอบหมายและเท่าที่คุณสามารถใช้ตัวชี้เพื่อทำงานใน C / C ++ แต่มีเหตุผลว่าทำไมสิ่งนี้จะไม่กลายเป็นคุณสมบัติในภาษาเหล่านั้น? มีข้อเสียเปรียบในการทำฟังก์ชั่นชั้นหนึ่งหรือไม่? สำหรับฉันแล้วมันมีประโยชน์อย่างมากดังนั้นฉันจึงหลงทางว่าทำไมภาษาอื่น ๆ (นอกกระบวนทัศน์การทำงาน) จึงไม่ได้นำมาใช้

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


3
ฉันไม่เห็นด้วยที่ C # สามารถทำ "สิ่งที่คล้ายกัน" ฉันจะบอกว่ามันมีฟังก์ชั่นชั้นหนึ่งสำหรับทุกเจตนาและวัตถุประสงค์ (ซึ่งเป็นสถานที่ปรักหักพังหลักฐานของคุณ) มันมีซินแทกซ์สำหรับฟังก์ชั่นสัญลักษณคุณสามารถใส่ฟังก์ชั่นเป็นตัวแปร ฯลฯ
Logan Capaldo

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

2
รายการวิกิพีเดียนั้นล้าสมัยแล้ว C # ที่ทันสมัยให้แลมบ์ดาที่เหมาะสม
SK-logic

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

1
@Logan & SK-Logic - ฉันขอขอบคุณความคิดเห็นของคุณและยังคงความสร้างสรรค์ ฉันยังคงเรียนรู้อยู่และเป็นสิ่งที่ดีมากที่จะไม่ถูกเผาไหม้ดังนั้นฉันจึงขอขอบคุณ ขอบคุณมากสำหรับความคิดเห็นและคำตอบ!
Jetti

คำตอบ:


5

C #, VB.NET, Python, JavaScript ตอนนี้แม้แต่ C ++ 0x ยังมีฟังก์ชั่นชั้นหนึ่ง

ปรับปรุง:

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

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

แนวคิดดังกล่าวทั้งหมดต้องใช้เวลาในการย่อยโดยอุตสาหกรรม


ฉันแก้ไขคำถามเดิมตามคำตอบแล้ว
Jetti

ฟังก์ชั่นชั้นหนึ่ง! = การปิด (และ GC มีความจำเป็นอย่างมากสำหรับหลัง) แม้ว่าใช่พวกเขามีความสัมพันธ์อย่างใกล้ชิดและคุณไม่ค่อยเห็นพวกเขาแยกจากกัน

@delnan อย่างน้อยที่สุดก็ไม่มีรูปแบบของฟังก์ชั่นการปิดคำศัพท์บางอย่างที่ไม่สามารถจัดเรียงและไม่สามารถสร้างได้ในเวลาทำงานซึ่งเป็นสิ่งจำเป็นสำหรับคำนิยามฟังก์ชั่นชั้นหนึ่ง
SK-logic

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

1
@ SK-logic: C ++ 0x ให้การปิดโดยไม่มีการรวบรวมขยะด้วยกลลวงปกติ -> หากตัวแปรไม่อยู่ในขอบเขตและคุณยังคงยึดติดกับการอ้างอิงโดยใช้การอ้างอิงนั้นเป็นพฤติกรรมที่ไม่ได้กำหนด ดังนั้นมันจึงเป็นไปได้ ... มันแค่สร้างเกียรติแก่ผู้พัฒนา
Matthieu M.

5

ฟังก์ชั่นชั้นหนึ่งนั้นมีความน่าสนใจน้อยลงโดยไม่ต้องปิด

การปิดไม่สามารถทำได้จริง ๆ หากไม่มีขอบเขตการจัดการแบบไดนามิก (การรวบรวมขยะ) หนึ่งในสิ่งที่ทำให้ C / C ++ มีประสิทธิภาพสูงคือความจริงที่ว่ามันง่ายกว่ามากในการรวบรวมภาษาที่คุณจัดการหน่วยความจำด้วยตนเองดังนั้น kinda จึงเอา C / C ++ ออกจากสมการ

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

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

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

ที่กล่าวว่าฉันรู้สึกเหมือนฉันไม่มีแขนเมื่อถูกบังคับให้เขียนโดยไม่มีพวกเขา


คุณสามารถปฏิบัติต่อวิธีการทั้งหมดเป็นปิดผนึกหรือเพียงแค่ปิดผนึกวิธีที่คุณสนใจมากที่สุดและคุณจะไม่เป็นไร
Alexei Averchenko

@AlexeiAverchenko ฉันยินดีที่จะบอกว่าฉันไม่แน่ใจ 100% ว่าคุณหมายถึงอะไร ขออภัยฉันพลาดความเห็นของคุณไปแล้ว Googling "วิธีการปิดผนึก"
Erik Reppen

4

มันเป็นไปไม่ได้จริงๆ แต่มันก็เป็นคุณสมบัติอีกอย่างและงบประมาณความซับซ้อนนั้นมี จำกัด มันอาจถูกพิจารณาว่าไม่จำเป็นโดยนักออกแบบภาษา (หรือไม่เกิดขึ้นกับ) - "ทำไม heck เราต้องผ่านฟังก์ชั่น? ภาษานี้ใช้สำหรับการเขียนโปรแกรมระบบปฏิบัติการ!" มันอาจใช้ความพยายามที่สำคัญในการผสานกับส่วนที่เหลือของภาษา ตัวอย่างเช่นประเภทฟังก์ชั่นอาจต้องมีการเพิ่มเติมอย่างจริงจังไปยังระบบประเภท (เช่นใน Java) ยิ่งถ้าคุณมีการโหลดมากเกินไป (ขอบคุณ @Renesis สำหรับการชี้ให้เห็นว่า) คุณต้องให้รหัสห้องสมุดเพื่อใช้ประโยชน์ได้ - ไม่มีใครต้องการกำหนดmapตัวเอง

นอกจากนี้ยังอาจทำให้เป้าหมายอื่น ๆ ของภาษายากขึ้นที่จะทำให้สำเร็จ:

  • มันจะกลายเป็น "ยาก" เพื่อเพิ่มประสิทธิภาพ (ไม่จริงยากขึ้นในหลายกรณี แต่ต้องใช้วิธีการที่แตกต่างกว่าที่คุณเคยใช้) ตัวอย่างเช่นหากฟังก์ชั่นทั่วโลกอาจได้รับมอบหมายใหม่คุณต้องพิสูจน์ว่าไม่ได้fกำหนดใหม่ก่อนที่คุณจะเข้าแถว
  • ในหลอดเลือดดำที่คล้ายกันหากคุณสร้างวัตถุที่มีคุณสมบัติครบถ้วนคุณจำเป็นต้องมีสมาร์ทคอมไพเลอร์และ JIT เพื่อลบค่าโสหุ้ยที่เกี่ยวข้องกับการโทรออกและทำให้การโทรมีประสิทธิภาพ (ความเร็ว - และพื้นที่ฉลาด) ที่อยู่บางส่วน
  • ดังที่ได้กล่าวไปแล้วมันเป็นคุณสมบัติที่สมบูรณ์และเป็นก้าวแรกในการสนับสนุนกระบวนทัศน์อื่น - หากคุณต้องการภาษาที่เรียบง่ายบางทีคุณอาจไม่สามารถเพิ่มฟังก์ชั่นชั้นหนึ่งโดยไม่ทิ้งสิ่งอื่น ๆ ออก.
  • บางทีมันอาจไม่เข้ากันกับภาษาที่เหลือ หากคุณออกแบบภาษาให้เป็นชาติที่ดีที่สุดของ OOP ตั้งแต่ Smalltalk คุณอาจต้องการที่จะมุ่งเน้นไปที่แทนที่จะนำเสนอกระบวนทัศน์ที่แตกต่างกันมาก โดยเฉพาะอย่างยิ่งถ้ามันยากที่จะรวมทั้งสอง (ดูด้านบน) กระบวนทัศน์ N ที่ทำได้ดีมีความสุขมากกว่าการเขียนโปรแกรมในกระบวนทัศน์ที่ N + 1 ทำได้ดี

ในหลอดเลือดดำเดียวกันเราสามารถถามได้ว่าเหตุใดภาษาการเขียนโปรแกรม L1 จึงไม่มีคุณสมบัติ F ของภาษา L2 ที่แตกต่างกันมาก


1

ฉันคิดว่าปัญหาแรกนั้นเป็นความเข้าใจที่คลาดเคลื่อนที่ไม่สามารถนำไปใช้กับ Object-Oriented และ Function ได้ รายการที่รวดเร็วของภาษาที่อธิบายไว้อย่างน้อยจากวิกิพีเดียขณะที่ทั้งสอง: JavaScript , ActionScript , งูหลาม , C # , F #

ปัญหาที่สองดูเหมือนจะเป็นคำจำกัดความของฟังก์ชั่นชั้นหนึ่ง - ทำไมคุณไม่คิดว่า C # จะมีฟังก์ชั่นเหล่านั้น?

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

คำถามจริงคืออะไร

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

ฟังก์ชั่นการบรรทุกเกินพิกัด

หนึ่งในเหตุผลหลักสำหรับเรื่องนี้คือความยากลำบากในการกำหนดฟังก์ชั่นชั้นหนึ่งเมื่อภาษาได้เลือกที่จะรองรับฟังก์ชั่นการทำงานเกิน (ตัวอย่างใน Java):

public int dispatchEvent(Event event);
public int dispatchEvent(String event, Object data);

dispatchEventฟังก์ชันใดที่ตัวแปรจะอ้างถึง

การเขียนโปรแกรมตามระดับ

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

ตัวอย่างเช่น ActionScript เมื่อภาษา ECMAScript เริ่มต้นในกระบวนทัศน์การทำงานที่มากขึ้นเช่น JavaScript ฟังก์ชั่นไม่ได้ถูกผูกไว้กับวัตถุโดยเนื้อแท้พวกมันสามารถถูกเรียกด้วยวัตถุใด ๆ ก็ได้เนื่องจากมันเป็นขอบเขตในช่วงเวลาของการดำเนินการ

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


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

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

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

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

0

ฉันสงสัยในสิ่งเดียวกันเอง เมื่อฉันใช้ภาษาแลมบ์ดาฉันก็ใช้ภาษาพวกนี้ได้เยอะ แม้แต่ PHP ก็ดีขึ้นเมื่อคุณรู้ว่าคุณสามารถทำการปิดด้วย php 5.3 (มันไม่ดีเท่าเสียงกระเพื่อม แต่ยังดีกว่า)

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