Lisp có còn tính năng đặc biệt nào KHÔNG được các ngôn ngữ lập trình khác áp dụng không?


35

Lisp có còn tính năng đặc biệt nào KHÔNG được các ngôn ngữ lập trình khác áp dụng không?

Theo Lisp, ý tôi là tất cả các ngôn ngữ lập trình Lisp nói chung. Tôi đã được cho biết Lisp tuyệt vời như thế nào và biết rằng nhiều ngôn ngữ đã được lấy cảm hứng từ Lisp. Nhưng Lisp vẫn có bất kỳ tính năng thiết kế độc quyền nào mà không thể thực hiện bằng bất kỳ ngôn ngữ nào khác?

Lý do tôi đặt câu hỏi là vì gần đây, bản thân tôi là một lập trình viên nghiệp dư, tôi bắt đầu học Clojure chỉ để giải trí, và kết quả là tôi đã tìm thấy rất nhiều bài đăng và bình luận liên quan đến Lisp, nhưng nói một điều: "Lisp là duy nhất ", Nhưng các ngôn ngữ lập trình hiện đại khác đã áp dụng và đánh cắp rất nhiều ý tưởng từ Lisp, như điều kiện, đệ quy và chức năng như một công dân hạng nhất. Và thậm chí siêu lập trình có thể được thực hiện bằng nhiều ngôn ngữ.

Tôi đã bỏ lỡ điều gì đó và "Lisp vẫn khác"?

Hoặc tôi may mắn vì các ngôn ngữ hiện đại khác đã đánh cắp tất cả các phần hay từ Lisp để không cần phải đào sâu vào dấu ngoặc đơn trong thế giới Lisp và "Lisp thì khác".


3
Chia sẻ nghiên cứu của bạn giúp mọi người. Hãy cho chúng tôi những gì bạn đã cố gắng và tại sao nó không đáp ứng nhu cầu của bạn. Điều này chứng tỏ rằng bạn đã dành thời gian để cố gắng tự giúp mình, nó giúp chúng tôi tránh nhắc lại các câu trả lời rõ ràng và hầu hết nó giúp bạn có được câu trả lời cụ thể và phù hợp hơn. Xem thêm Cách hỏi
gnat

3
@gnat Thx để được tư vấn và tôi đã cập nhật câu hỏi của mình :)
iceX

10
Một vấn đề là, một khi ngôn ngữ có một tập hợp con các tính năng Lisp nhất định (ví dụ: biểu thức S và macro), mọi người cho rằng đó là ngôn ngữ Lisp. Tất nhiên điều này có hậu quả là (theo những người này) không có ngôn ngữ phi Lisp nào có thể có các tính năng này.

9
Tôi đoán không có ngôn ngữ nào khác trong đó dấu ngoặc tròn là hình thức nhóm duy nhất cho mọi thứ :-)
Doc Brown

Lisp như một gia đình có thể không phải là độc nhất vô cùng, nhưng rất nhiều phương ngữ không thể thiếu (Vợt, CL, Scheme, Clojure) vẫn cung cấp rất nhiều tính năng hữu ích / độc đáo.
Daniel Gratzer

Câu trả lời:


28

Một tài liệu tham khảo chính cho loại câu hỏi này là What Made Lisp Dif . Hai tính năng chính còn lại của Lisp không có sẵn rộng rãi, theo bài viết này tại thời điểm viết bài, là:

8. Một ký hiệu cho mã sử dụng cây biểu tượng.

9. Toàn bộ ngôn ngữ luôn có sẵn. Không có sự phân biệt thực sự giữa thời gian đọc, thời gian biên dịch và thời gian chạy. Bạn có thể biên dịch hoặc chạy mã trong khi đọc, đọc hoặc chạy mã trong khi biên dịch và đọc hoặc biên dịch mã khi chạy.

Bài bình luận đề cập đến từng điểm và đặt tên cho các ngôn ngữ phổ biến có tính năng đó.

8, trong đó (với 9) là những gì làm cho macro Lisp có thể, cho đến nay vẫn là duy nhất đối với Lisp, có lẽ bởi vì (a) nó yêu cầu các parens đó, hoặc một cái gì đó tệ như vậy, và (b) nếu bạn thêm sức mạnh cuối cùng đó , bạn không còn có thể tuyên bố đã phát minh ra một ngôn ngữ mới, mà chỉ thiết kế một phương ngữ mới của Lisp; -)

Lưu ý rằng bài viết này đã được sửa đổi lần cuối vào năm 2002 và trong 11 năm qua đã có rất nhiều ngôn ngữ mới, một số ngôn ngữ có thể kết hợp tất cả các tính năng Lisp này vào thiết kế của chúng.


2
Những tính năng này không phải là duy nhất đối với Lisp (và các biến thể có nguồn gốc trực tiếp) và đã tồn tại khá lâu.
Donal Fellows

21
@iceX: Sự khác biệt giữa JavaScript và các ngôn ngữ như Lisp, Smalltalk, Self, Drameak, APL, Factor, Forth, v.v. là trong JavaScript, các chương trình đã "chết". Chúng là các tệp văn bản. Bạn giết chương trình đang chạy, chỉnh sửa tệp văn bản, sau đó khởi động một bản sao hoàn toàn mới của chương trình. Trong các môi trường khác (được gọi là "sống động"), bạn không bao giờ dừng chương trình đang chạy, bản thân chương trình đang chạy là một tập hợp các đối tượng trong bộ nhớ mà bạn thao tác giống như cách bạn thao tác với bất kỳ đối tượng nào khác, trong khi nó đang chạy . (Lưu ý: điều này không đúng với Clojure, nhưng hầu hết các Lisps lớn tuổi đều làm theo cách này.)
Jörg W Mittag

2
@ JörWWittitt Wow Nhưng ... nếu họ không thể thay đổi nó ... tại sao lại phải sử dụng biểu thức S mà tôi nghĩ là nhằm mục đích thao túng mã ... (cảm giác như tôi vừa rơi vào một hố thỏ sâu, tối)
iceX

4
@iceX: Nhiều ngôn ngữ có evalhoặc tương tự, và khá nhiều ngôn ngữ có thể thực hiện siêu lập trình, ví dụ: Mẫu Haskell của Haskell. Điều duy nhất (được cho là) ​​về Lisp là sự biểu diễn cho dữ liệu, mã và mã meta là giống nhau - không chỉ theo cú pháp, mà nó thực sự là điều tương tự.
tdammers

2
@iceX Eval chỉ là một phần của nó, nhưng không phải là tất cả. Trong Lisp bạn có thể thực thi mã tại thời gian biên dịch. Bạn có thể thực thi mã tại thời điểm đọc. Có clojure hỗ trợ tất cả tính năng động của Lisp, nó có macro, macro đọc và eval, cũng như khả năng gắn REPL vào chương trình đang chạy để sửa đổi nó một cách nhanh chóng.
ném đá

15

Câu hỏi là một câu hỏi khó trả lời, vì ai đó sẽ phải biết tất cả các ngôn ngữ để biết rằng không có ngôn ngữ nào khác có sẵn trong Lisp, vì vậy những điều sau đây dựa trên các ngôn ngữ tôi có kinh nghiệm.

Ngoài đỉnh đầu, điều kiện là thứ mà tôi chưa từng thấy trong bất kỳ ngôn ngữ nào khác. Hãy suy nghĩ 'ngoại lệ', nhưng nơi ngăn xếp cuộc gọi không phải là không có, và nơi người gọi có thể gửi giá trị khôi phục đến trang web ngoại lệ, nhưng không làm phiền ngăn xếp cuộc gọi ở giữa trình xử lý và nguồn của ngoại lệ. Công bằng mà nói, đây thực sự chỉ là một ứng dụng đặc biệt của các phần tiếp theo, vì vậy Ruby và Scheme (ít nhất) có thể làm điều này.

Hệ thống vĩ mô của Lisp được hưởng lợi từ tính đều đặn / đồng âm, nhưng Scala đang có kế hoạch kết hợp chúng như một tính năng ổn định trong 2.12Mẫu Haskell yêu cầu các tính năng tương tự. Tôi tranh luận rằng chúng sẽ phức tạp hơn về mặt cú pháp so với Lisp, nhưng việc tạo mã thời gian biên dịch là không có vấn đề gì.

Tuy nhiên, hãy nghĩ về nó, việc xây dựng các biểu mẫu thẳng chỉ là một loại macro có sẵn trong Lisp: Tôi chưa thấy một trình biên dịch hoặc trình đọc macro tương đương ở bất kỳ nơi nào khác.

Khả năng của một số phương ngữ (ví dụ SBCL ) để lưu một hình ảnh quá trình hoàn chỉnh, có thể tiếp tục là tuyệt vời, nhưng một lần nữa nó không phải là duy nhất: Smalltalk đã làm điều đó trong nhiều thập kỷ.

Nhiều ngôn ngữ khác cho phép hủy bỏ việc gán khi trả về mảng, nhưng cách tiếp cận giá trị # 'và #' nhiều giá trị / ràng buộc / giá trị dường như vẫn đặc trưng cho Common Lisp và Scheme (vẫn có thể phá hủy 'thường xuyên' ). 'Wantarray' của Perl cho phép một hàm xác định xem nó được gọi trong vô hướng, liệt kê hoặc bỏ ngữ cảnh để nó có thể điều chỉnh giá trị trả về của nó theo cách tương tự (-ish), nhưng tôi không thấy nhiều giá trị trả về 'đúng' bên ngoài của Đề án / CL.

Về các tính năng ngôn ngữ, có lẽ không nhiều điều mà Lisp có thể làm mà các ngôn ngữ khác không thể (Turing hoàn toàn là chính nó). Nó những gì , tuy nhiên, là một ngôn ngữ nơi mã được thể hiện về mặt cấu trúc dữ liệu riêng của mình, làm cho Big Idea ™ -đó code được dữ liệu một cái gì đó tương đối dễ dàng để làm việc với.


3
Các macro Scala ít mạnh hơn nhiều so với các macro Lisp, cũng như các macro TH, các macro vệ sinh Scheme, v.v. Một hệ thống mạnh tương đương có thể được tìm thấy trong MetaLua và Converge.
SK-logic

4

Sau nhiều thập kỷ, tôi không nghĩ có gì dành riêng cho Lisp. Nhưng ngay cả ngày nay, có rất nhiều điều thú vị khó tìm thấy bên ngoài Lisps. Một vài điều mà tôi suy nghĩ:

  • Một hệ thống đối tượng chất lượng cao với các giao thức meta tinh vi (ví dụ CLOS) không phổ biến từ xa.
  • đa phương thức bật lên theo thời gian ở đâu đó, nhưng hầu hết mọi người không bao giờ nghe về chúng.
  • Như những người khác đã chỉ ra, hệ thống điều kiện khá tinh vi so với các cơ chế xử lý ngoại lệ phổ biến.
  • Một đại diện nhỏ gọn về ngữ nghĩa của ngôn ngữ (eval), một cách tiếp cận trao quyền để xác định ngôn ngữ của một người và làm cho nó có sẵn để thích ứng sâu (xem SICP ) - các chức năng "eval" của các ngôn ngữ phổ biến hiện tại đơn giản là không chia sẻ cùng một thuộc tính.

Cuối cùng, có rất nhiều thứ để học từ Lisp không phải là về ngôn ngữ mà là một phần của lịch sử Lisp và bị lạc trong thời gian. Ví dụ: Interlisp, Generics Genera, v.v ... nếu bạn không bao giờ đặt tay lên Genera, hãy xem chủ đề comp.lang.lisp này trong đó Kent Pitman mô tả cách "Emacs chỉ là một cái bóng nhợt nhạt của Genera's Zmacs" - tất cả đều được kích hoạt bởi có một hệ thống Lisp mạnh mẽ mà Zmacs là một phần của nó, chạy trên Máy Lisp.


Tôi chưa bao giờ thấy một lời giải thích tốt về đa phương thức phân biệt chúng với các phương thức quá tải , một tính năng tiêu chuẩn trong gần như mọi ngôn ngữ mệnh lệnh hiện đại, ngoại trừ thực tế là công văn đa phương thức được giải quyết một cách linh hoạt trong thời gian chạy và do đó chậm hơn nhiều so với sử dụng các phương thức quá tải, được giải quyết tại thời gian biên dịch.
Mason Wheeler

Họ có sự phân biệt quan trọng. Nếu bạn gặp khó khăn trong việc tìm kiếm tài nguyên về điều đó, bạn luôn có thể tạo một câu hỏi mới tại đây ..
Thiago Silva

Julia có đa hình, và đa hình tham số của Haskell giống như đa hình. Có nhiều cách để mô phỏng đa phương thức trong nhiều ngôn ngữ. Hệ thống điều kiện là thứ tôi thực sự muốn đặc biệt (chỉnh sửa và tiếp tục, mặc dù tôi đã thấy nó cho trình gỡ lỗi C #).
aoeu256

4

Nó không nhất thiết phải là một tính năng nhất định . Đó là toàn bộ giao diện và cách các bộ tính năng nhất định hoạt động cùng nhau.

JavaScript hoặc Java có rất nhiều tính năng của Lisp (máy ảo, trình biên dịch / đánh giá, bộ sưu tập rác, v.v.). Nhưng ví dụ JavaScript thiếu phần lập trình tượng trưng, ​​nó thiếu các khả năng toán học (bên trong nó chỉ có phần nổi), nó thiếu xử lý lỗi, v.v.

Nhiều hệ thống Lisp thông thường được tối ưu hóa cho cách phát triển trong đó một phần mềm mở rộng dần dần, bằng cách mở rộng ngôn ngữ Lisp theo nhiều chiều khác nhau bằng các kỹ thuật lập trình meta khác nhau - mà không cần khởi động lại phần mềm trong một thời gian dài. Do đó, nó cần phải linh hoạt và có thể mở rộng - nhưng đồng thời nó cần phải mạnh mẽ. Thay đổi ngôn ngữ (macro về cơ bản là một cách để người dùng mở rộng trình biên dịch) mà không làm hỏng chương trình.

Bây giờ một cái gì đó như JavaScript cũng được sử dụng để mở rộng một chương trình, điển hình là trình duyệt web. Nhưng hầu hết thời gian người ta không có nhiều lập trình meta trong JavaScript - bên cạnh một số tin tặc OOP .

Thí dụ:

Người ta có thể triển khai một phần mềm toán học tiên tiến chung cho miền đại số máy tính theo hai cách: viết công cụ bằng C với một ngôn ngữ chuyên ngành trên đầu (như Mathicala ) hoặc trong một số phương ngữ Lisp nâng cao hơn. Macsyma / Maxima trong Lisp thông thường, Giảm trong Lisp tiêu chuẩn, Tiên đề trong Lisp chung.

(Cũng có một hoặc nhiều chữ viết bằng Python.)

Không có nhiều hệ thống cung cấp bộ tính năng của Axiom , chạy trên Common Lisp.

Điều khiến Lisp hấp dẫn cho các loại ứng dụng này là sự kết hợp các tính năng: toán học cơ bản nâng cao (bignums, tỷ lệ, ...), tính toán biểu tượng, trình biên dịch tương tác, v.v ... Hoàn toàn có thể có được những điều này bằng cách triển khai chúng ở mức thấp trình độ ngôn ngữ. Bằng cách đó, người ta sẽ thực hiện 50% hoặc nhiều hơn một hệ thống Lisp điển hình.


2

Không xa như tôi biết. Forth dễ dàng năng động như Lisp, có lẽ vì vậy, mã động trong Forth trông giống như mã Forth thông thường trong khi macro Lisp có xu hướng sử dụng các tính năng khác với mã Lisp thông thường (trong Clojure ít nhất tôi chưa bao giờ sử dụng trích dẫn cú pháp bên ngoài macro) và kết quả là chúng trông thực sự khác với mã Lisp thông thường. Như một ví dụ về mức độ năng động của Forth, đây là một cách để triển khai các bình luận trong Forth :

: (   41 word drop ; immediate
( That was the definition for the comment word. )
( Now we can add comments to what we are doing! )

1
Vui như Forth dường như, tôi luôn thấy nó vô vọng và khó xử, có lẽ vì nó dựa trên stack và mọi thứ đều đảo ngược.
Robert Harvey

2
Vì tò mò, ý của bạn là 'tách biệt khỏi phần chính của ngôn ngữ' là gì? Các macro trong Lisp có quyền truy cập đầy đủ vào tất cả các chức năng được xác định tại điểm mà macro được xác định, bất kỳ chức năng nào có thể được sử dụng để xây dựng biểu mẫu mà macro mở rộng. Điều này có thể liên quan đến thông tin được lấy từ cơ sở dữ liệu và / hoặc máy chủ. Ví dụ nhận xét của bạn, có thể được định nghĩa là: (bình luận defmacro (& phần còn lại)), phải không?
Daniel Woods

1
@DannyWoods Ý tôi là macro không giống như mã thông thường. Ít nhất là trong clojure, bạn có thể nói mã macro từ mã thông thường bởi vì nó sử dụng rất nhiều trích dẫn cú pháp, ghép nối unquote, v.v ... điều không bình thường trong mã thông thường. Ví dụ về mã tôi đã đưa ra trông giống như mã bình thường cho đến khi bạn thấy ngay lập tức. Đọc lại câu trả lời của tôi, nó chỉ được thể hiện kém.
ném đá

1
@stonemetal Không phải lo lắng, nhưng đáng chú ý là không có gì cụ thể về vĩ mô về trích dẫn cú pháp, trong Common Lisp hoặc Clojure. Đôi khi thật tiện lợi khi có các biểu thức backtick trong các định nghĩa hàm thông thường và các phần thân macro có thể được xây dựng thủ công với các danh sách đơn giản (mặc dù bạn chỉ phải thực hiện điều này một hoặc hai lần để quyết định rằng trích dẫn cú pháp là một điều tốt!)
Danny Woods

1
Để công bằng, điều tương tự có thể được thực hiện trong Lisp, bằng cách đăng ký một macro người đọc tùy chỉnh.
fjarri

2

Lisp có nhiều phương ngữ, và mỗi phương ngữ đều có bộ tính năng riêng. Tính năng yêu thích của tôi không có khả năng được chấp nhận bởi bất kỳ ngôn ngữ nào khác là "ngăn xếp mì spaghetti" từ Interlisp .

Các spaghetti stack giống như một đóng cửa, nhưng trên steroid. Nó không chỉ lưu chức năng hiện tại, mà toàn bộ bối cảnh lên đến đỉnh của ngăn xếp. Một cái gì đó giống như một thói quen chung , ngoại trừ việc bạn có thể tạo ra chúng một cách tùy tiện, dẫn đến một hệ thống phân cấp các bối cảnh ngăn xếp.


Không biết điều đó, sẽ kiểm tra xem, cảm ơn vì câu trả lời của bạn :)
iceX

7
Đây có giống như các phần tiếp theo của Đề án không?
Nicola Musatti

1
@NicolaMusatti, một "spaghetti stack" là một chiến lược triển khai phổ biến cho các phần tiếp theo giống như Đề án (có thể được gọi sau khi hàm tạo ra chúng đã trở lại).
Alex D
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.