Каков стандартный способ написания вложенных операторов определения (как на схеме) для clojure?

Все примеры взяты из книги SICP: http://sicpinclojure.com/?q=sicp/1-3-3-procedures-general- методы

Это было мотивировано серией видео MIT по 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/

В схеме вы можете поместить «define» внутри другого «define»:

(define (close-enough? v1 v2)
    (define tolerance 0.00001)
    (< (abs (- v1 v2)) tolerance ) )

В clojure есть « let' с той лишь разницей, что она вложенная:

(defn close-enough? [v1 v2]
    (let [tolerance 0.00001]
         (< (Math/abs (- v1 v2) ) 
            tolerance) ) )

А как насчет того, чтобы переписать в clojure что-то большее вроде этого?:

(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))

Это на самом деле работает, но выглядит очень нетрадиционно...

(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)

ОБНОВЛЕНО 8 марта/ 2012

Спасибо за ответ!

По сути, 'letfn' не слишком отличается от 'let' — вызываемые функции должны быть вложены в определение 'letfn' (в отличие от Scheme, где функции используются в следующем sexp после его определений и только существующие). в рамках функции верхнего уровня, в которой она определена).

Итак, еще вопрос...Почему clojure не дает возможности делать то, что делает схема? Это какое-то языковое дизайнерское решение? Что мне нравится в организации схемы, так это:

  • 1) Инкапсуляция идей, так что я, как программист, имею представление о том, какие маленькие блоки используются в более крупном блоке, особенно если я использую маленькие блоки только один раз в пределах одного блока. большой блок (по какой-либо причине, даже если маленькие блоки полезны сами по себе).

  • 2) Это также останавливает засорение пространства имен небольшими процедурами, которые бесполезны для конечного пользователя (я писал программы на clojure, вернулся к ним через неделю, и мне пришлось заново изучать мой код, потому что он был в плоская структура, и я чувствовал, что смотрю на код изнутри, а не сверху вниз).

  • 3) Общий интерфейс определения метода, поэтому я могу вытащить конкретный подметод, убрать отступ, протестировать его и вставить измененную версию обратно без особых возни.

Почему это не реализовано в clojure?

11
задан zcaudate 28 March 2012 в 01:21
поделиться