2012-03-02 21 views
22

Ba ngôn ngữ homoiconic lispy, Dylan, JuliaSeph tất cả di chuyển ra khỏi ngoặc hàng đầu - do đó, một chức năng cuộc gọi giả thuyết trong Common Lisp đó sẽ trông giống như:Clojure sẽ mất gì khi chuyển từ dấu ngoặc đơn hàng đầu như Dylan, Julia và Seph?

(print hello world) 

sẽ trông giống như gọi hàm giả sau

print(hello world) 

bằng ba ngôn ngữ được đề cập ở trên.

Được Clojure đi xuống con đường này - những gì nó sẽ phải hy sinh để đạt được điều đó?

Lý do: Ngoài cấu trúc dữ liệu chức năng lười biếng tuyệt vời trong Clojure và cú pháp cải tiến cho bản đồ và seq, hỗ trợ ngôn ngữ cho đồng thời, nền tảng JVM, công cụ và cộng đồng tuyệt vời - điều đặc biệt về nó 'LISP' là dấu ngoặc đơn hàng đầu cho tính đồng nhất cung cấp cho các macro cung cấp cú pháp trừu tượng.

Nhưng nếu bạn không cần dấu ngoặc đơn hàng đầu - tại sao lại có dấu ngoặc đơn? Những lập luận duy nhất tôi có thể nghĩ đến để giữ cho chúng được

(1) tái sử dụng công cụ hỗ trợ trong emacs

(2) khiến mọi người 'nghĩ trong LISP' và không cố gắng và coi nó như là một ngôn ngữ thủ tục)

+6

Một phần quan trọng của thẩm mỹ lisp là parseability tầm thường và khả năng sử dụng như dữ liệu của mã; bạn sẽ mất một số điều đó. – zmccord

+0

Ứng dụng chức năng chỉ là một trong nhiều hình thức có thể. Bạn đang đề xuất để đối xử với họ khác nhau? Clojure đã làm một điều khủng khiếp, bãi bỏ các tế bào khuyết điểm. Đi xa hơn sẽ hoàn toàn làm hỏng ngôn ngữ. –

+3

Xem thêm http://stackoverflow.com/questions/643892/fixing-lisp-syntax. Câu hỏi này nhắc tôi về một nhà phát triển Pascal mà tôi biết ai, khi phải đối mặt với việc sử dụng C, muốn một tập các macro làm cho C trở nên giống Pascal hơn. Tôi nghĩ rằng luôn luôn có một sự cám dỗ để giảm bớt sự khó chịu của bạn với một cái gì đó mới bằng cách buộc nó giống như quen thuộc hơn. Và đôi khi nó là tốt cho bạn để tiếp cận một cái gì đó khác nhau về các điều khoản riêng của mình. – user100464

Trả lời

13

macro Viết sẽ trở nên khó khăn hơn vì cấu trúc sẽ không còn đơn giản, bạn sẽ cần một cách khác để mã hóa mà biểu thức bắt đầu và ngừng sử dụng một số biểu tượng cú pháp để đánh dấu sự bắt đầu và kết thúc của biểu thức để bạn có thể ghi mã để tạo biểu có lẽ bạn có thể giải quyết vấn đề này bằng cách thêm một cái gì đó giống như một ( để đánh dấu sự khởi đầu của biểu thức ...

trên một góc hoàn toàn khác nhau, nó rất đáng xem video này trên the difference between familiar and easy làm lisps cú pháp quen thuộc hơn sẽ không làm cho nó dễ dàng hơn để mọi người tìm hiểu và có thể làm cho nó gây hiểu nhầm nếu nó trông giống như một cái gì đó nó không phải là.

thậm chí Nếu bạn hoàn toàn không đồng ý, video đó đáng giá một giờ.

23

Chỉ cần di chuyển các dấu ngoặc đơn một nguyên tử vào cho các cuộc gọi hàm sẽ không đủ để thỏa mãn bất kỳ ai; mọi người sẽ phàn nàn về việc thiếu các toán tử infix, các khối bắt đầu/kết thúc, v.v. Plus bạn có thể phải giới thiệu dấu phẩy/dấu phân cách ở tất cả các loại địa điểm.

Cung cấp cho họ điều đó và các macro sẽ khó hơn nhiều để viết chính xác (và có thể sẽ khó viết các macro trông và hành động tốt hơn với tất cả cú pháp mới mà bạn đã giới thiệu sau đó). Và các macro không phải là một tính năng tốt đẹp mà bạn có thể bỏ qua hoặc gây ra nhiều phiền toái hơn; toàn bộ ngôn ngữ (giống như bất kỳ Lisp nào khác) được xây dựng ngay trên đầu trang của chúng. Hầu hết các công cụ "có thể nhìn thấy" trong clojure.core, bao gồm let, def, defn, vv là các macro.

+0

:) Đồng ý rằng bạn không thể làm cho mọi người hạnh phúc. Tôi giả sử bạn muốn giữ macro, và tôi nghĩ bạn đang nói "tốt, bạn phải viết lại tất cả các macro ngôn ngữ cốt lõi". Nhưng vấn đề là một người nào đó đã quyết định điều này xứng đáng với ít nhất ba ngôn ngữ khác nhau. Câu hỏi của tôi không phải là lý do tại sao nhưng cái gì. – hawkeye

0
Were Clojure to go down this path - what would it have to sacrifice to get there? 

Sự hy sinh sẽ là cảm giác/tinh thần viết mã bằng cách tạo Danh sách danh sách .. hoặc kỹ thuật hơn "viết AST trực tiếp".

LƯU Ý: Có những thứ khác cũng sẽ được làm rõ như đã đề cập trong các câu trả lời khác.

2

Tôi đã sử dụng để mã C/C#/Java/Pascal vì vậy tôi nhấn mạnh với cảm giác rằng mã Lisp hơi lạ. Tuy nhiên cảm giác đó chỉ kéo dài vài tuần - sau một khoảng thời gian khá ngắn, phong cách Lisp sẽ rất tự nhiên và bạn sẽ bắt đầu bẻ tiếng các ngôn ngữ khác cho cú pháp "bất thường" :-)

Có một lý do rất tốt cho cú pháp Lisp. Các dấu ngoặc đơn hàng đầu làm cho mã hợp lý đơn giản hơn để phân tích cú pháp và đọc, bằng cách thu thập cả hàm và các biểu thức tạo nên các đối số của nó trong một biểu mẫu duy nhất.

Và khi bạn thao tác mã/macro sử dụng, đó là những biểu mẫu quan trọng: đây là các khối xây dựng của tất cả mã của bạn. Vì vậy, về cơ bản nó có ý nghĩa để đặt các dấu ngoặc đơn ở một nơi chính xác phân định các biểu mẫu này, thay vì tự ý rời khỏi phần tử đầu tiên bên ngoài biểu mẫu.

1

Triết lý "mã là dữ liệu" là những gì làm cho lập trình meta có thể tin cậy có thể. So sánh với Perl/Ruby, có cú pháp phức tạp, cách tiếp cận của họ để lập trình meta chỉ đáng tin cậy trong những hoàn cảnh rất hạn chế. Lập trình siêu lập trình Lisp hoàn toàn đáng tin cậy đến mức cốt lõi của ngôn ngữ phụ thuộc vào nó. Lý do cho điều này là cú pháp thống nhất được chia sẻ bởi mã và dữ liệu (tài sản của homoiconicity). Biểu thức S là cách thức tính đồng nhất này được thực hiện.

Điều đó nói rằng, có những trường hợp trong Clojure nơi ngụ ý ngoặc là có thể:

Ví dụ ba từ ngữ dưới đây được tương đương:

  1. (đầu tiên (phần còn lại (phần còn lại [1 2 3 4 5 6 7 8 9])))
  2. (-> [1 2 3 4 5 6 7 8 9] (còn lại) (còn lại) (trước))
  3. (-> [1 2 3 4 5 6 7 8 9 ] nghỉ ngơi còn lại trước)

Lưu ý rằng trong macro thứ ba -> có thể trong ngữ cảnh này để suy ra dấu ngoặc đơn và do đó loại bỏ chúng. Có rất nhiều trường hợp đặc biệt như thế này. Nói chung, thiết kế của Clojure sai lệch bên cạnh các dấu ngoặc đơn ít hơn. Xem ví dụ như quyết định gây tranh cãi về việc bỏ dấu ngoặc đơn trong cond. Clojure là rất nguyên tắc và nhất quán về sự lựa chọn này.

13

bạn sẽ không cần phải hy sinh bất cứ điều gì. có một cách tiếp cận nghĩ ra rất cẩn thận bởi david wheeler đó là hoàn toàn minh bạch và tương thích ngược, với sự hỗ trợ đầy đủ cho các macro, vv

19

(tín dụng để trả lời andrew Cooke, người cung cấp các liên kết đến Wheeler và Gloria của "Readable Lisp S-expressions Project")

Các liên kết ở trên là một dự án nhằm cung cấp cú pháp có thể đọc được cho tất cả các ngôn ngữ dựa trên các biểu thức s, bao gồm Đề án và Clojure. Kết luận là nó có thể được thực hiện: có một cách để có Lisp có thể đọc được mà không có dấu ngoặc đơn. Về cơ bản những gì dự án của David Wheeler làm là thêm đường cú pháp vào các ngôn ngữ giống như Lisp để cung cấp cú pháp hiện đại hơn, theo cách không phá vỡ sự hỗ trợ của Lisp cho các ngôn ngữ cụ thể theo miền. Các cải tiến là tùy chọn và tương thích ngược, vì vậy bạn có thể bao gồm nhiều hoặc ít phần tùy thích và trộn chúng với mã hiện có.

dự án này định nghĩa ba loại biểu hiện mới:

  • Quăn-infix-biểu thức. (+ 1 2 3) trở thành {1 + 2 + 3} ở mọi nơi bạn muốn sử dụng toán tử kết hợp của bất kỳ điều gì. (Có một trường hợp đặc biệt cần được xử lý cẩn thận nếu biểu thức nội tuyến sử dụng một số toán tử, như {1 + 2 * 3} - mặc dù {1 + {2 * 3}} hoạt động như mong đợi).
  • Biểu thức huyền bí. (f x y) trở thành f (x y) (yêu cầu không đặt dấu cách giữa tên hàm và thông số của nó)
  • Biểu thức ngọt ngào. Mở và đóng cha mẹ có thể được thay thế bằng (tùy chọn) thụt đầu dòng ngữ nghĩa giống như python. Các biểu thức ngọt có thể được tự do trộn lẫn với các dấu ngoặc đơn truyền thống.

Kết quả là mã tuân thủ Lisp nhưng dễ đọc hơn nhiều. Một ví dụ về cách các đường cú pháp mới tăng cường khả năng đọc:

(define (gcd_ a b) 
    (let (r (% b a)) 
     (if (= r 0) a (gcd_ r a)))) 

(define-macro (my-gcd) 
    (apply gcd_ (args) 2)) 

trở thành:

define gcd_(a b) 
    let r {b % a} 
     if {r = 0} a gcd_(r a) 

define-macro my-gcd() 
    apply gcd_ (args) 2 

Lưu ý cách mà cú pháp tương thích với các macro, mà là một vấn đề với previous projects that intended to improve Lisp syntax (như mô tả của Wheeler và Gloria) . Bởi vì nó chỉ là đường, hình thức cuối cùng của mỗi biểu thức mới là một biểu thức s, được chuyển đổi bởi trình đọc ngôn ngữ trước khi macro được xử lý - vì vậy các macro không cần bất kỳ xử lý đặc biệt nào. Do đó dự án "dễ đọc Lisp" bảo tồn tính đồng nhất, thuộc tính cho phép Lisp đại diện cho mã như dữ liệu trong ngôn ngữ, đó là những gì cho phép nó trở thành một môi trường lập trình meta mạnh mẽ.

+2

nếu bạn bị sa thải, nó luôn đánh tôi rằng vợt (một kế hoạch hỗ trợ nhiều "ngôn ngữ") sẽ là một nơi tốt để thực hiện điều này - https://en.wikipedia.org/wiki/Racket_features#Language_Extensions –

3

Bạn sẽ có Mathematica. Mathematica chấp nhận các hàm gọi là f[x, y, z], nhưng khi bạn điều tra thêm, bạn thấy rằng f[x, y, z] thực sự là cú pháp đường cho danh sách trong đó Head (phần tử 0) là fRest (các phần từ 1 đến N) là {x, y, z}. Bạn có thể xây dựng các cuộc gọi chức năng từ các danh sách trông giống như các biểu thức S và bạn có thể phân hủy các hàm chưa được đánh giá thành các danh sách (Hold ngăn việc đánh giá, giống như quote trong Lisp).

Có thể có sự khác biệt về ngữ nghĩa giữa Mathematica và Lisp/Đề án/Clojure, nhưng cú pháp của Mathematica là một minh chứng rằng bạn có thể di chuyển ngoặc trái qua bởi một nguyên tử và vẫn giải thích nó một cách hợp lý, xây dựng mã với macro vv

Cú pháp là khá dễ dàng để chuyển đổi với một bộ tiền xử lý (dễ dàng hơn nhiều so với ngữ nghĩa). Bạn có thể nhận được cú pháp bạn muốn thông qua một số phân lớp thông minh của Clojure's LispReader. Thậm chí có a project tìm cách giải quyết dấu ngoặc đơn của Clojure bằng cách thay thế tất cả chúng bằng dấu ngoặc vuông. (Nó lởn vởn tâm trí của tôi rằng đây được xem là một vấn đề lớn.)