อะไรคือข้อดีและข้อเสียในแนวทางของ C #, Java และ Scala to Closures / Lambdas / …?


30

ฉันสงสัยว่าสิ่งที่แตกต่างระหว่างดำเนินการทางเทคนิค C # และสกาล่าและวิธีการแก้ปัญหาทั้งเปรียบเทียบกับความคิดของการดำเนินงานและความกังวลเปล่งออกมาในอีเมลPeek อดีตแลมบ์ดาโดยไบรอันเก๊ส่งไปยังรายการทางไปรษณีย์ของโครงการแลมบ์ดา (JSR 335) ?

จากอีเมล:

เราสำรวจถนนของ "บางที lambdas ควรจะเป็นอินสแตนซ์ของคลาสภายในซึ่งจะง่ายมาก" แต่ในที่สุดก็มาถึงตำแหน่งของ "ฟังก์ชั่นเป็นทิศทางที่ดีกว่าสำหรับอนาคตของภาษา"

และต่อไป:

มุมมอง lambdas-are-objects ของโลกขัดแย้งกับอนาคตที่เป็นไปได้นี้ มุมมอง lambdas-are-function ของโลกไม่ได้และการรักษาความยืดหยุ่นนี้เป็นหนึ่งในจุดที่สนับสนุน lambdas ที่ไม่ทำให้เกิดภาระด้วยแม้แต่ลักษณะที่ปรากฏของวัตถุ

สรุป:

Lambdas-are-function เปิดประตู Lambdas-are-objects ปิดพวกเขา
เราต้องการเห็นประตูที่เปิดทิ้งไว้

และความคิดเห็นบางส่วนจากบุคคลในเธรด Redditพูดว่า:

จริง ๆ แล้วฉันส่งอีเมลถึง Neal Gafter เกี่ยวกับเรื่องนี้และความเข้าใจที่ จำกัด ของฉันเกี่ยวกับการอธิบายของเขา C # และการออกแบบ Java ในปัจจุบันค่อนข้างคล้ายกับที่ผู้ได้รับมอบหมายเป็นวัตถุจริงและไม่ใช่ประเภทการทำงาน ดูเหมือนว่าเขาเชื่อว่า Java ควรเรียนรู้จากข้อเสียของแกะแกะ C # และหลีกเลี่ยงพวกเขา (เช่น C # เรียนรู้จากข้อเสียของ Java และหลีกเลี่ยงพวกเขาในตอนแรก)

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

เมื่อเห็นว่าสิ่งต่าง ๆ ใน Scala "แค่งาน" ฉันคิดอยู่เสมอว่าฉันพลาดอะไรบางอย่างเกี่ยวกับวิธีการที่นำเสนอ / ใน C # / Java (8) บางทีมันอาจเกี่ยวข้องกับข้อกังวลเกี่ยวกับความเข้ากันได้แบบย้อนหลัง?


1
สิ่งนี้น่าสนใจ ระบุว่าระบบประเภท Javas ไม่มีแนวคิดของฟังก์ชั่น ณ ขณะนี้นี่หมายความว่าต้องมีการแนะนำสิ่งนี้ก่อน อาจเป็นไปได้ว่าภาษานี้จะซับซ้อนเกินไป
Ingo

อินสแตนซ์ของอินเทอร์เฟซบางอย่างไม่ควรทำใช่หรือไม่ มีอะไรพิเศษเกี่ยวกับพวกเขาเหรอ?
soc

Lisp / Scheme / Clojure สามารถสร้างโมเดลวัตถุในขณะที่ Java / C # ไม่สามารถทำโมเดลฟังก์ชันซ้อนโดยพลการ Python ดูเหมือนจะมีสิ่งที่ดีที่สุดของทั้งสองโลก
งาน

คำตอบ:


15

ฉันคิดว่าการอภิปรายเกี่ยวกับวัตถุกับฟังก์ชั่นเป็นปลาเฮอริ่งแดง หากคำถามคือ "แลมบ์ดาเป็นฟังก์ชั่นหรือวัตถุ?" คำตอบที่ควรจะใช่

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

สกาล่าทำสิ่งนี้ได้สำเร็จโดยการใช้อ็อบเจกต์ wrapper ที่มีเมธอดที่เรียกได้applyซึ่งสามารถเรียกใช้ด้วย just ()ทำให้ดูเหมือนกับการเรียกเมธอด มันใช้งานได้อย่างยอดเยี่ยม เวลาส่วนใหญ่คุณไม่จำเป็นต้องสนใจว่าคุณมีวิธีการหรือกำลังเรียกใช้การใช้งานฟังก์ชั่นวัตถุ


9

จากสิ่งที่ฉันเข้าใจมันเป็นเรื่องเกี่ยวกับการพิจารณาของ lambdas ในระดับภาษาหลัก อย่างที่อีเมลบอก

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

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

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


lamdas ใน C #! = จากผู้ได้รับมอบหมาย คอมไพเลอร์มีตัวเลือกในการรวบรวมเพื่อ delgates หรือต้นไม้ Expression ทั้งสองมีความแน่นอนกราฟวัตถุ แต่พวกเขาไม่ได้รวบรวมเพื่อ"ชั้นโดยเฉพาะอย่างยิ่ง" หรือแม้กระทั่งระดับของต้นไม้มรดกเฉพาะ
Rune FS

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

@mwolfetech: เท่าที่ฉันรู้พวกเขาได้รับการวางแผนสำหรับ Java 8 ด้วยวิธีการป้องกัน พวกเขาต้องการที่จะเพิ่มสิ่งที่ชอบforeach, map, filterคอลเลกชัน
soc

@soc จุดที่ดีมันยากที่จะติดตามจำนวนของ JSR และไม่ว่าพวกเขาจะเสร็จสมบูรณ์จริง ๆ และสร้าง JDK เวอร์ชันเป้าหมายหรือไม่ ดูเหมือนว่าวิธีการป้องกันอาจเป็นส่วนหนึ่งของ JSR เดียวกัน เกี่ยวกับJSRนี้ฉันพบว่าสถานะของ Brian Goetz ของ Lambda เป็นประโยชน์ - อธิบายประเภท SAM และความคิดปัจจุบันสำหรับการใช้แลมบ์ดา
mwolfetech

"ความคิดปัจจุบัน" mhhh ตอนนี้โพสต์นั้นล้าสมัยไปแล้วหรือยัง?
soc

5

ส่วนใหญ่เขาไม่ต้องการผูกมัดอะไรบางอย่างเร็วเกินไป ฉันไม่เห็นเหตุผลใด ๆ เลยนอกจากการลบทิ้งที่เขานำเสนอ แต่นั่นเป็นเหตุผลที่แข็งแกร่งมากอย่างแน่นอน

ฉันไม่ชอบประเภทฟังก์ชั่น - ฉันรักประเภทฟังก์ชั่น - แต่ฟังก์ชั่นประเภทนั้นต่อสู้อย่างรุนแรงกับแง่มุมที่มีอยู่ของระบบประเภทจาวาลบออก ประเภทฟังก์ชั่นที่ลบจะเลวร้ายที่สุดของทั้งสองโลก

พิจารณาวิธีการเหล่านี้ใน Scala's Regex:

def replaceAllIn (target: CharSequence, replacer: (Match)  String): String
def replaceSomeIn (target: CharSequence, replacer: (Match)  Option[String]): String

มันจะง่ายกว่านี้ถ้าเป็นแบบนี้:

def replace (target: CharSequence, replacer: (Match)  String): String
def replace (target: CharSequence, replacer: (Match)  Option[String]): String

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

อย่างไรก็ตาม a Matchเป็นสิ่งที่มีประโยชน์มาก แต่โดยส่วนใหญ่คุณต้องการให้ตรงกับStringหรือรายการของกลุ่มย่อย เราอยากได้สิ่งนี้:

def replaceAllIn (target: CharSequence, replacer: (String)  String): String
def replaceAllIn (target: CharSequence, replacer: (Seq[String])  String): String
def replaceAllIn (target: CharSequence, replacer: (Match)  String): String

เป็นไปไม่ได้เพราะการลบ ฉันเลือกตัวอย่างเฉพาะนี้เพราะฉันเกี่ยวข้องโดยตรง แต่ฉันได้เห็นคำถามเกี่ยวกับ Stack Overflow อย่างน้อยครึ่งโหลที่ผู้คนถามว่าทำไมการโอเวอร์โหลดผิดกฎหมายเนื่องจากปัญหาที่แน่นอนนี้

และจากนั้นให้พิจารณาว่าการจับคู่รูปแบบของ Scala และ Java instanceofนั้นไร้ประโยชน์อย่างมีประสิทธิภาพเนื่องจากการลบออก

ฉันคิดว่ามันยุติธรรมพอที่จะหน่วงชนิดของฟังก์ชันจนกว่าปัญหานี้จะได้รับการจัดการ ท้ายที่สุดมีภาษามากมายที่มีอยู่ใน JVM และไม่เหมือน Java เป็นภาษาที่พัฒนาอย่างรวดเร็ว


ถ้าการลบประเภทเป็นปัญหาเดียวที่พวกเขามีพวกเขาวางแผนจะทำอะไร? ทำลายทุกรหัสบนโลกใบนี้ได้รับการปกครองตัวเลือกที่ไม่ใช่สำหรับ Java 5 แล้ว ...
SOC

@soc ผมจึงดีใจที่ฉันไม่อยู่ในรองเท้าของพวกเขา! แต่นั่นคือซันนี่คือออราเคิล ออราเคิลไม่เคยมีส่วนร่วมในการเปลี่ยนแปลงที่สำคัญระหว่างผลิตภัณฑ์หลักและรุ่นรองลงมา
Daniel C. Sobral

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

@Giorgio นั่นคงเป็นเรื่องไร้สาระ บางคนที่รับผิดชอบสิ่งที่ Java ทำในวันนี้ แต่อย่างที่คุณพูดมีหลายทางเลือก แต่คนที่รับผิดชอบJavaต้องพัฒนา Java เอง - พวกเขาต้องรับผิดชอบต่อJava ทั้งหมด ทางเลือกเดียวคือปล่อย Java และสละประโยชน์ทั้งหมดที่เกิดจากการควบคุม
แดเนียลซี Sobral

@Daniel C. Sobral: IMO ภาษาการเขียนโปรแกรมเป็นเหมือนซอฟต์แวร์บางส่วน: ในตอนแรกมันสามารถทำความสะอาดและออกแบบได้ดี แต่ยิ่งคุณเล่นมากก็ยิ่งทำให้มันยุ่งเหยิงยิ่งขึ้น ดังนั้นฉันคิดว่ามันจะเป็นประโยชน์ของนักพัฒนาที่จะหยุดจาวาเป็นภาษาและมุ่งเน้นการพัฒนาใน (1) การสร้างห้องสมุดใหม่หรือปรับปรุงที่มีอยู่ (2) ปรับปรุง JVM (ถ้าเป็นไปได้), (3) การพัฒนาภาษาใหม่ . แต่อย่างที่คุณบอกว่ามีคนที่รับผิดชอบ Java และผู้ที่ต้องการขายการอัพเกรดต่อไป ดังนั้นพวกเขาจะขยายเพื่อให้มัน "เย็น" แค่ 2 เซ็นต์ของฉัน
Giorgio
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.