Tại sao nghiên cứu một thông dịch viên lisp trong lisp rất quan trọng?


30

Tôi đã thấy nhiều chương trình giảng dạy CS và đề xuất học tập cho các lập trình viên mới kêu gọi lập trình viên khao khát nghiên cứu một trình thông dịch lisp được viết cụ thể bằng lisp. Tất cả các trang web này đều nói những điều tương tự như "đó là một tiết lộ trí tuệ", "đó là một trải nghiệm khai sáng mà mọi lập trình viên nghiêm túc nên có" hoặc "nó cho bạn thấy mối quan hệ phần cứng / phần mềm" và các tuyên bố mơ hồ khác, đặc biệt từ bài viết này được lấy từ bài viết này Cách làm uy tín này .

Tâm lý chung của câu hỏi của tôi là, làm thế nào để lisp đạt được các mục tiêu trên và tại sao lại không? Tại sao không phải là một số ngôn ngữ khác?

Tôi đang hỏi điều này bởi vì tôi vừa viết xong một trình thông dịch lược đồ trong lược đồ (lấy từ SICP http://mitpress.mit.edu/sicp/ ) và bây giờ tôi đang viết một trình thông dịch python trong lược đồ và tôi đang đấu tranh để có bản hùng ca huyền thoại này đó được cho là đặc biệt đến từ trước đây. Tôi đang tìm kiếm các chi tiết kỹ thuật cụ thể giữa hai ngôn ngữ mà tôi có thể khai thác trong trình thông dịch lược đồ của họ để hiểu được cách thức các chương trình hoạt động.

Cụ thể hơn:

Tại sao nghiên cứu về một thông dịch viên được viết bằng ngôn ngữ mà nó diễn giải lại được nhấn mạnh đến vậy - nó chỉ là một bài tập tinh thần tuyệt vời để giữ cho ngôn ngữ gốc và ngôn ngữ được xây dựng thẳng hay có những vấn đề cụ thể mà các giải pháp chỉ có thể được tìm thấy trong bản chất của ngôn ngữ gốc?

Làm thế nào để thông dịch viên lisp thể hiện các khái niệm kiến ​​trúc tốt cho thiết kế phần mềm trong tương lai?

Tôi sẽ bỏ lỡ điều gì nếu tôi thực hiện bài tập này bằng một ngôn ngữ khác như C ++ hoặc Java?

Các takeaway hoặc "công cụ tinh thần" được sử dụng nhiều nhất từ bài tập này là gì? **

** Tôi chọn câu trả lời tôi đã làm vì tôi đã nhận thấy rằng tôi đã đạt được từ bài tập này kỹ năng hơn trong việc thiết kế các công cụ phân tích trong đầu của tôi hơn bất kỳ công cụ nào khác và tôi muốn tìm phương pháp khác nhau của phân tích cú pháp có thể làm việc tốt hơn cho chương trình này thông dịch viên hơn phiên dịch python.



4
@gnat Không chính xác lời khuyên nghề nghiệp, nhiều hơn một câu hỏi "những gì tuyệt vời về Lisp".
Robert Harvey

1
@RobertHarvey liên kết đó không chỉ cho sự nghiệp mà còn cho lời khuyên giáo dục , tôi có ý này. Nhưng, chà , Lisp-is-so-great có lẽ cũng phù hợp
gnat

1
Bạn dường như đang hỏi những gì bạn sẽ học được từ một bài tập cụ thể. Sự thận trọng của bạn là một dấu hiệu của sự lười biếng, chìa khóa cho bất kỳ lập trình viên giỏi nào, nhưng bất kể cách duy nhất để tìm hiểu những gì bạn sẽ học được từ một bài tập là làm điều đó và xem. Không ai có thể nói cho bạn biết bạn sẽ học được gì khi làm điều đó, bạn sẽ phải làm điều đó.
Jimmy Hoffa

2
Trong khi câu hỏi này liên quan đến giáo dục nói chung, tôi sẽ không phân loại nó là "lời khuyên giáo dục" theo cách "Tôi nên học ngôn ngữ nào?" Là. Đó là, nó không cụ thể cho một loại khóa học hoặc công việc nhất định. Trong thực tế, nếu bạn cắt bỏ một số từ thông dụng giáo dục, đây là một câu hỏi về toàn bộ ngôn ngữ lập trình, có câu trả lời thảo luận về các tính năng ngôn ngữ. Nó thực sự không đặc trưng cho Lisp, nhưng có thể được áp dụng cho các ngôn ngữ đồng âm khác như xslt. Vì vậy, tôi sẽ không nói đây là một câu hỏi hoàn hảo, chỉ là nó không chỉ đơn giản là "lời khuyên nghề nghiệp".
TheRubberDuck

Câu trả lời:


17

Có nguy cơ đưa ra câu trả lời "tôi cũng vậy", nếu bạn thử nó, bạn sẽ thấy ...

Nếu bạn học ngôn ngữ máy tính, bạn có thể có ấn tượng rằng ít nhất một nửa về phân tích cú pháp. Nếu bạn học Lisp, bạn sẽ nhận ra việc phân tích cú pháp bề mặt không gì khác hơn là sự tiện lợi cho mọi người (như hầu hết chúng ta), những người không thích nhiều Dấu ngoặc đơn gây khó chịu.

Sau đó, bạn có thể nhận ra rằng một cái giá lớn đã được trả cho sự thuận tiện đó. Trong Lisp, việc một chương trình xây dựng một chương trình khác và thực hiện nó là chuyện nhỏ. Trong các ngôn ngữ khác, nó là một kỹ thuật tiên tiến, giống như thực hiện phép nhân số La Mã.

Tất nhiên, gần như tất cả mọi người sẽ hỏi "ai cần làm điều đó?" Chà, bạn rất có thể thấy rằng nó mở ra cả một vista những điều bạn thậm chí chưa bao giờ nhận ra bạn không thể làm trước đây. Bạn có thể làm điều đó bằng các ngôn ngữ khác, nhưng không dễ dàng như vậy.

XÁC NHẬN để trả lời bình luận của Izkata:

  • Chương trình hiểu ngôn ngữ tự nhiên SHRDLU hoạt động bằng cách dịch một câu hoặc câu hỏi tiếng Anh sang một chương trình theo phương ngữ Lisp có tên MICRO-PLANNER và thực hiện nó.
  • Các chương trình thao túng các chương trình, ví dụ để đơn giản hóa chúng hoặc chứng minh chúng đúng được viết tự nhiên bằng Lisp.
  • Tôi đã sử dụng việc tạo chương trình trong một chương trình để hiểu các cảnh trực quan, trong đó nó phải xử lý tất cả các đối xứng có khả năng trong các đối tượng 3 chiều, mà không cần nhân mã.
  • Bất cứ điều gì phải làm với logic và các thỏa thuận chứng minh định lý trong việc điều khiển các biểu thức logic, là một dạng của chương trình.
  • Toán học tượng trưng, ​​chẳng hạn như tích phân biểu tượng hoặc phép tính vi phân, liên quan đến thao tác các biểu thức toán học, giống như các chương trình thu nhỏ.
  • Bất kỳ vấn đề nào liên quan đến việc tạo mã, hoặc thuật ngữ "đánh giá một phần" cao hơn, là điều tự nhiên ở Lisp. Tôi đã làm điều này cho một chương trình cầu cơ sở dữ liệu từ lâu. Tôi đã làm nó trong C, điều này không dễ như Lisp, nhưng tôi đã có ý tưởng từ Lisp. Đó được coi là một kỹ thuật mà hầu như không ai có thể làm vào thời điểm đó (đặc biệt là các đầu của COBOL). Có lẽ nhiều hơn bây giờ, tôi hy vọng.

... đó chỉ là một vài ...

Sau đó, bạn nhận ra một số thứ được coi là "hiện đại" ngày nay đã trở thành chiếc mũ cũ ở Lisp trong 40 năm. Giống như lập trình chức năng. Giống như thu gom rác. Giống như đóng cửa.

Điều đó không có nghĩa là các ngôn ngữ hiện đại không có những ý tưởng hay mới, như OOP, v.v. Nhưng nếu bạn học Lisp, nó sẽ mở rộng tầm nhìn của bạn.


You can do it in other languages, but not nearly so easily.- Như? (Câu hỏi đối với tôi dường như là bởi vì những câu như thế này thường được đưa ra, nhưng hầu như không bao giờ được cụ thể hơn)
Izkata

Đầu tiên tôi nghĩ rằng thế giới đã được cách mạng hóa khi tôi nhận ra javascript có thể in mã nguồn của chính nó và các đối tượng có thể được duyệt qua để có được chuỗi ký tự có thể được đưa vào trong đối tượng theo nghĩa đen. Sau đó, tôi nhận ra Perl có tất cả những thứ này cùng với $ Data :: Dumper :: Depude, và rồi tôi nhận ra rằng lisp có thứ này mãi mãi. Hiểu các phiên dịch viên giải phóng sức mạnh này luôn có sẵn để xây dựng các mô-đun sống và trong Lisp, điều này dễ tiếp cận hơn bất kỳ ngôn ngữ nào khác.
Dmitry

Điều thú vị là một lập trình viên Lisp nhận thức được nội bộ Lisps luôn có thể tạo ra lối đi Lisp của riêng họ cho bất kỳ ngôn ngữ động nào từ javascript đến bash hoặc perl hoặc python; bootstraps độc đáo từ môi trường có sẵn.
Dmitry

19

Câu trả lời đơn giản cho câu hỏi của bạn là dùng thử Lisp, tốt nhất là kết hợp với SICP . Rồi bạn sẽ được giác ngộ.

Mà nói...

Mã là dữ liệu
Hầu hết các ngôn ngữ tạo ra sự khác biệt rõ ràng giữa mã và dữ liệu; Lisp thì không. Điều này cho phép, ví dụ, có thể viết một trình phân tích cú pháp Lisp trong Lisp và thao tác mã Lisp trong Lisp. Mô tả tốt nhất về sự giác ngộ này mà tôi đã tìm thấy là Bản chất của Lisp .

Điều này đúng một phần vì cú pháp của ngôn ngữ rất đơn giản. Nó làm cho những điều có thể có trong Lisp (như siêu lập trình) không thực tế trong các ngôn ngữ khác vì cú pháp gây cản trở.

Đọc thêm
Đánh bại mức trung bình


3
Đoạn 2 không có nghĩa: homoiconicity! = Cú pháp đơn giản; cú pháp đơn giản giúp bạn dễ dàng viết trình phân tích cú pháp Lisp bằng bất kỳ ngôn ngữ nào (xem phần này ). Đoạn 3 mơ hồ, cần ví dụ (s).

@MattFenwick đúng là sự đồng âm có thể được thực hiện với cú pháp phức tạp, nhưng điều đó sẽ cực kỳ khó khăn. Thật công bằng khi cho rằng nếu bạn đang xử lý một cú pháp đồng âm, nó sẽ đơn giản, nếu không vì lý do nào khác ngoài sự nhất quán đòi hỏi nó sẽ làm cho nó dễ theo dõi hơn một cú pháp không đồng âm. Mặc dù điểm thứ hai của bạn là một điểm tốt, LISP rất dễ phân tích vì đó là cú pháp đơn giản, không phải vì tính đồng âm (ngay cả khi tính đồng âm là nguyên nhân cho sự đơn giản đó)
Jimmy Hoffa

1
Trong mọi trường hợp, có rất ít chi phí để lấy một giá trị dữ liệu và diễn giải nó như một chương trình. Đây là một điều tốt đẹp. Lập trình theo cấu hình là đơn giản khi tất cả những gì bạn phải làm là viết một trình thông dịch cho dữ liệu cấu hình. Các phép biến đổi toán học nâng cao (khó thực hiện trong các langau trạng thái) thường được "giảm" thành các phép biến đổi cú pháp đơn thuần của đoạn thuần Lisp.
Tên của

1
@MattFenwick: Tôi đã xóa từ "Homoiconicity" khỏi câu trả lời của mình.
Robert Harvey

1
Tôi ước tôi có thể cho nhiều hơn +1 cho Bản chất của Lisp; Tôi chưa bao giờ thấy một lời giải thích tuyệt vời như vậy.
Doval

9

Tại sao nghiên cứu về một thông dịch viên được viết bằng ngôn ngữ mà nó diễn giải lại được nhấn mạnh như vậy?

Nói chung, nghiên cứu một thông dịch viên cung cấp cho bạn cái nhìn sâu sắc về ngôn ngữ và các tính năng của nó. Nói chung, học mã trong ngôn ngữ lập trình cũng giống như thực hành ngôn ngữ nói bằng cách nghe và đọc: nó làm quen với những gì ngôn ngữ đó có thể làm, cách sử dụng và "thành ngữ" phổ biến. Cụ thể hơn, Lisp là một ngôn ngữ đồng âm, có nghĩa là cú pháp biểu thức của nó giống như cú pháp của dữ liệu. Viết mã bằng Lisp trông khủng khiếp giống như bạn đang viết ra một danh sách và ngược lại. Do đó, việc giải thích mã Lisp bằng mã Lisp cũng đơn giản như chạy qua các danh sách với carcdr.

Làm thế nào tôi nên tận dụng bài tập này để đạt được hiệu quả cao nhất về mặt khái niệm?

Hãy suy nghĩ về cách trình thông dịch sẽ tự diễn giải - trong nhiều triển khai trình thông dịch siêu vòng tròn (trong đó bản thân một trình thông dịch ngôn ngữ đồng âm) chỉ có thể "chuyển qua" chức năng. Ví dụ, để thực hiện car, chỉ cần lấy carđối số. Điều này làm mất đi sự nhấn mạnh từ các cơ chế lưu trữ dữ liệu và tập trung vào chức năng.

Làm thế nào để thông dịch viên lisp thể hiện các khái niệm kiến ​​trúc tốt cho thiết kế phần mềm trong tương lai?

Thông dịch viên có thể rất phức tạp, điều này khuyến khích kiến ​​trúc tốt trong việc thiết kế chúng. Với ý nghĩ đó, điều này phụ thuộc nhiều hơn vào từng phiên dịch viên.

Tôi sẽ bỏ lỡ điều gì nếu tôi thực hiện bài tập này bằng một ngôn ngữ khác như C ++ hoặc Java?

Các ngôn ngữ này không phải là đồng âm, vì vậy chúng không được hưởng lợi từ sự duyên dáng và đơn giản của trình thông dịch Lisp siêu vòng tròn. Điều này làm cho bài tập khó hơn và có lẽ ít phổ biến hơn, nhưng tôi sẽ không nói nó thực sự ít lợi ích hơn.

Các takeaway hoặc "công cụ tinh thần" được sử dụng nhiều nhất từ ​​bài tập này là gì?

Tôi không chắc mình có câu trả lời hay cho câu hỏi này không; chỉ đơn giản là nó giúp xem trình thông dịch làm việc như thế nào và có thể quan trọng hơn là tìm hiểu về nó để xem những thay đổi nhỏ trong ngôn ngữ có thể được thực hiện dễ dàng như thế nào.


5

LISP được cấu trúc theo cách làm cho nó dễ dàng phân tích cú pháp. Nếu bạn cố gắng viết một trình biên dịch, bạn sẽ nhận thấy rằng nó dễ dàng hơn rất nhiều nếu mọi thứ trong ngôn ngữ của bạn là một biểu thức và có mức độ mơ hồ thấp. LISP buộc các dấu ngoặc ở khắp mọi nơi để loại bỏ sự mơ hồ và không có tuyên bố, chỉ có biểu thức.

Thực tế là LISP rất dễ phân tích khuyến khích người dùng phân tích mã nguồn của chính họ và thực hiện các trò ảo thuật với nó. Dòng giữa dữ liệu và mã trở nên mờ và bạn có thể dễ dàng thực hiện những việc thường đòi hỏi khá nhiều nỗ lực, như phản chiếu, viết lại mã động, bổ trợ và tuần tự hóa.

Đó là ý chính của nó. Bài tập có lẽ là để cung cấp cho bạn cái nhìn sâu sắc về những gì có thể khi mã dễ dàng được phân tích cú pháp từ chính nó.


Nó không phải là Lisp dễ dàng phân tích. S-Expressions rất dễ phân tích. Trên hết, bạn cần phải phân tích Lisp.
Rainer Joswig

@Rainer: Không phải chỉ là nitpicking sao? Trong thế giới của tôi, phân tích cú pháp có nghĩa là chuyển từ văn bản sang AST, không nói gì về việc diễn giải các lệnh.
Alexander Torstling

Trong C ++, trình phân tích cú pháp sẽ phát hiện một khai báo hàm sai về mặt cú pháp. Ở Lisp thì không. Người đọc không biết gì về ngôn ngữ lập trình Lisp. Trình phân tích cú pháp C ++ biết cú pháp C ++ đầy đủ. Người đọc Lisp chỉ biết biểu thức s.
Rainer Joswig

Ah, sau đó tôi hiểu ý của bạn. Đúng, mặc dù tôi vẫn nghĩ rằng một trình đánh giá lisp đơn giản sẽ được xây dựng đơn giản hơn so với một c ++ đơn giản. Đó là những gì họ làm trong SICP, phải không (đã một thời gian kể từ khi tôi đọc nó)?
Alexander Torstling

ngôn ngữ được sử dụng trong SICP rất đơn giản, thậm chí không đầy đủ Đề án. Một thông dịch viên cho một ngôn ngữ C nhỏ xíu cũng nên đơn giản. C ++ lớn. Một số khó khăn của nó đến từ một số lượng cú pháp tích hợp tương đối cao. Trong một hệ thống Lisp điển hình, phần lớn cú pháp được xây dựng với các macro - bên ngoài trình thông dịch. Macro thực hiện cú pháp và một cơ chế mở rộng cho các biến đổi nguồn. Điều này giữ cho lõi nhỏ hơn. Nhưng các macro có thể rất lớn. Ví dụ, việc triển khai cho cấu trúc LOOP có hơn 2000 dòng mã macro phức tạp.
Rainer Joswig

4

Tôi không chắc nó thực sự quan trọng đối với mọi người. Bạn có thể là một nhà phát triển thành công mà không cần biết trình thông dịch Lisp hoạt động như thế nào. Khi học Khoa học Máy tính, những ý tưởng cơ bản của Lisp nên được học.

Thông dịch viên Lisp rất quan trọng đối với các lập trình viên Lisp. Họ cần hiểu cách thức Thông dịch viên ([và trình biên dịch] 1 ) hoạt động, để hiểu đầy đủ cách sử dụng ngôn ngữ.

Trình thông dịch Lisp thường được sử dụng như một công cụ trong khoa học máy tính để dạy cho sinh viên một số điều:

Là một thiết bị giảng dạy, một thông dịch viên Lisp rất hữu ích, bởi vì nó có thể được học và hiểu trong thời gian nhỏ. Vì ít sinh viên đã biết về Lisp, các sinh viên đang ở trên một cấp độ khi nói đến việc học các khái niệm trên.

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.