Những lợi ích và bất lợi trong cách tiếp cận của C #, Java và Scala đối với việc đóng cửa / Lambdas / Lỗi là gì?


30

Tôi tự hỏi sự khác biệt về triển khai kỹ thuật giữa C # và Scala là gì và làm thế nào cả hai giải pháp so sánh với các ý tưởng triển khai và mối quan tâm được gửi trong email Peek Past lambda của Brian Goetz, được gửi đến danh sách gửi thư của Dự án Lambda (JSR 335) ?

Từ email:

Chúng tôi đã khám phá con đường "có lẽ lambdas chỉ là những trường hợp bên trong, điều đó thực sự đơn giản", nhưng cuối cùng đã đến với vị trí "các chức năng là một hướng tốt hơn cho tương lai của ngôn ngữ".

và xa hơn:

Quan điểm của lambdas là đối tượng của thế giới xung đột với tương lai có thể này. Quan điểm của lambdas là các chức năng của thế giới thì không, và bảo tồn tính linh hoạt này là một trong những điểm có lợi cho việc không gây gánh nặng cho lambdas thậm chí với sự xuất hiện của đối tượng.

Phần kết luận:

Lambdas-are-chức năng mở cửa. Lambdas-are-object đóng chúng lại.
Chúng tôi muốn thấy những cánh cửa còn bỏ ngỏ.

Và một số bình luận từ một người trên chủ đề Reddit nói:

Tôi thực sự đã gửi email cho Neal Gafter về điều này và với sự hiểu biết hạn chế của tôi về giải thích C # của anh ấy và thiết kế Java hiện tại khá giống nhau ở chỗ các Đại biểu thực sự là các đối tượng và không phải là các loại hàm. Có vẻ như ông tin rằng Java nên học hỏi từ những nhược điểm của lambdas của C # và tránh chúng (giống như C # đã học được từ những bất lợi của Java và tránh chúng ngay từ đầu).

Tại sao phương pháp "Lambdas-are-chức năng" cho phép nhiều cơ hội hơn trong tương lai hơn "Lambdas-are-object"? Ai đó có thể giải thích sự khác biệt tồn tại và cách chúng ảnh hưởng đến cách viết mã?

Thấy mọi thứ trong Scala "chỉ hoạt động", tôi cứ nghĩ rằng tôi đang thiếu một cái gì đó về các cách tiếp cận được thực hiện / đề xuất trong C # / Java (8), có lẽ nó liên quan đến mối quan tâm về khả năng tương thích ngược?


1
Hay đấy. Cho rằng hiện tại hệ thống loại Javas không có khái niệm về chức năng, điều này có nghĩa là người ta phải giới thiệu cái này trước. Có thể ngôn ngữ sẽ trở nên quá phức tạp với điều này.
Ingo

Không phải là chức năng nên phiên bản của một số giao diện? Có gì đặc biệt ở họ?
soc

Lisp / Scheme / Clojure có thể mô hình hóa các đối tượng trong khi Java / C # không thể mô hình hóa các hàm lồng nhau tùy ý. Python dường như có tốt nhất của cả hai thế giới, tuy nhiên.
Công việc

Câu trả lời:


15

Tôi nghĩ rằng các cuộc thảo luận về các đối tượng so với các chức năng là một cá trích đỏ. Nếu câu hỏi là "lambda là một chức năng hay một đối tượng?" Câu trả lời nên .

Đó là điểm của các chức năng hạng nhất: chúng không được đối xử khác với bất kỳ loại nào khác. Java đã quản lý hầu như bỏ qua sự khác biệt giữa các loại Object và nguyên thủy (và Scala thậm chí còn tốt hơn), do đó, lambda là một lớp con của Object hay là một kiểu nguyên thủy mới hoặc một thứ khác không thực sự quan trọng đối với ngôn ngữ. Điều quan trọng là bạn có thể đặt lambdas của mình vào các bộ sưu tập, chuyển chúng xung quanh để được gọi, gọi chúng và làm bất cứ điều gì khác mà bạn có thể muốn làm với một đối tượng hoặc một phương thức.

Scala thực hiện điều này bằng cách sử dụng một đối tượng trình bao bọc có một phương thức được gọi applycó thể được gọi bằng chỉ (), làm cho nó trông giống như một cuộc gọi phương thức. Công trình này lộng lẫy; phần lớn thời gian bạn không cần phải quan tâm liệu bạn có một phương thức hay đang gọi việc áp dụng một đối tượng hàm.


9

Từ những gì tôi hiểu, nó nói thêm về cách lambdas được xem xét ở cấp độ ngôn ngữ chính. Như email nói,

Bạn có thể nghĩ rằng thiết kế hiện tại được gắn chặt với một hộp đối tượng cho lambdas - loại SAM - làm cho chúng trở thành đối tượng hiệu quả. Nhưng điều này đã được giấu cẩn thận khỏi khu vực bề mặt để cho phép chúng tôi xem xét lambdas 'trần trụi' trong tương lai, hoặc xem xét các bối cảnh chuyển đổi khác cho lambdas, hoặc tích hợp chặt chẽ hơn lambdas vào các cấu trúc kiểm soát. Bây giờ chúng tôi không làm điều đó và thậm chí chúng tôi không có kế hoạch cụ thể để làm điều đó, nhưng khả năng có thể làm điều đó trong tương lai là một phần quan trọng của thiết kế.

Tôi nghĩ rằng tổng hợp câu hỏi của bạn khá độc đáo. Nếu bạn tuyên bố rằng "lambdas là đối tượng", thì chúng chỉ là một đối tượng của một lớp cụ thể và bạn bị mắc kẹt với điều đó. Mặt khác, nếu bạn tuyên bố "lambdas là các hàm", thì về mặt ngữ nghĩa, bạn có một sân chơi phong phú hơn nhiều. Java 1.7 có thể biên dịch chúng xuống các đối tượng, vì vậy chúng thực tế giống hệt nhau tại thời điểm đó.

Nhưng Java 1.8, hoặc 1.9, có thể mang lại các thay đổi cho ngôn ngữ (chẳng hạn như các kiểu cấu trúc hợp nhất) hơn là cho phép các hàm được sử dụng theo những cách linh hoạt hơn nhiều. Nếu "lambdas là đối tượng", những thay đổi này sẽ không tương thích ngược và bạn phải giới thiệu một khái niệm mới hoàn toàn, để không phá vỡ mã hiện có của mọi người. Nhưng nếu javacchỉ lặng lẽ chuyển đổi lambdas thành các vật thể phía sau hậu trường, thì cái mới javaccó thể chuyển đổi chúng thành bất cứ thứ gì nó muốn, miễn là ngữ nghĩa vẫn còn tồn tại.


lamdas trong C #! = từ các đại biểu. Trình biên dịch có tùy chọn biên dịch chúng thành các cây phân định hoặc biểu thức. cả hai thực sự là đồ thị đối tượng nhưng chúng không được biên dịch thành một "lớp cụ thể" hay thậm chí là một lớp của một cây thừa kế cụ thể
Rune FS

Nếu tôi hiểu chính xác, thì việc biên dịch lambda thành một lớp bên trong của đối tượng được liên kết với đối tượng đó, vì vậy trong tương lai nếu Java sẽ giới thiệu các hàm bậc cao hơn (các hàm ở cùng cấp đối tượng) thì bạn không thể sử dụng triển khai lớp bên trong và sẽ có sự không nhất quán. Tôi không nghĩ Java sẽ có các hàm bậc cao hơn bất cứ lúc nào sớm.
mwolfetech

@mwolfetech: Theo tôi biết, họ đã lên kế hoạch cho Java 8 với các phương thức phòng thủ. Họ muốn thêm những thứ như foreach, map, filtercác bộ sưu tập.
soc

@soc Điểm hay, thật khó để theo kịp số lượng JSR và liệu chúng có thực sự hoàn thành và tạo phiên bản đích của JDK hay không. Có vẻ như các phương thức bảo vệ có thể là một phần của cùng một JSR. Liên quan đến JSR này , tôi thấy bài viết Trạng thái Lambda của Brian Goetz rất hữu ích - giải thích các loại SAM và những suy nghĩ hiện tại để thực hiện các biểu thức lambda.
mwolfetech

"Những suy nghĩ hiện tại" mhhh, không phải bài viết từ năm 2010 đã lỗi thời rồi sao?
soc

5

Hầu như, anh ta không muốn cam kết quá sớm với điều gì đó. Tôi không thấy bất kỳ lý do nào ngoài việc xóa bỏ mà anh ấy trình bày, nhưng đó thực sự là một lý do rất mạnh mẽ.

Tôi không thích các kiểu hàm - Tôi thích các kiểu hàm - nhưng các kiểu hàm đó đã chiến đấu không tốt với một khía cạnh hiện có của hệ thống kiểu Java, xóa. Các loại chức năng bị xóa là tồi tệ nhất của cả hai thế giới.

Hãy xem xét các phương pháp này trong Scala Regex:

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

Sẽ đơn giản hơn nếu họ chỉ đơn giản thế này:

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

Thật không may, điều đó là không thể, bởi vì hai chức năng này giống hệt nhau trong quá trình xóa. Nhưng, tốt thôi, các chức năng này làm một số điều khác nhau, vì vậy một tên khác có thể là đủ công bằng.

Tuy nhiên, a Matchlà một cái gì đó rất hữu ích, nhưng hầu hết thời gian bạn muốn Stringhoặc là danh sách các nhóm con phù hợp . Chúng tôi muốn có điều này:

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

Không thể, vì tẩy xóa. Tôi đã chọn ví dụ cụ thể này vì tôi liên quan trực tiếp đến nó, nhưng tôi đã thấy ít nhất nửa tá câu hỏi về Stack Overflow, nơi mọi người hỏi tại sao quá tải là bất hợp pháp, do vấn đề chính xác này gây ra.

Và sau đó, hãy xem xét việc khớp mẫu của Scala và Java thực sự instanceofvô dụng vì bị xóa.

Tôi nghĩ thật công bằng khi trì hoãn các loại chức năng cho đến khi vấn đề này được giải quyết. Rốt cuộc, có rất nhiều ngôn ngữ có nó trên JVM và không giống như Java là ngôn ngữ phát triển nhanh.


Chà, nếu loại tẩy xóa là vấn đề duy nhất họ có, họ dự định làm gì? Phá vỡ mọi mã trên hành tinh này đã được quy định là không có tùy chọn cho Java 5 ...
soc

@soc Tôi rất vui vì tôi không ở trong giày của họ! Nhưng đó là Sun, đây là Oracle. Oracle chưa bao giờ có bất kỳ sự ràng buộc nào trong việc thực hiện các thay đổi đột phá giữa các phiên bản chính - và thậm chí là nhỏ - của sản phẩm chính của mình.
Daniel C. Sobral

Có lẽ họ nên thay đổi tên của ngôn ngữ và bắt đầu phát triển một ngôn ngữ mới, bỏ khả năng tương thích ngược. Vì vậy, người ta sẽ có những lợi ích của một ngôn ngữ mới mà không cần phải chơi xung quanh với một ngôn ngữ cũ và được thiết lập tốt. Rốt cuộc, đây là những gì Scala và Clojure đã làm.
Giorgio

@Giorgio Điều đó sẽ là một chút vô nghĩa. Chà, một số người chịu trách nhiệm cho những gì Java ngày nay đã làm điều đó, nhưng, như bạn đã nói, có những lựa chọn thay thế. Nhưng những người chịu trách nhiệm về Java phải tự cải thiện Java - rốt cuộc họ chịu trách nhiệm về nó. Cách thay thế duy nhất là chỉ cần bỏ Java và từ bỏ tất cả các lợi ích có được từ việc kiểm soát nó.
Daniel C. Sobral

@Daniel C. Sobral: IMO một ngôn ngữ lập trình hơi giống một phần mềm: ban đầu nó có thể sạch sẽ và được thiết kế tốt nhưng bạn càng chơi với nó thì nó càng trở nên lộn xộn. Vì vậy, tôi nghĩ rằng sẽ có lợi cho các nhà phát triển khi đóng băng Java như một ngôn ngữ và tập trung phát triển vào (1) tạo thư viện mới hoặc cải thiện các thư viện hiện có, (2) cải thiện JVM (nếu có thể), (3) phát triển các ngôn ngữ mới . Nhưng như bạn đã nói, có những người chịu trách nhiệm về Java và muốn tiếp tục bán các bản nâng cấp. Vì vậy, họ sẽ mở rộng nó để giữ cho nó "mát mẻ". Chỉ 2 xu của tôi.
Giorgio
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.