2010-04-19 40 views
20

Paul Graham đã viết rằng "The unusual thing about Lisp-- in fact, the defining quality of Lisp-- is that it can be written in itself." Nhưng điều đó dường như không có chút bất thường hoặc dứt khoát với tôi. ISTM là ngôn ngữ lập trình được xác định bởi hai thứ: Trình biên dịch hoặc thông dịch viên, định nghĩa cú pháp và ngữ nghĩa cho ngôn ngữ của fiat và thư viện chuẩn của nó, xác định mức độ lớn các thành ngữ và kỹ thuật có kỹ năng người dùng sẽ sử dụng khi viết mã bằng ngôn ngữ.Điều gì có nghĩa là "Lisp có thể được viết trong chính nó?"

Với một vài ngoại lệ cụ thể, (các thành viên không phải là C# của gia đình .NET), các thư viện chuẩn của hầu hết các ngôn ngữ được viết bằng ngôn ngữ đó vì hai lý do rất tốt: vì nó sẽ chia sẻ cùng một tập hợp các định nghĩa cú pháp, các quy ước gọi điện, và "nhìn và cảm nhận" chung của ngôn ngữ, và bởi vì những người có khả năng viết một thư viện chuẩn cho một ngôn ngữ lập trình là người dùng của nó, và đặc biệt là các nhà thiết kế của nó. Vì vậy, không có gì độc đáo ở đó; đó là tiêu chuẩn khá.

Và một lần nữa, không có gì độc đáo hoặc bất thường về trình biên dịch của ngôn ngữ được viết trong chính nó. C trình biên dịch được viết bằng C. Pascal trình biên dịch được viết bằng Pascal. Trình biên dịch C# của Mono được viết bằng C#. Heck, thậm chí some scripting languages có triển khai "tự viết".

Vì vậy, điều gì có nghĩa là Lisp không bình thường khi được viết vào chính nó?

+6

Như bạn nói, một trình biên dịch tự lưu trữ hoặc thông dịch viên không có tin tức gì cả. Một ngôn ngữ có cây cú pháp trừu tượng * là * mã, mà bản thân nó hoàn toàn có thể thao tác như dữ liệu, ngược lại, là một con vật khác. Quét giấy McCarthy mà Paul Graham đã bình luận, không có câu hỏi hợp lý nào về tính đối xứng này. –

+2

http://stackoverflow.com/questions/1481053/what-is-the-exact-definition-of-a-metacircular-interpreter –

Trả lời

10

Có lẽ ý nghĩa của Phao-lô là biểu thị cú pháp của Lisp là giá trị Lisp được tiêu chuẩn hóa và phổ biến. Đó là, một chương trình Lisp chỉ là một loại đặc biệt của biểu thức S, và nó đặc biệt dễ dàng để viết mã Lisp thao túng mã Lisp. Viết một trình thông dịch Lisp trong Lisp là một trường hợp đặc biệt, và không phải là thú vị như khả năng chung để có một đại diện thống nhất cho cả mã và dữ liệu.

+6

Những gì bạn mô tả là thuộc tính của ngôn ngữ là [homoiconic] (http: // vi .wikipedia.org/wiki/Homoiconic), cũng là một đặc điểm được chia sẻ bởi các ngôn ngữ khác. –

+0

@Greg: Tôi luôn có một điểm mềm cho TRAC (và người kế nhiệm của nó, MINT), nhưng ý thức của tôi là những người lập trình chưa bao giờ tận dụng lợi thế của homoiconicity theo cách mà các lập trình viên của Lisp ... –

+3

Tôi không bao giờ có thể đọc được từ đó homoiconic mà không nghĩ đến Judy Garland. –

7

Vâng, liên kết bạn cung cấp sẽ tiếp tục để nói rằng, nếu bạn tiếp tục đọc, anh ấy sẽ trả lời chi tiết câu hỏi của bạn.

Điều bất thường về Lisp-- trong thực tế, chất lượng xác định của Lisp-- là nó có thể được viết trong chính nó. Để hiểu ý nghĩa của McCarthy là , chúng ta sẽ truy xuất lại các bước của mình, với ký hiệu toán học của mình được dịch thành mã Common Lisp .

+2

Vâng, và sau đó bài viết kết thúc. –

+0

@Mason: Bạn có thể tải xuống tệp PostScript, chuyển đổi tệp thành PDF tại đây: http://www.ps2pdf.com/convert.htm và đọc bằng Adobe Reader. Đó là khoảng mười ba trang dài. –

+1

Có liên kết đến toàn bộ bài viết trên dòng tiếp theo ... – harto

7

Tôi vừa xóa câu trả lời rất dài có thể không phù hợp ở đây.

Tuy nhiên xem xét rằng:

  1. LISP không có "cú pháp" nếu bạn có nghĩa là nó có nghĩa là nó có cho các ngôn ngữ như C/Java/Pascal ... có một (ban đầu nhưng tùy chỉnh) cú pháp cho người đọc LISP Common, nhưng đó là một điều khác nhau (LISP rằng Graham đang nói về không phải là Common LISP và (những) người đọc là không phải là ngôn ngữ LISP, nhưng chỉ là một thủ tục). Giống như "(lambda (x) (* x 2))" là không Mã LISP, nhưng văn bản ví dụ trình đọc chuẩn CL có thể chuyển thành mã LISP.

  2. LISP không chỉ thể được viết bằng LISP (nếu bạn có nghĩa là "bootstrap" khả năng) nhưng nó thực sự đã vào sự tồn tại như vậy. Việc thực hiện đầu tiên của eval vào cuối những năm 1950 được viết bằng LISP trên giấy, và sau đó chuyển đổi theo cách thủ công sang ngôn ngữ máy (1): LISP bắt đầu như một ý tưởng hoàn toàn lý thuyết không phải là . Tôi không biết ngôn ngữ máy tính nào khác theo sau đường dẫn đó. Ví dụ C++ đã được hình thành như là một bộ xử lý trước cho một trình biên dịch C và được viết bằng C, nó không phải là một chương trình C++ sau này được chuyển thành C thành có thể chạy nó.

Có rất nhiều khía cạnh khác, trong đó LISP khá khác nhau, và tôi nghĩ rằng cách tốt nhất để có được một nắm bắt của nó là để thực sự thực hiện một thông dịch viên toy LISP (đó là một công việc nhỏ hơn là khi làm suy nghĩ đặc biệt nếu "ngôn ngữ máy" của bạn là một ngôn ngữ động được đánh máy cao cấp như Python).

(1) trong http://www-formal.stanford.edu/jmc/history/lisp/node3.html bạn có thể tìm thấy cách McCarthy mô tả rằng eval[e, a] được tìm thấy trên giấy đầu tiên như một kết quả lý thuyết thú vị (một chức năng "phổ quát" thực hiện neater hơn một máy Turing chung) khi chỉ cấu trúc dữ liệu và chức năng gốc cơ bản đã được đặt ra cho ngôn ngữ Lisp nhóm đang xây dựng. Chức năng viết tay này được thực hiện bởi S.R. Russell trong mã máy và bắt đầu phục vụ chúng như là thông dịch viên Lisp đầu tiên.

+0

Tôi có thể tìm thấy ở đâu "triển khai eval đầu tiên vào cuối những năm 1950 [được viết bằng LISP trên giấy" –

+0

@ RenéG: Xem câu trả lời đã chỉnh sửa, tôi đã thêm một tài liệu tham khảo. – 6502

6

Anh ấy không nói rằng Lisp có thể được sử dụng để viết trình biên dịch Lisp. Anh ấy nói rằng ngôn ngữ được tạo thành từ các cấu trúc dữ liệu của riêng nó. Vì vậy, trong khi bạn không thể xây dựng một hàm C trong cấu trúc dữ liệu C, bạn có thể làm điều đó trong Lisp. Một chương trình được tạo thành từ các danh sách được thực thi bởi máy tính của bạn và hiệu quả của các danh sách đó có thể là tạo các danh sách khác sau đó được thực thi và hiệu quả của các danh sách đó có thể là tạo nhiều danh sách hơn để thực thi. C không có tài sản này. Ví dụ, mã C không thể thao tác AST của riêng nó.

+1

Mã C có thể tự thao tác. Thực ra, tôi tin rằng Mã tự sửa đổi khá phổ biến trong một thời gian. – Ponkadoodle

+5

@wallacoloo: Có sự phân biệt tinh tế giữa ngôn ngữ * và * triển khai * ở đây. Mã C không thể thao tác ** chính nó **, nhưng nó có thể thao tác mã ** ngôn ngữ máy ** mà nó được cài đặt. Đó là một mức trừu tượng hoàn toàn khác với thao tác mã Lisp trong Lisp. –

+0

Ồ, từ khóa có AST, đó là bản chỉnh sửa hoặc thứ tôi đã bỏ lỡ. Xin lỗi, và cảm ơn vì đã làm rõ. – Ponkadoodle

4

Ý tưởng chính là ngôn ngữ Lisp có một hạt nhân rất nhỏ của một hàm số ít và cơ chế đánh giá chính có thể được viết bằng mã trên một trang duy nhất.

Đó là lõi của Lisp.

Để hiểu được hoạt động cơ bản của ngôn ngữ nó chỉ là cần thiết để nhìn vào đó trang duy nhất mã: nó giải thích như thế nào biến làm việc, làm thế nào chức năng kêu gọi các công trình, làm thế nào các chức năng mới có thể được tạo vv

Just suy nghĩ về số tiền bạn có thể xóa khỏi triển khai ngôn ngữ để tìm hiểu các khái niệm cơ bản. Bộ nguyên thủy tối thiểu là gì và động cơ thực hiện tối thiểu là gì. Để viết một Lisp trong một Lisp bạn nhận được xuống hầu như không có gì.

Nếu bạn xem xét triển khai PASCAL (ví dụ), nó không được thực hiện trong PASCAL, nhưng trong PASCAL + mã lớn hơn cung cấp các cấu trúc dữ liệu cần thiết để biểu diễn các thực thể ngôn ngữ, trình phân tích cú pháp, trình biên dịch, một thời gian chạy, ... - ra khỏi hộp PASCAL không cung cấp nhiều - một trong những đã xây dựng những (hoặc sử dụng một thư viện).

Wirth (tác giả của Pascal) đã viết một cuốn sách giải thích việc thực hiện một ngôn ngữ giống Pascal rất nhỏ - bạn vẫn phải viết mã đáng kể để triển khai trình phân tích cú pháp, trình tạo mã, thời gian chạy, bộ nạp. ..

Ngược lại, trong một Lisp, mã nguồn Lisp có một biểu diễn tự nhiên và thường trình cốt lõi đánh giá mã Lisp chỉ là một hàm Lisp. Điều này có thể không thực hiện hoặc thực thi Lisp, nó vẫn khác với tình huống PASCAL, nơi mã nguồn không có biểu diễn hữu ích (ngoài chuỗi hoặc tệp) và công cụ thực thi là mã nhiều hơn.

Vì vậy, trong Lisp ta có:

  • một đại diện đơn giản cho mã nguồn (danh sách các biểu tượng)

  • một thực hiện đơn giản của người đánh giá trong một chức năng đơn nhỏ

Ngoài ra, không có gì là cần thiết để thực hiện một đánh giá Lisp trong Lisp.

Các vấn đề liên quan