OCaml chỉ trích: nó vẫn còn hiệu lực?


14

Tôi là một người mới hoàn toàn với OCaml. Gần đây tôi đã tình cờ vào trang này liệt kê một số lời chỉ trích tốt đối với OCaml.

Thấy rằng trang này khá cũ (2007): điểm đạn nào được liệt kê vẫn còn đúng cho đến ngày hôm nay? Ví dụ: vẫn đúng là không thể in một đối tượng chung?

Tôi muốn làm rõ rằng tôi không tìm kiếm một cuộc thảo luận về các ý kiến ​​bày tỏ trong đó. Tôi đang hỏi liệu thông tin được liệt kê, chẳng hạn như số nguyên tràn mà không có cảnh báo, có còn đúng cho các phiên bản mới hơn của OCaml không


5
Tôi đang bỏ phiếu để đóng câu hỏi này ngoài chủ đề vì meta.programmers.stackexchange.com/questions/6417/ mẹo
Philipp

3
Có một ngã ba nơi những cái đó có thể đã được sửa: tryfsharp.org
Den

7
Tất nhiên ý kiến ​​trong bài luận mà bạn liên kết là hợp lệ, nhưng liệu những lời chỉ trích này có liên quan đến bạn hay không là một vấn đề hoàn toàn khác. Lưu ý rằng tác giả đến từ một nền Lisp chung và do đó có các giá trị Lispish. Nếu bạn thực hiện một cách tiếp cận khác với OCaml so với việc so sánh nó với Lisp (ví dụ, thì OC OCL là Haskell đối với những người bình thường. Đối với tất cả các sai sót của nó, OCaml là một ngôn ngữ tuyệt vời và tôi khuyến khích bạn tiếp tục học hỏi.
amon

5
Theo như tôi biết thì không có cách nào để phát hiện tràn số nguyên trong phần cứng , vì vậy bạn cần phải chèn kiểm tra thời gian chạy khắp nơi để phát hiện ra nó; nhưng tác giả đã loại bỏ bằng cách sử dụng "bignum" trên cơ sở hiệu suất! Khiếu nại về số lượng gõ tĩnh để nói dây an toàn là xấu vì bạn có thể nghĩ rằng bạn không thể chết trong một vụ tai nạn xe hơi. Khiếu nại về tính bất biến của mô-đun đang nói rằng ông muốn điều chỉnh mọi thứ - một thực tiễn chống mô-đun và dễ bị lỗi. "Sở thú loại nhỏ" không liên quan gì đến suy luận kiểu. Rõ ràng sự thiên vị của anh ấy nằm ở đâu .
Doval

2
@Doval: Tất nhiên bạn có thể phát hiện tràn phần cứng. Đối phó với nó, tuy nhiên, là một vấn đề phần mềm.
Mason Wheeler

Câu trả lời:


13

Bài viết này được thảo luận ở một số nơi:

Tóm lại: có, OCaml không phải là Lisp, và không, nó không hoàn hảo (điều đó có nghĩa là gì?). Tôi không nghĩ rằng những điểm được đề cập trong bài đăng trên blog có liên quan đến các lập trình viên O'Caml hàng ngày.

Đã nghiên cứu O'Caml, tôi nghĩ rằng đó là một ngôn ngữ thú vị có thể giúp bạn xây dựng các chương trình mà bạn thậm chí không dám viết, ví dụ, C / C ++ / Java: ví dụ, hãy xem Frama-C .

Để mô tả cập nhật về O'Caml, tôi khuyến khích bạn đọc về các tính năng của nó : ngôn ngữ khuyến khích các kỹ thuật kiểm tra kiểu tĩnh mạnh cho phép triển khai tập trung vào sản xuất thời gian chạy hiệu quả, nhưng an toàn.

Quan trọng : Tôi không phải là chuyên gia OCaml: nếu bạn là một trong số họ và thấy tôi đã viết một cái gì đó sai lầm khủng khiếp, xin vui lòng sửa cho tôi. Tôi sẽ chỉnh sửa bài này cho phù hợp.

Kiểm tra kiểu tĩnh

  • Sai cảm giác an toàn

    Điều này là đúng, nhưng rõ ràng.

    Gõ tĩnh cung cấp cho bạn bằng chứng bạn có thể tin tưởng về một tập hợp con các thuộc tính của chương trình. Trừ khi bạn chấp nhận đi tất cả chính thức, một chương trình trung bình (không phải đồ chơi) sẽ bị lỗi lập trình mà chỉ có thể được chứng kiến ​​khi chạy.

    Đó là khi các kỹ thuật kiểm tra động có thể được áp dụng: trình biên dịch OCaml có cờ để tạo các tệp thực thi với thông tin gỡ lỗi, v.v ... Hoặc, nó có thể tạo mã tin tưởng người lập trình một cách mù quáng và xóa thông tin loại càng nhiều càng tốt. Các lập trình viên muốn các chương trình mạnh mẽ nên thực hiện kiểm tra động một cách rõ ràng.

    Điều tương tự cũng áp dụng cho ví dụ Common Lisp, nhưng đảo ngược: kiểu động trước, với khai báo kiểu tùy chọn và chỉ thị trình biên dịch thứ hai.

  • Vài loại cơ bản

    Vẫn áp dụng: ngôn ngữ cốt lõi không thay đổi (hoặc không đáng kể).

  • Tràn số nguyên im lặng

    Đây là tiêu chuẩn trong hầu hết các ngôn ngữ mà số nguyên tràn được kiểm tra bằng tay. Tôi không biết bất kỳ thư viện nào sẽ kiểm tra các hoạt động để xác minh xem liệu tràn có thể xảy ra hay không.

  • Mô đun bất biến

    1. Tác giả đề cập đến Functor nhưng tôi không thấy ví dụ của anh ta có thể được thực hiện như thế nào. Đọc chương Mô-đun hạng nhất của https://realworldocaml.org , dường như các mô-đun có thể được sử dụng để soạn thảoxây dựng các mô-đun mới. Tất nhiên, sửa đổi một mô-đun hiện có yêu cầu sửa đổi mã nguồn, nhưng một lần nữa, điều này không phải là bất thường giữa các ngôn ngữ lập trình.

    2. "Về mặt ngữ nghĩa , các chức năng được biên dịch TRỰC TUYẾN"

    Các chủ đề reddit ở trên không đồng ý, nói rằng ràng buộc được giải quyết tại thời điểm liên kết. Tuy nhiên, đây là một chi tiết triển khai và tôi nghĩ rằng ngữ nghĩa được nhấn mạnh liên quan đến cách giải quyết các chức năng. Thí dụ:

     let f x y = x + y ;;
     let g a b = f b a ;;
     let f x y = x * y ;;
     exit (g 2 3) ;;
    

    Chương trình trên sẽ biên dịch và khi được thực thi, trả về 5, vì gđược xác định với phiên bản đầu tiên f, giống như khi hàm gọi gnội tuyến gọi đến f. Điều này không phải là "xấu", nhân tiện, nó chỉ phù hợp với quy tắc che bóng tên của O'Caml.

    Để tóm tắt : có, mô-đun là bất biến . Nhưng chúng cũng có thể ghép lại được .

  • Đa hình gây ra lỗi loại thời gian chạy

    Tôi không thể tái tạo lỗi đã đề cập. Tôi nghi ngờ nó là một lỗi biên dịch.

Không có macro

Thật vậy, không có macro mà là bộ tiền xử lý (OcamlP4, OcamlP5, ...).

  • Wrappers (có tệp mở)

    Biết làm thế nào UNWIND-PROTECT có thể hữu ích, điều này thực sự đau đớn khi thấy nó vắng mặt ở nhiều ngôn ngữ hơn. Dưới đây là một số tùy chọn:

    1. Cải thiện quản lý ngoại lệ trong OCaml
    2. Mở rộng Cú pháp OCaml
  • Nơi

    Tôi không nghĩ các tài liệu tham khảo tổng quát tồn tại trong OCaml.

Ngôn ngữ nhỏ

  • Ghi lại trường đặt tên địa ngục

    Đúng, nhưng bạn nên sử dụng các mô-đun:

    1. Hai trường của hai bản ghi có cùng nhãn trong OCaml
    2. Giải quyết tên trường
  • Cú pháp

    Vẫn áp dụng (nhưng thực sự, đây chỉ là cú pháp).

  • Không đa hình

    Vẫn áp dụng, nhưng bằng cách nào đó, có những người thích điều đó thay vì tháp số của Lisp (tôi không biết tại sao). Tôi cho rằng nó giúp với suy luận kiểu.

  • Bộ hàm không nhất quán

    Xem dự án Bao gồm pin OCaml . Cụ thể, BatArray , ví dụ về map2mảng.

  • Không có biến động

    Có thể thực hiện:

    1. http://okmij.org/ftp/ML/dynvar.txt
    2. http://okmij.org/ftp/ML/index.html#dynvar
  • Tùy chọn ~ đối số hút

    Bằng cách hạn chế ngôn ngữ, bạn không thể trộn các đối số từ khóa và tùy chọn trong Common Lisp. Nó có nghĩa là nó hút? (tất nhiên, điều này có thể được thay đổi bằng macro (xem ví dụ câu trả lời của tôi )). Xem tài liệu của O'Caml để biết các đối số tùy chọn và được đặt tên trong O'Caml.

  • Ứng dụng một phần không thống nhất

    Tôi không nghĩ rằng điều này thực sự gây phiền nhiễu trong thực tế.

  • Khả năng đọc số học

    Nó giữ, nhưng bạn có thể sử dụng R hoặc Python cho các vấn đề về số nếu bạn thích.

  • Giải quyết xung đột tên im lặng

    Vẫn áp dụng, nhưng lưu ý rằng điều này là tài liệu tốt.

  • Không có đầu vào / đầu ra đối tượng

    Vẫn áp dụng.

Thực hiện, thư viện

Những điều này liên tục thay đổi mỗi ngày: không có câu trả lời dứt khoát.

Cuối cùng,

"Bạn nên thử OCaml (hoặc, tốt hơn là Haskell) ngay cả khi bạn nghĩ rằng nó tệ và bạn không có kế hoạch sử dụng nó. Nếu không có nó, giáo dục Khoa học Máy tính của bạn không đầy đủ, giống như nó không hoàn chỉnh nếu không có Lisp và C (hoặc , tốt hơn nữa, hội) tiếp xúc. "

... vẫn được áp dụng.


Cảm ơn bạn, tôi sẽ xem xét các liên kết, nhưng tôi không thực sự hỏi liệu những ý kiến ​​đó có hợp lý không. Tôi đang hỏi liệu sự thật vẫn còn. Ví dụ: có cách nào để in ra bất kỳ kiểu dữ liệu đại số nào không? Có còn chính xác rằng số nguyên tràn mà không có cảnh báo? Hôm nay có cách nào để vận hành trên tệp và loại bỏ chúng mà không phải viết mỗi lần soạn thảo để xử lý việc đóng tệp bị lỗi không?
Andrea

@Andrea Tôi đã chỉnh sửa câu trả lời của tôi.
coredump

1
"... có những người thích điều đó thay vì tháp số của Lisp (tôi không biết tại sao). Tôi cho rằng nó giúp với suy luận kiểu." Chơi lô tô. Hệ thống loại của SML và OCaml yêu cầu mọi biểu thức chỉ có một loại. Quá tải toán tử toán học của SML là một ngoại lệ được tích hợp vào ngôn ngữ. Điều này cũng đúng với Haskell; cho phép loại quá tải đó là động lực đằng sau các lớp loại. Điều hấp dẫn là bạn chỉ có thể có một thể hiện lớp loại cho mỗi loại. Bạn cũng không thể mù quáng chuyển đổi một số nguyên thành một float có kích thước bằng nhau - một float 64 bit chỉ có độ chính xác 54 bit.
Doval

@Doval Điều gì về một cái gì đó như Gõ tháp số cho vợt? Chúng ta có thể tưởng tượng một thư viện OCaml sẽ khai thác các lớp loại hoặc Kiểu dữ liệu đại số tổng quát (GADT) để cung cấp các toán tử đa hình không? Về chuyển đổi: không phải tất cả các hoạt động đều có thể, nhưng một số có thể và có thể được gõ.
coredump

2
@Doval: "Re: Toán tử toán học đa hình, tôi không nghĩ có cách nào khác mà không thực hiện các lớp loại của Haskell". F # có các toán tử đa hình mà không có các lớp loại.
Jon Harrop

7

Thấy rằng trang này khá cũ (2007): điểm đạn nào được liệt kê vẫn còn đúng cho đến ngày hôm nay?

  • Sai cảm giác an toàn . Thật vô nghĩa.

  • Vài loại cơ bản . OCaml hiện có các byte và mảng byte nhưng không có chuỗi unicode tích hợp, số nguyên 16 bit, số nguyên không dấu, số float 32 bit, vectơ hoặc ma trận. Thư viện của bên thứ ba cung cấp một số trong số này.

  • Im lặng tràn số nguyên . Không thay đổi nhưng nó không bao giờ là một vấn đề.

  • Mô đun bất biến . Khuyến nghị của ông rằng các chức năng và mô-đun nên có thể thay đổi là một nhược điểm nghiệt ngã đối với Lisp và một ý tưởng thực sự tồi tệ. Bạn có thể thay thế các mô-đun bằng cách sử dụng includenếu bạn muốn nhưng tất nhiên bạn không thể thay đổi chúng.

  • Đa hình gây ra lỗi loại thời gian chạy . Đây là một vấn đề lớn với OCaml và nó chưa được khắc phục. Khi các loại của bạn phát triển bình đẳng đa hình, việc so sánh và băm sẽ bắt đầu thất bại khi chúng gặp các loại như hàm và gỡ lỗi vấn đề là rất khó. F # có một giải pháp tuyệt vời cho vấn đề này.

  • Không có macro . Trớ trêu thay, khi ông viết OCaml này thực sự đã hỗ trợ đầy đủ cho các macro nhưng giờ họ đã quyết định rút tính năng này ra.

  • Giấy gói . Đây là một vấn đề thực sự và nó đã không được sửa chữa. Vẫn không có try ... finallycấu trúc trong ngôn ngữ OCaml và không có trình bao bọc nào thực hiện nó trong stdlib.

  • Địa điểm . Không thay đổi nhưng không vấn đề.

  • Ghi lại trường đặt tên địa ngục . Cấu trúc mã của bạn đúng cách sử dụng các mô-đun.

  • Cú pháp . Không thay đổi nhưng không vấn đề.

  • Không đa hình . Điều này chủ yếu là vô nghĩa khi ông viết nó và không có gì thay đổi.

  • Bộ hàm không nhất quán . OCaml vẫn không có conschức năng. Tốt rồi. Tôi không muốn công cụ Lisp trong ngôn ngữ của tôi, cảm ơn bạn.

  • Không có biến động . Là một điều tốt về OCaml. Vẫn là một điều tốt về OCaml.

  • Tùy chọn ~ đối số hút . Tùy chọn đá đối số. Tôi đã làm phiền Microsoft để khiến họ thêm các đối số tùy chọn vào F #.

  • Ứng dụng một phần không thống nhất ứng dụng . Hở?

  • Khả năng đọc số học . Điều này đã thay đổi kể từ khi tôi ngừng sử dụng OCaml ~ 8 năm trước. Rõ ràng bây giờ bạn có thể làm Int64.((q * n - s * s) / (n - 1L)).

  • Im lặng giải quyết xung đột tên . Anh ấy đã cố gắng phát triển phần mềm toàn diện trong REPL như bạn làm ở Lisp. Đừng làm điều đó trong OCaml. Sử dụng các tệp và biên dịch hàng loạt chỉ dùng đến REPL để thử nghiệm, chạy mã dùng một lần và tính toán kỹ thuật tương tác.

  • Trình tự đánh giá . Điều này là sai khi ông viết nó. Thứ tự đánh giá là không xác định trong OCaml.

  • Không có đối tượng đầu vào / đầu ra . Ông đã trích dẫn một thư viện bên thứ ba đã giải quyết "vấn đề" này.

  • Trình biên dịch dừng sau lỗi đầu tiên . Hở?

  • Không có dấu vết ngăn xếp cho các thực thi được biên dịch nguyên bản . Đã sửa.

  • Con nợ hút . Tôi không bao giờ sử dụng trình gỡ lỗi. Kiểm tra kiểu tĩnh bắt hầu hết các lỗi của tôi.

  • GC hút . Tôi thấy GC của OCaml là tuyệt vời ngoại trừ một vấn đề lớn: khóa toàn cầu ngăn chặn lập trình song song.

  • Không khai báo ngầm . Đệ quy lẫn nhau được thiết kế rõ ràng trong tất cả các ML. Điều khó khăn duy nhất là các typeđịnh nghĩa được đệ quy theo mặc định trong khi letcác ràng buộc không được đệ quy theo mặc định.

  • Vòng chức năng vắng mặt . OCaml vẫn có một stdlib xương trần nhưng các thư viện bên thứ ba như Jane St's Core cung cấp roundvà bạn bè.

  • Danh sách . List.mapvẫn không đuôi đệ quy. Tôi đã gửi các bản vá để sửa các lỗi nghiêm trọng như thế này và phải đợi nhiều năm trước khi chúng xuất hiện trong các bản phát hành. Danh sách vẫn là bất biến, tất nhiên. Và vì vậy họ nên được.

  • Tốc độ . Tôi tin rằng thời gian biên dịch cho các biến thể đa hình lớn đã được sửa.

  • Mẫu phù hợp . Một chiến thắng của hy vọng trên thực tế. Cộng đồng Lisp đã thất bại trong việc này. Do đó, quy tắc thứ 10 của tôi: bất kỳ chương trình Lisp nào đủ phức tạp đều chứa một triển khai đặc biệt, được chỉ định không chính thức và có lỗi với một nửa trình biên dịch khớp mẫu của OCaml.

Ví dụ: vẫn đúng là không thể in một đối tượng chung?

Khi anh ấy viết rằng bạn không thể đơn giản làm:

print value

nhưng bạn có thể gọi máy in đẹp từ cấp cao nhất dưới dạng cuộc gọi thư viện, cung cấp cho nó thông tin loại cần thiết. Và có một macro mà bạn có thể sử dụng để chú thích cấu trúc dữ liệu để có các máy in đẹp được tự động tạo.


Khớp mẫu: Mã nguồn OCamloptima đều tham chiếu cùng một loại giấy: "Tối ưu hóa khớp mẫu". Tôi có thể nói rằng cả "ad-hoc", "bug-ridden" hay "không chính thức" đều có thể được áp dụng thực tế ở đây. "F # có một giải pháp tuyệt vời cho vấn đề này": Tôi thực sự muốn thấy chi tiết hơn một chút về vấn đề này, nếu có thể. Câu trả lời là tốt nhưng chửi rủa khi nói về việc consđưa ra một giai điệu xấu (bài viết gốc là một lời ca ngợi, nhưng bạn không cần phải sao chép nó từ đó).
coredump

2
@coredump: "Tôi thực sự muốn xem chi tiết hơn một chút về điều này, nếu có thể". F # có tính đa hình ad-hoc do người dùng định nghĩa trên các toán tử và hàm nhất định. Vì vậy, bạn có thể sử dụng +trên ints, float và phức tạp nhưng bạn cũng có thể xác định các loại của riêng bạn và thêm một quá tải +để làm việc trên loại của bạn. Điều này cung cấp sự ngắn gọn và dễ đọc của Lisp hoặc Haskell với hiệu suất dự đoán tốt của SML hoặc OCaml, đạt được điều gì đó mà không ngôn ngữ nào làm được.
Jon Harrop

@coredump: "Mã nguồn OCaml và optima cả hai tham chiếu cùng một bài báo". Các kỹ thuật được mô tả trong bài báo đó được xây dựng hoàn toàn dựa trên hệ thống loại ML. Một hệ thống loại mà Lisp không có. Optima không và không thể làm nhiều điều được mô tả trong bài báo đó. Chỉ cần xem phần 4.2 "Sử dụng thông tin toàn diện". Không có thông tin đầy đủ trong Lisp vì không có loại biến thể. Ví dụ, OCaml chọn giữa các lần nhảy lồng nhau hoặc bảng công văn dựa trên số lượng lá nhưng thông tin đó không được biết trong Lisp.
Jon Harrop

Lisp và OCaml được thiết kế cho những thứ khác nhau (ví dụ như tính năng động, lập trình dựa trên hình ảnh). Nhưng Lisp một hệ thống kiểu, khác nhau từ Hindley-Milner, và triển khai làm khai thác nó trong quá trình biên dịch. Nhìn vào phiên SBCL này với các ví dụ từ phần 4.2 của bài báo. Độ xả đã được kiểm tra bởi trình biên dịch từ kiểu suy luận và khai báo. Optima có thể thêm mã dành riêng cho việc triển khai để mở rộng vĩ mô thời gian biên dịch (hoặc SBCL VOP), để có các chiến lược khác, nhưng không có đủ động lực để thực hiện.
coredump

Làm thế nào điều đó áp dụng cho kiểu dữ liệu đại số do người dùng định nghĩa?
Jon Harrop
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.