Là cú pháp trùng lặp để xác định các chức năng được đặt tên là một quyết định thiết kế ngôn ngữ xấu?


9

Tôi đang mô hình hóa một ngôn ngữ lập trình cho vui, và cú pháp bị ảnh hưởng rất nhiều bởi Scala - cụ thể là các định nghĩa hàm.

Tôi đã gặp phải một vấn đề thiết kế vì ngôn ngữ của tôi không phân biệt giữa các hàm được xác định thông qua defcú pháp (phương thức lớp) và các hàm ẩn danh được gán cho các giá trị (được tạo bằng cách sử dụng =>) - nó loại bỏ sự khác biệt trong cả cách thực hiệnhành vi .

Kết quả là hai định nghĩa sau có nghĩa giống nhau:

def square(x: Int) = x*x

val square = (x: Int) => x*x

Không có lý do nào để hình thức sau (gán chức năng ẩn danh ngay lập tức) được sử dụng trong mọi tình huống thông thường - đơn giản là có thể sử dụng nó thay vì defbiểu mẫu.

Việc có cú pháp trùng lặp như vậy để xác định các hàm được đặt tên có ảnh hưởng đến tính trực giao của ngôn ngữ hoặc một số khía cạnh thiết kế khác không?

Tôi thích giải pháp này vì nó cho phép các định nghĩa ngắn và trực quan về các phương thức và các hàm được đặt tên (thông qua def) và các định nghĩa ngắn về các hàm ẩn danh (sử dụng =>).

Chỉnh sửa: Scala không phân biệt giữa hai - vô danh chức năng là không giống như các phương pháp định nghĩa với deftrong Scala. Sự khác biệt là tương đối tinh tế - xem các bài viết tôi liên kết trước đó.


However, assigning existing functionsdường như đang thiếu phần cuối của câu
Izkata

1
Bạn có thể xác định các hàm đệ quy bằng cách sử dụng valký hiệu của bạn ?
Giorgio

2
Tôi đã xác minh rằng điều này là có thể trong Scala quá. Trong SML thì không và bạn phải sử dụng funđể xác định hàm đệ quy.
Giorgio

3
Hình thức thứ hai không thực sự là một cấu trúc cú pháp đặc biệt def. Nó chỉ là một tác dụng phụ của thực tế là một hàm ẩn danh, nói (x : Int) => x + 1là một đối tượng và các đối tượng có thể được gán cho các giá trị với val f = .... Các nhà thiết kế ngôn ngữ sẽ phải đi ra ngoài để không cho phép cú pháp. Nó không hoàn toàn giống như nỗ lực rõ ràng để hỗ trợ hai cú pháp khác nhau thực hiện (xấp xỉ) cùng một điều.
KChaloux

3
Lợi ích chính của việc làm một điều gì đó nhiều hơn một cách trong một ngôn ngữ là một cách tuyệt vời để bắt đầu các cuộc tranh luận tôn giáo không mang lại lợi ích làm sao lãng các vấn đề thực sự (Suy nghĩ C ++ ở đây) .......
mattnz

Câu trả lời:


3

Tôi nghĩ rằng có hai cấu trúc có nghĩa là giống nhau nhưng trông khác nhau nên được giữ ở mức tối thiểu trong ngôn ngữ. Bất kỳ sự trùng lặp nào đều làm tăng mức độ khó đọc (và do đó viết / sửa đổi mã) trong ngôn ngữ của bạn. Loại bỏ tất cả sự trùng lặp là không thể tránh khỏi trong một ngôn ngữ có thể tạo ra các cấu trúc tùy ý (ví dụ: sự tương đương của phép lặp so với đệ quy).

Vì vậy, trong trường hợp này, tôi nghĩ rằng nó có thể được thiết kế tốt hơn ở đây. Một cách duy nhất để xác định các hàm có ý nghĩa nhất đối với tôi. Trong trường hợp này, có vẻ như hai tuyên bố scala mà bạn thực sự có ý nghĩa hơi khác nhau, một lần nữa có lẽ không phải là thiết kế tốt (có lẽ tốt nhất là có một cái gì đó rõ ràng nói lên sự khác biệt, như từ khóa).

Trong thực tế, bạn có thể áp dụng nguyên tắc này không chỉ cho các hàm được đặt tên, mà còn cho bất kỳ chức năng nào . Tại sao có sự khác biệt trong việc xác định hàm được đặt tên và hàm ẩn danh? Ở Lima , các chức năng luôn được định nghĩa như thế này : fn[<arguments>: <statements>]. Nếu bạn muốn nó được "đặt tên", bạn có thể gán nó cho một biến: var x = fn[<arguments: <statements>]và nếu bạn muốn chuyển nó vào một hàm khác ẩn danh : function[fn[<arguments: <statements>]]. Nếu bạn muốn nó được nâng lên, làm cho nó liên tục const var x = fn[<arguments: <statements>]. Các hình thức duy nhất làm cho rõ ràng rằng chúng có nghĩa là điều tương tự.


Điều đó khá thú vị constgây ra cẩu, nhưng nó có ý nghĩa hoàn hảo. Trong JS function myFuncgây ra cẩu, nhưng var myFunc =không, có lẽ hơi trực quan hơn một chút vì chúng hoạt động khá giống nhau.
mở

1
@mpen Vâng, thực sự javascript cũng làm điều tương tự. các function fnName()...hình thức nào trong thực tế tạo ra một hằng số, đó là những gì làm cho cẩu một điều hợp lệ để làm gì với nó. Javascript làm cho mọi thứ khá khó hiểu khi bạn sử dụng biểu mẫu var fn = function anotherFnName()...vì điều đó làm cho tên anotherFnName không phải là Palăng, thậm chí tho không rõ ràng.
BT

2

Những gì bạn đã đăng là scala hợp lệ và hoạt động tốt.

Cho rằng việc nhân đôi đã không gây ra vấn đề với scala (theo hiểu biết của tôi), tôi sẽ nói rằng nó cũng sẽ không phải là vấn đề đối với ngôn ngữ của bạn.


1
Nó có giá trị trong Scala, nó hầu như hoạt động giống nhau, nhưng điều đó không có nghĩa tương tự - và nếu bạn đưa ra các ví dụ phức tạp hơn (kiểu đa hình không có sẵn cho các hàm ẩn danh, ví dụ) - sự khác biệt sẽ trở nên rõ ràng hơn.
jcora

2

Tôi đã tìm thấy một sự khác biệt cơ bản giữa lambdas và defphương pháp trong Scala - rằng tôi vẫn không chắc liệu mình có muốn thực hiện hay không. Tôi phải nghiên cứu thêm về nó và sau đó tôi sẽ báo cáo lại quyết định của mình.

Về cơ bản, chỉ có các phương thức có thể return- và khi từ khóa được sử dụng từ lambda, nó thực sự trả về từ phương thức bao gồm.

Như tôi đã nói, tôi không chắc liệu tôi có muốn điều này không. Nhưng nó có thể đủ biện minh cho cú pháp này. Hoặc có thể quá nguy hiểm vì sự khác biệt tinh tế có thể gây ra tác hại bất ngờ.

Chi tiết

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.