Tại sao viết một trình biên dịch bằng ngôn ngữ chức năng lại dễ dàng hơn? [đóng cửa]


88

Tôi đã nghĩ về câu hỏi này rất lâu, nhưng thực sự không thể tìm thấy câu trả lời trên Google cũng như một câu hỏi tương tự trên Stackoverflow. Nếu có một bản sao, tôi xin lỗi vì điều đó.

Có vẻ như nhiều người nói rằng viết các trình biên dịch và các công cụ ngôn ngữ khác bằng các ngôn ngữ chức năng như OCaml và Haskell sẽ hiệu quả hơn và dễ dàng hơn nhiều khi viết chúng bằng các ngôn ngữ mệnh lệnh.

Điều này có đúng không? Và nếu vậy - tại sao viết chúng bằng ngôn ngữ chức năng thay vì bằng ngôn ngữ mệnh lệnh, như C lại hiệu quả và dễ dàng đến vậy? Ngoài ra - không phải một công cụ ngôn ngữ trong một ngôn ngữ chức năng sẽ chậm hơn trong một số ngôn ngữ cấp thấp như C?


5
Tôi sẽ không nói nó dễ dàng hơn. Nhưng bản chất chức năng của các tác vụ biên dịch chẳng hạn như phân tích cú pháp có lẽ khá tự nhiên với lập trình chức năng. Các ngôn ngữ chức năng như OCaml có thể cực kỳ nhanh, sánh ngang với tốc độ của C.
Robert Harvey

17
Mọi người, điều này có thực sự gây tranh cãi không? Chắc chắn ai đó có một số cái nhìn sâu sắc. Tôi muốn biết bản thân mình.
Robert Harvey

Tôi nghĩ rằng ít nhất phải có một số lý do chính đáng để sử dụng ngôn ngữ chức năng thay vì ngôn ngữ mệnh lệnh. Tôi đã tìm thấy một số bài báo về cơ bản nói rằng các ngôn ngữ chức năng không có tác dụng phụ và như vậy. Nhưng nó không thực sự rõ ràng chút nào. Tuy nhiên, nếu điều này là tranh luận, thì tốt hơn là nên đóng nó lại hoặc định dạng lại câu hỏi.
wvd

12
Có thực sự gây tranh cãi khi thừa nhận rằng một số ngách phù hợp hơn với một phong cách ngôn ngữ cụ thể? "Tại sao C tốt hơn Javascript để viết trình điều khiển thiết bị" sẽ không gây tranh cãi, tôi nghĩ ...
CA McCann

1
Tôi nghĩ nó sẽ ngược lại. Tôi đang đọc "trình biên dịch siêu nhỏ" và nó sử dụng biến đột biến ở khắp nơi.
Rolf

Câu trả lời:


101

Thông thường, một trình biên dịch làm việc rất nhiều với cây. Mã nguồn được phân tích cú pháp thành một cây cú pháp. Cây đó sau đó có thể được chuyển đổi thành một cây khác với chú thích kiểu để thực hiện kiểm tra kiểu. Bây giờ bạn có thể chuyển đổi cây đó thành một cây chỉ chứa các phần tử ngôn ngữ cốt lõi (chuyển đổi các ký hiệu cú pháp giống như đường thành một dạng không liên kết). Bây giờ bạn có thể thực hiện các tối ưu hóa khác nhau về cơ bản là các phép biến đổi trên cây. Sau đó, bạn có thể sẽ tạo một cây ở một số dạng bình thường và sau đó lặp lại cây đó để tạo mã đích (lắp ráp).

Ngôn ngữ hàm có các tính năng như khớp mẫu và hỗ trợ tốt cho việc đệ quy hiệu quả, giúp dễ dàng làm việc với cây, vì vậy đó là lý do tại sao chúng thường được coi là ngôn ngữ tốt để viết trình biên dịch.


Câu trả lời đầy đủ nhất cho đến nay, tôi sẽ đánh dấu đây là câu trả lời được chấp nhận, tuy nhiên tôi nghĩ câu trả lời của Pete Kirkham cũng hay.
wvd

1
Còn về "tính đúng đắn", vì tính đúng đắn của trình biên dịch là một thuộc tính quan trọng, tôi thường nghe nói rằng những người hâm mộ ngôn ngữ chức năng kết hợp "bằng chứng" về tính đúng đắn vào quy trình làm việc của họ bằng cách nào đó. Tôi không biết điều đó thực sự có ý nghĩa gì về mặt thực tế, nhưng vì độ tin cậy của trình biên dịch là quan trọng, điều này có vẻ đáng giá.
Warren P

3
@WarrenP: Khái niệm "mã mang bằng chứng" xuất phát từ các ngôn ngữ chức năng được định kiểu tĩnh. Ý tưởng là bạn sử dụng hệ thống kiểu theo cách để một hàm chỉ có thể đánh máy nếu nó đúng, vì vậy thực tế mã biên dịch là bằng chứng về tính đúng đắn. Tất nhiên điều này là không thể hoàn toàn trong khi vẫn giữ cho ngôn ngữ hoàn chỉnh và có thể phân loại được. Nhưng loại hệ thống càng mạnh, bạn càng có thể tiến gần đến mục tiêu đó.
sepp2k

3
Lý do mà khái niệm này chủ yếu phổ biến trong cộng đồng chức năng là trong các ngôn ngữ có trạng thái có thể thay đổi, bạn cũng phải mã hóa thông tin về thời gian và vị trí xảy ra thay đổi trạng thái trong các loại. Trong các ngôn ngữ mà bạn biết rằng kết quả của một hàm chỉ phụ thuộc vào các đối số của nó, thì việc mã hóa một bằng chứng theo các kiểu sẽ dễ dàng hơn nhiều (việc chứng minh bằng tay tính đúng đắn của mã cũng dễ dàng hơn nhiều vì bạn không phải cân nhắc trạng thái toàn cục nào là có thể xảy ra và nó sẽ ảnh hưởng như thế nào đến hành vi của hàm). Tuy nhiên không có điều nào trong số này liên quan cụ thể đến trình biên dịch.
sepp2k

3
Theo tôi, tính năng quan trọng nhất là khớp mẫu. Việc tối ưu hóa một cây cú pháp trừu tượng với kết hợp mẫu thật dễ dàng. Làm điều đó mà không khớp mẫu thường rất khó khăn.
Bob Aman

38

Rất nhiều tác vụ của trình biên dịch là khớp mẫu trên cấu trúc cây.

Cả OCaml và Haskell đều có khả năng đối sánh mẫu ngắn gọn và mạnh mẽ.

Thật khó để thêm đối sánh mẫu vào các ngôn ngữ bắt buộc vì bất kỳ giá trị nào đang được đánh giá hoặc trích xuất để đối sánh với mẫu phải không có tác dụng phụ.


Nghe có vẻ là một câu trả lời hợp lý, nhưng đây có phải là điều duy nhất? chẳng hạn như những thứ như đệ quy đuôi cũng đóng một vai trò?
wvd

Điều đó dường như chỉ ra rằng đó là một vấn đề của hệ thống kiểu hơn là mô hình thực thi thực tế. Một cái gì đó dựa trên lập trình mệnh lệnh với các giá trị bất biến đối với các kiểu cấu trúc có thể ổn.
Donal Fellows

@wvd: Tối ưu hóa đệ quy đuôi là một chi tiết triển khai, không phải là một tính năng ngôn ngữ như vậy, làm cho các hàm đệ quy tuyến tính tương đương với một vòng lặp lặp lại. Một hàm đệ quy để xem danh sách liên kết trong C sẽ được hưởng lợi từ nó giống như việc đệ quy trên một danh sách trong Scheme.
CA McCann

@wvd gcc C có loại bỏ lệnh gọi đuôi, cũng như các ngôn ngữ trạng thái có thể thay đổi khác
Pete Kirkham

3
@camccann: Nếu tiêu chuẩn ngôn ngữ đảm bảo tco (hoặc ít nhất đảm bảo rằng các hàm đệ quy của một dạng nhất định sẽ không bao giờ gây ra tràn ngăn xếp hoặc mức tiêu thụ bộ nhớ tăng tuyến tính), tôi sẽ coi đó là một tính năng ngôn ngữ. Nếu tiêu chuẩn không đảm bảo điều đó, nhưng trình biên dịch vẫn làm được điều đó, thì đó là một tính năng của trình biên dịch.
sepp2k

15

Một yếu tố quan trọng cần xem xét là một phần quan trọng của bất kỳ dự án trình biên dịch nào là khi bạn có thể tự lưu trữ trình biên dịch và "ăn thức ăn cho chó của riêng bạn." Vì lý do này khi bạn nhìn vào các ngôn ngữ như OCaml, nơi chúng được thiết kế để nghiên cứu ngôn ngữ, chúng có xu hướng có các tính năng tuyệt vời cho các vấn đề kiểu trình biên dịch.

Trong công việc biên dịch cuối cùng của tôi, chúng tôi đã sử dụng OCaml vì lý do chính xác này trong khi thao tác mã C, nó chỉ là công cụ tốt nhất cho nhiệm vụ này. Nếu những người ở INRIA đã xây dựng OCaml với các ưu tiên khác nhau thì nó có thể không phù hợp như vậy.

Điều đó nói rằng, các ngôn ngữ chức năng là công cụ tốt nhất để giải quyết bất kỳ vấn đề nào, vì vậy theo logic, chúng là công cụ tốt nhất để giải quyết vấn đề cụ thể này. QED.

/ me: thu thập dữ liệu trở lại các tác vụ Java của tôi kém vui hơn một chút ...


4
-1 cho "ngôn ngữ chức năng là công cụ tốt nhất để giải quyết mọi vấn đề." Nếu điều này là đúng, tất cả chúng ta sẽ sử dụng chúng ở mọi nơi. ;)
Andrei Krotkov

15
@Andrei Krotkov: Từ mới bắt đầu trong ngày là fa · ce · tious Cách phát âm: \ fə-ˈsē-shəs \ Chức năng: tính từ Từ nguyên: Trung Pháp facetieux, từ facetie jest, từ facetia trong tiếng Latinh Ngày: 1599 1: đùa cợt hoặc giễu cợt thường không thích hợp : waggish <chỉ là đểu cáng> 2: có nghĩa là hài hước hoặc hài hước: không nghiêm túc. Bạn đang cho rằng tất cả mọi người đều là những tác nhân lý trí, và tôi e rằng, đó không phải là một giả định công bằng.
Ukko

5
Tôi đoán là tôi đã bỏ lỡ trò đùa, vì tôi biết những người trong cuộc sống thực sẽ nói khá nhiều điều chính xác, ngoại trừ hoàn toàn nghiêm túc. Tôi đoán định luật Poe. tvtropes.org/pmwiki/pmwiki.php/Main/PoesLaw
Andrei Krotkov

13
@Andrei: Sử dụng quảng cáo đối số của bạn : "Nếu lý trí tốt hơn sự thiếu hiểu biết về cảm xúc, tất cả chúng ta sẽ sử dụng nó ở mọi nơi."
Tim Schaeffer

9

Về cơ bản, trình biên dịch là sự chuyển đổi từ bộ mã này sang bộ mã khác - từ nguồn sang IR, từ IR sang IR tối ưu hóa, từ IR sang assembly, v.v. Đây chính xác là loại ngôn ngữ chức năng được thiết kế cho - một hàm thuần túy là chỉ là sự biến đổi từ vật này sang vật khác. Các chức năng bắt buộc không có chất lượng này. Mặc dù bạn có thể viết loại mã này bằng ngôn ngữ mệnh lệnh, nhưng các ngôn ngữ chức năng là chuyên biệt cho nó.


6

Xem thêm

Mẫu thiết kế F #

FP nhóm mọi thứ 'theo hoạt động', trong khi OO nhóm mọi thứ 'theo loại' và 'theo hoạt động' tự nhiên hơn đối với trình biên dịch / thông dịch.


3
Điều này liên quan đến cái được gọi, trong một số vòng tròn Lý thuyết Ngôn ngữ Lập trình, là "bài toán biểu thức". Ví dụ, hãy xem câu hỏi này , trong đó tôi chứng minh một số mã Haskell thực sự khủng khiếp thực hiện mọi thứ theo cách "loại có thể mở rộng". Ngược lại, việc buộc ngôn ngữ OOP theo kiểu "hoạt động có thể mở rộng" có xu hướng thúc đẩy Mẫu khách truy cập.
CA McCann

6

Một khả năng là một trình biên dịch có xu hướng phải xử lý rất cẩn thận với một loạt các trường hợp góc. Việc lấy đúng mã thường được thực hiện dễ dàng hơn bằng cách sử dụng các mẫu thiết kế cấu trúc việc triển khai theo cách tương đồng với các quy tắc mà nó triển khai. Thông thường, kết thúc là một thiết kế khai báo (đối sánh mẫu, "ở đâu") hơn là thiết kế mệnh lệnh (sắp xếp theo trình tự, "khi nào") và do đó dễ triển khai hơn trong ngôn ngữ khai báo (và hầu hết chúng đều có chức năng).


4

Có vẻ như mọi người đã bỏ qua một lý do quan trọng khác. Khá dễ dàng để viết một ngôn ngữ dành riêng cho miền được nhúng (EDSL) cho các trình phân tích cú pháp trông giống như (E) BNF trong mã thông thường. Các tổ hợp phân tích cú pháp như Parsec khá dễ viết bằng các ngôn ngữ chức năng bằng cách sử dụng các hàm bậc cao hơn và thành phần hàm. Không chỉ dễ dàng hơn mà còn rất thanh lịch.

Về cơ bản, bạn đại diện cho các trình phân tích cú pháp chung đơn giản nhất chỉ là các hàm và bạn có các phép toán đặc biệt (thường là các hàm bậc cao hơn) cho phép bạn soạn các trình phân tích cú pháp nguyên thủy này thành các trình phân tích cú pháp phức tạp hơn, cụ thể hơn cho ngữ pháp của bạn.

Tất nhiên, đây không phải là cách duy nhất để thực hiện các khuôn khổ parer.

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.