2012-04-23 27 views
18
  • defn = công
  • defn- = tin

Có lẽ tôi phải xấu phong cách mã hóa Clojure - nhưng tôi thấy rằng hầu hết các chức năng tôi viết trong Clojure là các hàm trợ giúp nhỏ mà tôi không muốn phơi bày.Clojure, defn, defn-, public/private, giá trị mặc định

Có một số tùy chọn cấu hình, trong đó:

  • defn = tin theo mặc định,
  • và để làm một cái gì đó công chúng, tôi phải làm defn+?

Cảm ơn!

Trả lời

16

Không. Không có.

Một phương pháp thay thế có thể hoặc có thể không hoạt động cho bạn là khai báo một không gian tên foo.bar.internal chứa tất cả những người trợ giúp riêng tư được sử dụng bởi không gian tên foo.bar của bạn. Điều này có lợi thế hơn các khai báo hàm riêng khi bạn muốn sử dụng các hàm riêng trong các mở rộng macro.

+12

Không chỉ là không có, nó sẽ thực sự gây rối với tâm trí của bất kỳ Clojurian khác nhìn vào mã như vậy. Tôi sẽ không khuyến khích nó ngay cả khi nó có thể làm được. –

4

Nếu "chức năng trợ giúp" rất có thể được sử dụng một lần, bạn có thể chọn đặt chúng ở vị trí địa lý lớn hơn hoặc viết chúng dưới dạng hàm ẩn danh. Xem letfn: http://clojuredocs.org/clojure_core/clojure.core/letfnhttp://clojuredocs.org/clojure_core/clojure.core/fn.

Tôi hầu như không bao giờ sử dụng letfn bản thân mình.

+0

Tôi không nghĩ rằng kích thước của các chức năng trợ giúp này quan trọng. Nếu chúng được sử dụng nhiều lần, chúng thực sự cần được trừu tượng hóa cho mã máy sấy. Tôi thực sự không thể thấy lý do khiến chúng trở thành địa phương/ẩn danh trừ khi chúng chỉ được sử dụng một lần cục bộ. – tjb1982

+0

Điều này đúng. Tôi sẽ điều chỉnh câu trả lời. –

+0

Tôi đã cố gắng sử dụng 'letfn' cho những người giúp đỡ của mình, nhưng nó làm cho mã của tôi quá lộn xộn. Vì vậy, sau một thời gian ngắn, tôi chuyển sang 'defn-'. –

4

Như đã nêu bởi @kotarak, không có cách nào (theo như tôi biết) để làm điều đó, cũng không phải là mong muốn.

Đây là lý do tại sao tôi không thích defn-:

tôi phát hiện ra rằng khi sử dụng các thư viện Clojure khác nhau đôi khi tôi cần một chút thay đổi một chức năng để phù hợp hơn với nhu cầu cụ thể của tôi. Nó thường là một cái gì đó khá nhỏ, và điều đó chỉ có ý nghĩa trong trường hợp cụ thể của tôi. Thường thì đây chỉ là một hoặc hai.

Nhưng khi chức năng này sử dụng lại các chức năng riêng bên trong, nó làm cho việc sửa đổi trở nên khó khăn hơn. Tôi phải sao chép-dán tất cả các chức năng riêng tư đó.

Tôi hiểu rằng đây là cách để người lập trình nói rằng "điều này có thể thay đổi mà không cần thông báo".

Bất kể, tôi muốn quy ước ngược lại:

  • luôn luôn sử dụng defn, mà làm cho tất cả mọi thứ công
  • sử dụng defn+ (mà chưa hề tồn tại) để xác định để các lập trình viên có chức năng là một phần của API công khai mà anh ta định sử dụng. defn+ không được khác với defn nếu không.

Cũng xin lưu ý rằng nó có thể access private functions anyway:

;; in namespace user 
user> (defn- secret [] 
     "TOP SECRET") 

;; from another namespace 
(#'user/secret) ;;=> "TOP SECRET" 
+2

Từ kinh nghiệm của tôi với Ruby cho phép truy cập không giới hạn vào mọi thứ (chỉ cần sử dụng #send cho các phương thức riêng). Nó kết thúc là một mớ hỗn độn lớn và các nhà phát triển ít kinh nghiệm có xu hướng lạm dụng "tự do" này bằng cách làm những điều thực sự xấu. – yagooar

+0

Sau khi làm việc trên một codebase clojure lớn, tôi thực sự tìm thấy một số giá trị cho trường hợp 'defn-' riêng. Tôi vẫn chưa thử sử dụng 'defn +'. – nha

+2

Chính xác. Nếu tôi phạm sai lầm khi sửa đổi chức năng của người khác, đó là lỗi của tôi. Là một lập trình viên, ngăn cản tôi sửa đổi nội bộ là một sự xúc phạm. Mọi thứ phải được công khai. Chỉ cần ghi lại mọi vấn đề tiềm ẩn một cách chính xác và không cần phải riêng tư. – Rebs

4

Vẻ đẹp của Clojure là một Lisp, là bạn có thể xây dựng và thích nghi với ngôn ngữ cho phù hợp với nhu cầu của bạn. Tôi khuyên bạn nên đọc On Lisp, by Paul Graham. Bây giờ anh ta tặng sách của mình miễn phí.

Về đề xuất của bạn về defn + vs defn vs defn-. Điều này âm thanh với tôi như một trường hợp tốt để viết Macro của riêng bạn. defn là một hàm và defn- là một macro. Bạn chỉ có thể xác định lại chúng như bạn muốn, hoặc quấn chúng theo cách riêng của bạn.

Dưới đây là một đề xuất để triển khai, dựa chủ yếu vào việc thực hiện riêng của Clojure - bao gồm một tiện ích đơn giản và thử nghiệm.

(defmacro defn+ 
    "same as Clojure's defn, yielding public def" 
    [name & decls] 
    (list* `defn (with-meta name (assoc (meta name) :public true)) decls)) 

(defmacro defn 
    "same as Clojure's defn-, yielding non-public def" 
    [name & decls] 
    (list* `defn (with-meta name (assoc (meta name) :private true)) decls)) 

(defn mac1 
    "same as `macroexpand-1`" 
    [form] 
    (. clojure.lang.Compiler (macroexpand1 form))) 

(let [ ex1 (mac1 '(defn f1 [] (println "Hello me."))) 
     ex2 (mac1 '(defn+ f2 [] (println "Hello World!"))) ] 
    (defn f1 [] (println "Hello me.")) 
    (defn+ f2 [] (println "Hello World!")) 
    (prn ex1) (prn (meta #'f1)) (f1) 
    (prn ex2) (prn (meta #'f2)) (f2)) 
Các vấn đề liên quan