Tất cả các ví dụ được lấy từ Sách SICP: http://sicpinclojure.com/?q=sicp/1-3-3-procedures-general-methodsCách tiêu chuẩn để viết các câu lệnh xác định lồng nhau (như trong sơ đồ) cho clojure là gì?
này được thúc đẩy từ loạt video MIT về LISP - http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-001-structure-and-interpretation-of-computer-programs-spring-2005/video-lectures/2a-higher-order-procedures/
Trong chương trình, bạn có thể đặt 'định nghĩa' bên trong một 'định nghĩa':
(define (close-enough? v1 v2)
(define tolerance 0.00001)
(< (abs (- v1 v2)) tolerance))
Trong clojure, đó là 'let' tuyên bố với sự khác biệt duy nhất mà nó được lồng:
(defn close-enough? [v1 v2]
(let [tolerance 0.00001]
(< (Math/abs (- v1 v2))
tolerance)))
Nhưng những gì về viết lại trong clojure một cái gì đó lớn hơn như thế này ?:
(define (sqrt x)
(define (fixed-point f first-guess)
(define (close-enough? v1 v2)
(define tolerance 0.00001)
(< (abs (- v1 v2)) tolerance))
(define (try guess)
(let ((next (f guess)))
(if (close-enough? guess next)
next
(try next))))
(try first-guess))
(fixed-point (lambda (y) (average y (/ x y)))
1.0))
này làm trong công việc thực tế nhưng trông rất độc đáo ...
(defn sqrt [n]
(let [precision 10e-6
abs #(if (< % 0) (- %) %)
close-enough? #(-> (- %1 %2) abs (< precision))
averaged-func #(/ (+ (/ n %) %) 2)
fixed-point (fn [f start]
(loop [old start
new (f start)]
(if (close-enough? old new)
new
(recur new (f new)))))]
(fixed-point averaged-func 1)))
(sqrt 10)
UPDATED Mar/8/2012
Cảm ơn câu trả lời!
Về cơ bản 'letfn' không quá khác biệt với 'let' - các hàm được gọi phải được lồng trong định nghĩa 'letfn' (trái ngược với Đề án trong đó các hàm được sử dụng trong sexp tiếp theo sau định nghĩa của nó và chỉ tồn tại trong phạm vi của hàm cấp cao nhất mà nó được xác định).
Vì vậy, một câu hỏi khác ... Tại sao không clojure cung cấp cho khả năng làm những gì chương trình nào? Có một số loại quyết định thiết kế ngôn ngữ không? Những gì tôi thích về việc tổ chức chương trình là:
1) Các đóng gói các ý tưởng vì vậy mà tôi như các lập trình viên có một ý tưởng như những gì các khối nhỏ đang được sử dụng khối lớn - đặc biệt là nếu tôi chỉ sử dụng ít khối một lần trong khối lớn (vì lý do gì, ngay cả khi các khối nhỏ hữu ích trong quyền riêng của họ).
2) Điều này cũng dừng gây ô nhiễm không gian tên với ít thủ tục không hữu ích cho người dùng cuối (tôi đã viết chương trình clojure, quay lại sau một tuần và phải tìm hiểu lại mã của tôi vì nó trong một cấu trúc phẳng và tôi cảm thấy rằng tôi đã nhìn vào mã bên trong ra ngoài như trái ngược với một cách từ trên xuống).
3) Giao diện định nghĩa phương pháp chung để tôi có thể rút ra một phương thức phụ cụ thể, bỏ thụt lề thử nghiệm và dán lại phiên bản đã thay đổi mà không quá khó sử dụng.
Tại sao điều này không được thực hiện trong clojure?
đó là một câu hỏi thú vị nhưng tôi không nghĩ rằng tôi sẽ cố gắng đặt tất cả trong một chức năng. – Kevin