Почему я получаю ошибку, когда пытаюсь использовать правило Симпсона в Clojure? - PullRequest
2 голосов
/ 24 мая 2011

Я пытаюсь выполнить некоторые упражнения в SICP с использованием Clojure, но получаю ошибку с моим текущим методом выполнения правила Симпсона (пример 1-29).Это имеет отношение к ленивой / нетерпеливой оценке?Любые идеи о том, как это исправить?Ошибка и код приведены ниже:

java.lang.ClassCastException: пользователь $ simpson $ h__1445 не может быть приведен к java.lang.Number в clojure.lang.Numbers.divide (Numbers.java:139)

Вот код:

(defn simpson [f a b n]
  (defn h [] (/ (- b a) n))
  (defn simpson-term [k]
    (defn y [] (f (+ a (* k h))))
    (cond 
      (= k 0) y
      (= k n) y
      (even? k) (* 2 y)
      :else (* 4 y)))
  (* (/ h 3)
     (sum simpson-term 0 inc n)))

1 Ответ

7 голосов
/ 24 мая 2011

Вы определяете h как функцию без аргументов, а затем пытаетесь использовать ее, как если бы это было число. Я также не уверен, к чему ты клонишь с (sum simpson-term 0 inc n); Я просто предположу, что sum - это какая-то магия, которую вы получили от SICP, и что аргументы, которые вы ей передаете, верны (я смутно припоминаю, что они определяют какую-то общую сумму).

Другое дело, что почти всегда ужасно иметь def или defn, вложенных в defn. Вы, вероятно, хотите либо let (для чего-то временного или локального) или другого верхнего уровня defn.

Помня, что я годами не писал simpson функцию и не проверял ее на алгоритмическую корректность на всех , вот эскиз, который ближе к "правильной форме" "чем ваш:

(defn simpson [f a b n]
  (let [h (/ (- b a) n)
        simpson-term (fn [k]
                       (let [y (f (+ a (* k h)))]
                         (cond 
                          (= k 0) y
                          (= k n) y
                          (even? k) (* 2 y)
                          :else (* 4 y))))]
    (* (/ h 3)
       (sum simpson-term 0 inc n))))
...