Scheme vs Common Lisp: Những đặc điểm nào tạo nên sự khác biệt trong dự án của bạn? [đóng cửa]


155

Không thiếu những câu hỏi "Scheme vs Common Lisp" mơ hồ trên cả StackOverflow và trên trang web này, vì vậy tôi muốn làm cho câu hỏi này tập trung hơn. Câu hỏi dành cho những người đã mã hóa bằng cả hai ngôn ngữ:

Trong khi mã hóa trong Scheme, bạn đã bỏ lỡ những yếu tố cụ thể nào trong trải nghiệm mã hóa Common Lisp của bạn? Hoặc, ngược lại, trong khi mã hóa trong Common Lisp, bạn đã bỏ lỡ điều gì từ mã hóa trong Scheme?

Tôi không nhất thiết chỉ là các tính năng ngôn ngữ. Sau đây là tất cả những điều hợp lệ để bỏ lỡ, liên quan đến câu hỏi:

  • Thư viện cụ thể.
  • Các tính năng cụ thể của các môi trường phát triển như SLIME, DrRacket, v.v.
  • Các tính năng của việc triển khai cụ thể, như khả năng của Gambit để viết các khối mã C trực tiếp vào nguồn Scheme của bạn.
  • Và tất nhiên, tính năng ngôn ngữ.

Ví dụ về loại câu trả lời tôi hy vọng:

  • "Tôi đã cố gắng thực hiện X trong Common Lisp, và nếu tôi có các phần tiếp theo hạng nhất của Scheme, tôi hoàn toàn sẽ làm Y, nhưng thay vào đó tôi phải làm Z, điều đó còn đau hơn."
  • "Viết kịch bản quá trình xây dựng trong dự án Scheme của tôi ngày càng đau đớn khi cây nguồn của tôi phát triển và tôi liên kết với ngày càng nhiều thư viện C. Đối với dự án tiếp theo của tôi, tôi đã quay trở lại Common Lisp."
  • "Tôi có một cơ sở mã C ++ lớn hiện có và đối với tôi, việc có thể nhúng các cuộc gọi C ++ trực tiếp vào mã Đề án Gambit của tôi hoàn toàn xứng đáng với bất kỳ thiếu sót nào mà Scheme có thể gặp phải so với Common Lisp, thậm chí bao gồm thiếu hỗ trợ SWIG."

Vì vậy, tôi hy vọng vào những câu chuyện chiến tranh, thay vì những tình cảm chung chung như "Lược đồ là một ngôn ngữ đơn giản hơn", v.v.


25
Một câu hỏi tuyệt vời, từ ngữ tốt. Tôi tò mò về điều này bản thân mình; hy vọng có một số người có chuyên môn về cả hai ngôn ngữ sẵn sàng cung cấp một số hiểu biết.
Robert Harvey

1
@Josh K - nó rõ ràng có thể trả lời được, nhưng không nhất thiết phải có một câu trả lời dứt khoát. Ngoại trừ việc tôi cá là sẽ có một vì ai đó sẽ đưa ra một câu trả lời tuyệt vời đến nỗi mọi người đều giống như whoa!
glenatron

4
@Josh: Có lẽ bạn không quen thuộc với Scheme và Common Lisp. Cả hai ngôn ngữ đều rất mạnh theo quyền riêng của họ, nhưng không có sự chấp nhận chính thống. Tại sao lại thế này? Nó có thể là do có rất nhiều phương ngữ; Bạn chọn cái nào? Một so sánh về loại này có thể rất rõ ràng và OP đã cẩn thận đặt câu hỏi để giới hạn phạm vi cho các câu trả lời, theo quan điểm của tôi, rất cụ thể và có thể trả lời được.
Robert Harvey

13
Các bạn, đừng đóng câu hỏi chỉ vì bạn không thích nó hoặc không thể liên quan đến nó. Đây rõ ràng là một câu hỏi "thực sự"; nếu bạn không thể tìm thấy lý do tốt hơn để đóng nó, bạn không nên bỏ phiếu để đóng.
Robert Harvey

4
Bạn có thể gửi email cho Richard Stallman cho câu trả lời của mình.
wassimans

Câu trả lời:


100

Bằng đại học của tôi là về Khoa học nhận thức và Trí tuệ nhân tạo. Từ đó tôi đã có một đoạn giới thiệu một khóa học về Lisp. Tôi nghĩ rằng ngôn ngữ này rất thú vị (như "thanh lịch") nhưng thực sự không nghĩ nhiều về nó cho đến khi tôi bắt gặp Quy tắc thứ mười của Greensasta sau đó:

Bất kỳ chương trình C hoặc Fortran nào đủ phức tạp đều chứa một chương trình đặc biệt, được chỉ định không chính thức, có lỗi, triển khai chậm một nửa Common Lisp.

Quan điểm của Greensasta là (một phần) rằng nhiều chương trình phức tạp có trình thông dịch tích hợp. Thay vì xây dựng một trình thông dịch thành ngôn ngữ, ông cho rằng việc sử dụng một ngôn ngữ như Lisp đã có sẵn một trình thông dịch (hoặc trình biên dịch) có ý nghĩa hơn.

Lúc đó tôi đang làm việc trên một ứng dụng khá lớn thực hiện các tính toán do người dùng xác định bằng trình thông dịch tùy chỉnh cho ngôn ngữ tùy chỉnh. Tôi quyết định thử viết lại cốt lõi của nó trong Lisp như một thử nghiệm quy mô lớn.

Mất khoảng sáu tuần. Mã ban đầu là ~ 100.000 dòng Delphi (một biến thể Pascal). Trong Lisp đã giảm xuống ~ 10.000 dòng. Tuy nhiên, điều đáng ngạc nhiên hơn nữa là thực tế là động cơ Lisp nhanh hơn 3-6 lần. Và hãy nhớ rằng đây là công việc của một tân sinh viên Lisp! Đó là toàn bộ trải nghiệm đối với tôi; lần đầu tiên tôi thấy khả năng kết hợp hiệu suất và biểu cảm trong một ngôn ngữ duy nhất.

Một thời gian sau khi tôi bắt đầu làm việc với một dự án dựa trên web, tôi đã thử giọng một số ngôn ngữ. Tôi đã bao gồm Lisp và Scheme trong hỗn hợp. Cuối cùng, tôi đã chọn một triển khai Đề án-- Lược đồ Chez . Tôi đã rất hài lòng với kết quả.

Dự án dựa trên web là một "công cụ lựa chọn" hiệu suất cao . Chúng tôi sử dụng Lược đồ theo một số cách khác nhau, từ xử lý dữ liệu đến truy vấn dữ liệu để tạo trang. Ở nhiều điểm, chúng tôi thực sự bắt đầu với một ngôn ngữ khác nhưng cuối cùng lại chuyển sang Scheme vì những lý do tôi sẽ mô tả ngắn gọn dưới đây.

Bây giờ tôi có thể trả lời câu hỏi của bạn (ít nhất là một phần).

Trong buổi thử giọng, chúng tôi đã xem xét một loạt các triển khai Lisp và Scheme. Về phía Lisp, chúng tôi đã xem xét (tôi tin) Allegro CL, CMUCL, SBCL và LispWorks. Về phía Scheme, chúng tôi đã xem xét (tôi tin) Bigloo, Chicken, Chez, Gambit. (Việc lựa chọn ngôn ngữ đã có từ lâu; đó là lý do tại sao tôi hơi mơ hồ. Tôi có thể khai thác một số ghi chú nếu nó quan trọng.)

Ngay lập tức chúng tôi đang tìm kiếm một) chủ đề gốc và b) Hỗ trợ Linux, Mac và Windows. Hai điều kiện đó kết hợp đã đánh gục tất cả mọi người nhưng (tôi nghĩ) Allegro và Chez - vì vậy để tiếp tục đánh giá, chúng tôi phải nới lỏng yêu cầu đa luồng.

Chúng tôi tập hợp một bộ các chương trình nhỏ và sử dụng chúng để đánh giá và thử nghiệm. Điều đó tiết lộ một số vấn đề. Ví dụ: một số triển khai có các khiếm khuyết ngăn một số thử nghiệm chạy đến hoàn thành; một số triển khai không thể biên dịch mã vào thời gian chạy; một số triển khai không thể dễ dàng tích hợp mã được biên dịch theo thời gian chạy với mã được biên dịch trước; một số triển khai có người thu gom rác rõ ràng tốt hơn (hoặc rõ ràng tệ hơn) so với những người khác; Vân vân.

Đối với nhu cầu của chúng tôi, chỉ có ba triển khai thương mại - Allegro, Chez và Lispworks - đã vượt qua các thử nghiệm chính của chúng tôi. Trong ba người duy nhất, Chez đã vượt qua tất cả các bài kiểm tra với màu sắc bay. Vào thời điểm đó, tôi nghĩ Lispworks không có chủ đề gốc trên bất kỳ nền tảng nào (tôi nghĩ họ làm bây giờ) và tôi nghĩ Allegro chỉ có chủ đề gốc trên một số nền tảng. Hơn nữa, Allegro có phí cấp phép thời gian "gọi cho chúng tôi" mà tôi không thích lắm. Tôi tin rằng Lispworks không có phí thời gian chạy và Chez có sự sắp xếp đơn giản (và rất hợp lý) (và nó chỉ khởi động nếu bạn sử dụng trình biên dịch vào thời gian chạy).

Đã tạo ra một số đoạn mã đáng kể trong cả Lisp và Scheme, đây là một số điểm so sánh và tương phản:

  • Môi trường Lisp trưởng thành hơn rất nhiều. Bạn nhận được rất nhiều bang cho buck. (Đã nói rằng, nhiều mã hơn cũng tương đương với nhiều lỗi hơn.)

  • Môi trường Lisp khó học hơn rất nhiều. Bạn cần nhiều thời gian hơn để thành thạo; Lisp thông thường là một ngôn ngữ lớn - và đó là trước khi bạn đến các thư viện mà các triển khai thương mại thêm vào đầu nó. (Đã nói rằng, trường hợp cú pháp của Scheme tinh tế và phức tạp hơn nhiều so với bất kỳ điều gì trong Lisp.)

  • Môi trường Lisp có thể khó tạo ra nhị phân hơn. Bạn cần "lắc" hình ảnh của mình để loại bỏ các bit không cần thiết và nếu bạn không thực hiện chương trình của mình một cách chính xác trong quá trình đó, bạn có thể gặp phải lỗi thời gian chạy sau này . Ngược lại, với Chez, chúng tôi biên dịch một tệp cấp cao nhất bao gồm tất cả các tệp khác mà nó cần và chúng tôi đã hoàn tất.

Tôi đã nói trước đó rằng chúng tôi đã kết thúc việc sử dụng Scheme ở một số nơi mà ban đầu chúng tôi không có ý định. Tại sao? Tôi có thể nghĩ ra ba lý do ngoài đỉnh đầu.

Đầu tiên, chúng tôi đã học cách tin tưởng vào Chez (và nhà phát triển của nó, Cadence). Chúng tôi đã hỏi rất nhiều từ công cụ này và nó luôn được chuyển giao. Ví dụ, trong lịch sử, Chez có một số lượng nhỏ các khiếm khuyết nhỏ và trình quản lý bộ nhớ của nó rất, rất tốt.

Thứ hai, chúng tôi đã học cách yêu thích màn trình diễn mà chúng tôi có được từ Chez. Chúng tôi đã sử dụng thứ gì đó giống như ngôn ngữ kịch bản - và chúng tôi đã nhận được tốc độ mã gốc từ nó. Đối với một số điều không quan trọng - nhưng nó không bao giờ bị tổn thương, và đôi khi nó giúp ích rất nhiều.

Thứ ba, chúng tôi đã học cách yêu thích Đề án trừu tượng có thể cung cấp. Nhân tiện, tôi không chỉ có nghĩa là macro; Ý tôi là những thứ như đóng cửa, lambdas, gọi đuôi, v.v ... Một khi bạn bắt đầu nghĩ theo những thuật ngữ đó, các ngôn ngữ khác có vẻ khá hạn chế khi so sánh.

Đề án có hoàn hảo không? Không; đó là một sự đánh đổi. Đầu tiên, nó cho phép các nhà phát triển riêng lẻ hoạt động hiệu quả hơn - nhưng các nhà phát triển khó khăn hơn trong việc tìm kiếm mã của nhau vì các biển chỉ dẫn mà hầu hết các ngôn ngữ có (ví dụ: đối với các vòng lặp) đều bị thiếu trong Đề án (ví dụ: có hàng triệu cách để làm một vòng lặp for). Thứ hai, có một nhóm các nhà phát triển nhỏ hơn nhiều để nói chuyện, thuê, mượn, v.v.

Tóm lại, tôi nghĩ tôi muốn nói: Lisp và Scheme cung cấp một số khả năng không có sẵn ở bất kỳ nơi nào khác. Khả năng đó là một sự đánh đổi, vì vậy tốt hơn hết là nên có ý nghĩa trong trường hợp cụ thể của bạn. Trong trường hợp của chúng tôi, các yếu tố quyết định giữa việc đi với Lisp hay Scheme có liên quan nhiều hơn đến các tính năng rất cơ bản (hỗ trợ nền tảng, luồng nền tảng, biên dịch thời gian chạy, cấp phép thời gian chạy) so với các tính năng ngôn ngữ hoặc thư viện. Một lần nữa, trong trường hợp của chúng tôi cũng là một sự đánh đổi: với Chez chúng tôi có các tính năng cốt lõi mà chúng tôi muốn nhưng chúng tôi đã mất các thư viện rộng lớn mà môi trường Lisp thương mại có.

Ngoài ra, chỉ để nhắc lại: chúng tôi đã xem xét các Lisps và Đề án khác nhau từ lâu; tất cả họ đã phát triển và cải thiện kể từ đó.


1
Ồ, đó hẳn là một mã Delphi thực sự khủng khiếp nếu bằng cách nào đó nó có thể thực hiện chậm hơn 3-6 lần so với triển khai Lisp! :(
Mason Wheeler

2
+1: Điều thú vị nhất về bài đăng này là việc bạn đã chuyển từ Lisp sang Scheme sau khi hoàn thành một dự án lớn ở Lisp. (Hoặc có lẽ tôi vừa mới ẩn mình trên comp.lang.lisp quá lâu.)
Larry Coleman

25
"Wow, đó hẳn là một mã Delphi thực sự khủng khiếp nếu bằng cách nào đó nó có thể thực hiện chậm hơn 3-6 lần so với triển khai Lisp!" Phải, tôi sẽ coi đó là thất bại của tôi vì đã không giải thích nó tốt hơn. Việc triển khai Lisp có thể chuyển đổi các biểu thức người dùng thành các biểu thức Lisp - một quy trình dễ dàng tầm thường - và sau đó biên dịch các biểu thức Lisp thành mã gốc (với tối ưu hóa hoàn toàn). Đó là ý nghĩa của Quy tắc thứ mười của Greensasta.
Michael Lenaghan

1
Câu trả lời tuyệt vời! Tôi sẽ chọn nó, ít nhất là cho đến khi một cái tốt hơn xuất hiện :) Một câu hỏi: bạn nói rằng bạn đã đưa ra quyết định đi với Chez Scheme dựa trên trạng thái của lĩnh vực "một thời gian dài trước đây". Bạn có thể chỉ định một năm?
SuperElectric

11
Điểm đó, việc triển khai LISP là miễn phí để biên dịch một cái gì đó thành mã máy, thay vì dựa vào một trình thông dịch, là tinh tế và khá hữu ích. Cuốn sách "Let Over Lambda" chỉ ra đây chính xác là lý do tại sao gói regrec LISP chung di động, nhân bản cú pháp regrec PERL, vượt trội hơn PERL bởi một yếu tố quan trọng. PERL, ở phía bên, có một trình thông dịch regrec. Gói LISP chung biên dịch biểu thức chính quy thành mã.
John R. Strohm

37

Tôi thường không thích dán một liên kết như một câu trả lời, nhưng tôi đã viết một bài viết trên blog về chính điều này. Nó không đầy đủ, nhưng nó có được một số điểm chính thông qua.

http://symbo1ics.com/blog/?p=729

Chỉnh sửa : Dưới đây là các điểm nguyên tắc:

  1. TỒN TẠI : Cả lisps đưa ra sau khi một loạt các lisps khác. Sơ đồ lấy con đường tối thiểu, tiên đề. CL đi theo con đường baroque.
  2. TRƯỜNG HỢP : Điển hình là Đề án phân biệt chữ hoa chữ thường. CL không phải (mặc dù nó có thể). Điều này đôi khi bị bỏ lỡ, nhưng tính thực tế của nó được tranh luận (bởi tôi).
  3. TÊN : Tên của các biểu tượng trong CL rất nhiều lần lẻ và khó hiểu. TERPRI, PROGNvv Sơ đồ thường có tên rất hợp lý. Đây là một cái gì đó bị bỏ lỡ trong CL.
  4. CHỨC NĂNG : CL có một không gian tên hàm riêng biệt. Điều này không bị bỏ lỡ trong Đề án. Có một không gian tên duy nhất thường cho phép lập trình chức năng rất sạch sẽ, điều này thường khó hoặc khó xử trong CL. Nhưng nó có chi phí --- đôi khi bạn phải làm xáo trộn những cái tên như " list" đến " lst" trong Đề án.
  5. MACROS : Tôi nhớ các macro bẩn cấp thấp nhất trong Scheme. Vâng, syntax-rulestất cả đều ổn và bảnh bao cho đến khi bạn muốn thực sự hack một số thứ. Mặt khác, các macro vệ sinh đôi khi bị bỏ sót trong CL. Không có cách tiêu chuẩn để làm chúng có nghĩa là phát minh lại bánh xe.
  6. PORTABILITY : Thường thì CL dễ mang theo hơn, mặc dù cả hai ngôn ngữ đều được chuẩn hóa. CL lớn hơn và do đó có nhiều tính năng tiêu chuẩn hơn để sử dụng mà không cần thư viện bên ngoài. Nó cũng có nghĩa là nhiều thứ phụ thuộc vào việc thực hiện có thể được thực hiện một cách hợp lý. Ngoài ra, Scheme bị ảnh hưởng bởi việc thực hiện nghìn tỷ, hầu hết trong số đó là không tương thích. Điều này làm cho CL rất mong muốn.
  7. LIBRARIES : Rất liên quan đến điểm cuối cùng của tôi. Đề án có SRFI nhưng không được thừa nhận toàn cầu. Không có cách di động để làm việc với các thư viện. CL mặt khác có cách. Và Quicklisp là một món quà từ thượng đế (Xach) --- một loại kho thư viện để sử dụng.
  8. THỰC HIỆN : Đề án phải chịu quá nhiều triển khai. Không có thực hiện kinh điển thực sự. Mặt khác, CL có một số triển khai sử dụng cụ thể hoặc hiệu suất cao rất tốt (hiệu suất cao: SBCL, thương mại: Allegro, nhúng: ECL, xách tay: CLISP, Java: ABCL, ...).

Mặc dù tôi chỉ nói chuyện ở người đầu tiên một chút ở trên, nhưng rõ ràng những gì tôi bỏ lỡ và những gì tôi không.

[Tôi xin lỗi nếu những điều này quá chung chung. Có vẻ như bạn có thể muốn nhiều chi tiết cụ thể hơn. Có một số chi tiết cụ thể trong bài viết.]


Điều gì về một bản tóm tắt ngắn gọn (thực sự)? ^^
Dave O.

2
Hãy nội tuyến những điểm nổi bật. Câu trả lời nên tự đứng.

1
@Dave O. và @ Thorbjørn Ravn Andersen: Đã thêm một bản tóm tắt theo yêu cầu. Cảm ơn.
Quadreshood

2
"Con đường baroque"! Thật là một cách tuyệt vời để đặt nó.
Đánh dấu C

Lisp thông thường phân biệt chữ hoa chữ thường, nhưng chuyển đổi đầu vào của nó thành chữ hoa trước khi đánh giá nó. Bạn có thể nhận được chữ cái viết thường trong các ký hiệu bằng cách trích dẫn chúng. Vấn đề tên là vì Scheme đã loại bỏ những tên cũ xấu và CL thì không.
David Thornley

25

Gần đây tôi đã bắt đầu một dự án gia đình bằng cách sử dụng một thư viện có phiên bản C và phiên bản Java. Tôi muốn sử dụng Lisp cho dự án và tôi đã dành khoảng một tháng để bỏ trống giữa việc sử dụng Common Lisp, Scheme hoặc Clojure. Tôi có một số kinh nghiệm với cả ba, nhưng chỉ có các dự án đồ chơi. Tôi sẽ kể cho bạn nghe một chút về trải nghiệm của tôi với từng người trong số họ trước khi cho bạn biết tôi đã chọn cái nào.

Vợt PLT có một IDE đẹp không chỉ cho phép bạn đánh giá các biểu thức từ trình chỉnh sửa mà còn cho phép bạn nhập dấu ngoặc thay vì parens, chuyển chúng trở lại parens khi thích hợp. Vợt cũng có một bộ thư viện lớn với cài đặt và thậm chí còn có sẵn để tải xuống. Trình gỡ lỗi trực quan cũng hữu ích.

Việc triển khai Lisp chung của tôi (SBCL) không có IDE, nhưng theo thông lệ với các triển khai CL nguồn mở để sử dụng Emacs và SLIME. Sự kết hợp này có thể rất hiệu quả. Cùng với khả năng đánh giá biểu thức khi bạn nhập chúng vào tệp nguồn, còn có REPL có tất cả các lệnh chỉnh sửa của emacs, do đó, sao chép mã có thể thực hiện hiệu quả cả hai cách. Ngay cả các đối tượng được hiển thị trong bộ đệm REPL cũng có thể được sao chép và dán. Alt+(Alt+)có hiệu quả để xử lý các dấu ngoặc đơn và thụt lề phù hợp.

Tất cả các tính năng Emacs ở trên cũng có sẵn cho Clojure. Trải nghiệm chỉnh sửa của tôi với Clojure tương tự như của Lisp. Giao diện Java hoạt động tốt và tôi muốn thực hiện một dự án Clojure khi nó đáo hạn.

Tôi đã có thể truy cập vào thư viện bằng cách sử dụng cả ba (Common Lisp, Vợt và Clojure), nhưng cuối cùng tôi đã chọn Common Lisp cho dự án. Yếu tố quyết định là FFI dễ sử dụng hơn trong Common Lisp. CFFI có một hướng dẫn rất tốt với mã ví dụ và giải thích chi tiết về từng phương pháp. Tôi đã có thể bọc 20 chức năng C vào một buổi chiều và từ đó không phải chạm vào mã.

Yếu tố khác là tôi quen thuộc với Lisp thông thường hơn với Đề án Clojure hoặc R6RS. Tôi đã đọc hầu hết các cuốn sách của Lisp và Graham thực tế, và tôi cảm thấy thoải mái với Hyperspec. Đây chưa phải là mã "lispy", nhưng tôi chắc chắn điều đó sẽ thay đổi khi tôi có thêm kinh nghiệm.


Cảm ơn các chi tiết! Tôi có hiểu chính xác bạn rằng bạn nghĩ rằng FFI của SBCL dễ sử dụng hơn Clojure không? Nếu vậy, tôi sẽ khá ngạc nhiên về điều đó, vì bạn chỉ có thể gọi các phương thức Java trực tiếp từ Clojure mà không cần phải bọc chúng. (Hay bạn cũng cần gọi mã riêng?)
SuperElectric

6
@SuperElectric: Gọi các phương thức Java "tích hợp" từ Clojure là chuyện nhỏ; gọi các phương thức Java trong thư viện đã tải xuống: không quá nhiều. Tôi thực sự đã dành nhiều thời gian hơn để có được đường dẫn lớp và nhập các dòng đúng hơn so với việc tôi có được phương thức C đầu tiên làm việc từ SBCL với CFFI. Nhưng tôi không phải là chuyên gia Java, vì vậy Mileage của bạn có thể thay đổi.
Larry Coleman

21

Tôi lập trình trong cả CL và Vợt.

Hiện tôi đang phát triển một trang web tại Common Lisp và tôi đã viết một bộ các chương trình nội bộ cho chủ nhân trước đây của tôi trong Vợt.

Đối với mã nội bộ, tôi đã chọn Vợt (khi đó được gọi là PLT Scheme) vì nhà tuyển dụng là một cửa hàng Windows và tôi không thể bắt họ trả tiền cho LispWorks. Việc triển khai CL nguồn mở tốt duy nhất cho Windows là (và vẫn là) CCL, yêu cầu hỗ trợ SSE trong bộ xử lý. Chủ nhân, giá rẻ, đang sử dụng phần cứng thời đồ đá. Ngay cả khi nhà tuyển dụng có phần cứng tốt, thư viện GUI duy nhất có hậu quả trong Common Lisp là McCLIM, chỉ hoạt động trên Unix. Vợt có một thư viện GUI tốt hoạt động trên cả Unix và Windows, điều này rất quan trọng cho sự thành công của dự án của tôi.

Tôi đã dành hơn một năm để đưa ra trình soạn thảo DrRacket nguyên thủy. EMACS không thể biến phiên bản GUI của Vợt, sau đó được gọi là MrEd, thành một thứ không thể thiếu trên Windows. Tôi phải làm mà không thể đánh giá biểu thức ở con trỏ bằng một lần nhấn phím. Thay vào đó, tôi phải chọn thủ công biểu thức S, sao chép nó, nhấp vào cửa sổ REPL (vì không có tổ hợp phím để chuyển sang biểu thức S), sau đó dán biểu thức S. Tôi cũng phải làm mà không có trình soạn thảo có thể chỉ cho tôi các đối số dự kiến ​​của hàm hoặc macro tôi đang sử dụng. DrRacket không thay thế cho SLIME.

Nhà tuyển dụng đã sử dụng cơ sở dữ liệu độc quyền với API XML phức tạp, yêu cầu vô số thông tin dường như không cần thiết để có thể trả lời phiên bản truy vấn CHỌN của nó. Tôi đã quyết định sử dụng cả HTMLPrag để phát ra XML cho API này và phân tích các câu trả lời. Nó đã làm việc tuyệt vời.

Tôi đã phải tìm hiểu hệ thống macro "trường hợp cú pháp" quá phức tạp của vợt để viết một macro cho phép tôi tương tác với API XML quá phức tạp bằng cách nhập các biểu mẫu trông giống như SQL. Phần này sẽ dễ dàng hơn nhiều nếu tôi có DEFMACRO theo ý của tôi. Tuy nhiên, kết quả cuối cùng vẫn liền mạch mặc dù phải mất nhiều nỗ lực hơn để đạt được.

Hơn nữa, tôi phải làm mà không có macro LOOP của Common Lisp. Vợt bắt đầu cung cấp một giải pháp thay thế chỉ sau khi tôi đã viết hầu hết mã, và giải pháp thay thế vẫn còn tệ so với LOOP (mặc dù nhóm phát triển của vợt khẳng định điều đó tốt hơn-- đơn giản là họ đã sai). Cuối cùng tôi đã viết rất nhiều mẫu LET có tên đã sử dụng "xe hơi" và "cdr" để lặp lại các danh sách.

Nói về xe hơi và cdr, không có gì khó chịu hơn cách giải thích của Scheme về (xe '()) là một lỗi. Tôi đã tận dụng độ nhạy trường hợp của vợt và triển khai CAR và CDR, có ngữ nghĩa chung của Lisp. Tuy nhiên, việc tách '() và #f làm cho việc trả về' () làm giá trị mặc định trở nên ít hữu ích hơn nhiều.

Cuối cùng tôi cũng đã thực hiện lại UNWIND-PROTECT, và đã phát minh ra hệ thống khởi động lại của riêng tôi để lấp đầy khoảng trống mà Vợt để lại. Cộng đồng vợt cần biết rằng khởi động lại rất hữu ích và dễ thực hiện.

Hình thức cho phép giá trị của vợt quá dài, vì vậy tôi đã triển khai NHIỀU-GIÁ TRỊ-BIND. Điều này là hoàn toàn cần thiết, bởi vì Vợt yêu cầu bạn phải nhận tất cả các giá trị được tạo, cho dù bạn có sử dụng chúng hay không.

Sau đó, tôi đã cố gắng viết một ứng dụng API XML của eBay trong Common Lisp, chỉ để thấy rằng nó không có bất cứ thứ gì như HTMLPrag. HTMLPrag rất hữu ích. Tôi đã kết thúc việc thực hiện dự án đó trong vợt. Tôi đã thử nghiệm với các cơ sở Lập trình Văn học của Rquet, chỉ để phát hiện ra rằng tôi là lập trình viên duy nhất trên Trái đất tìm thấy mã chữ viết đúng được viết khó hơn so với mã thông thường hoặc viết mã "nhận xét quá mức" không đúng cách.

Dự án mới của tôi đang được thực hiện ở Common Lisp, đó là lựa chọn đúng đắn vì cộng đồng Vợt chỉ không tin vào sự song song, điều cần thiết cho dự án này. Điều duy nhất tôi nghĩ rằng tôi có thể đã bỏ lỡ từ Vợt là sự tiếp tục. Tuy nhiên, tôi đã có thể làm những gì tôi cần bằng cách sử dụng khởi động lại, và, khi nhìn lại, có lẽ có thể đã thực hiện nó với một đóng cửa đơn giản.


2
Tôi đã không thử nó, nhưng tôi đã thấy các bài đăng trên blog từ những người sử dụng chương trình vợt dòng lệnh với Emacs. Ví dụ: bc.tech.coop/scheme/scheme-emacs.htm
Larry Coleman

5
Nói một cách công bằng, có vẻ như bạn đã đến Scheme muốn viết CL thay vì cố gắng tiếp cận mọi thứ từ một Đề án POV thành ngữ. Ví dụ, chương trình không khuyến khích tái diễn hơn là sử dụng các vòng lặp?
Sled

@ArtB Scheme không chỉ khuyến khích đệ quy, nó đòi hỏi nó, vì vậy tất nhiên dự án được đề cập ở trên đã sử dụng rất nhiều đệ quy. Và điều đó chỉ phục vụ để thêm sự lặp lại ( ví dụ, bạn phải bao gồm một bản sao của cuộc gọi đệ quy trong mỗi nhánh của condbiểu mẫu) và các lỗi (tôi đã viết bài kiểm tra chấm dứt vòng lặp đúng chưa?) Ngay cả hôm nay, tôi có ấn tượng vợt đó chủ yếu dành cho sinh viên và không phải lập trình viên chuyên nghiệp. Mỗi lần tôi nghe ai đó ngoài tôi sử dụng nó, họ đang sử dụng ngôn ngữ con "Học sinh mới bắt đầu" và nó dành cho một lớp học.
Vứt bỏ tài khoản

Nếu bạn đang lặp lại mã trên COND, bạn có nói rằng bạn chỉ cần một chức năng khác?
Sled

@ArtB Một hàm để gọi hàm lặp với các đối số khác nhau? Đó sẽ là vô nghĩa. Bạn thấy kiểu lặp lại đó chỉ trong mã Scheme của bất kỳ ai. Thậm chí có những ví dụ trong mã nguồn riêng của vợt.
Vứt bỏ tài khoản

5

Đề án được thiết kế với một phần tổng hợp riêng trong tâm trí. Do đó, sức mạnh của các macro của nó thường bị hạn chế nghiêm trọng, ngay cả với các phần mở rộng cho phép defmacro kiểu Lisp thông thường thay vì hệ thống macro kém, hạn chế vệ sinh. Không phải lúc nào cũng có thể định nghĩa một macro xác định một macro khác, nhằm mục đích sử dụng ngay lập tức trong một dòng mã tiếp theo. Và khả năng như vậy là rất cần thiết để thực hiện các trình biên dịch eDSL hiệu quả.

Không cần phải đề cập rằng việc triển khai Đề án chỉ với các macro vệ sinh R5RS hầu như không hữu ích đối với tôi, vì phong cách lập trình siêu dữ liệu của tôi không thể được dịch đầy đủ sang vệ sinh.

May mắn thay, có những triển khai Scheme (ví dụ: Vợt) không có giới hạn đó.


1
Xin chào, tôi mới bắt đầu bị ướt chân với Scheme gần đây bằng cách sử dụng vợt. Bạn có phiền khi cung cấp một ví dụ nhanh về việc sử dụng các macro không hợp vệ sinh trong Vợt không? Loại macro có sẵn có vẻ như là một trong những điểm được tranh luận sôi nổi nhất giữa CL và Scheme.
cam80

@ cam80, một cách tiếp cận là sử dụng docs.racket-lang.org/mzlib/mzlib_defmacro.html Và, tất nhiên, trong chế độ R6RS có một cách ít hạn chế hơn.
SK-logic

@ SK-logic, bạn đang làm gì với các macro không phổ biến?
Sled

1
@ArtB, tôi đang triển khai các eDSL dưới dạng các hàm biên dịch có thể làm khá nhiều với AST nguồn của chúng. Vệ sinh là một sự phiền toái hoàn toàn trong cách tiếp cận như vậy. Bạn có thể xem cách nó hoạt động: github.com/combinatorylogic/mbase
SK-logic
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.