1

我一定对如何定义函数有误解。我正在做这个 SICP 练习,“定义一个以三个数字作为参数并返回两个较大数字的平方和的过程。”

我在 REPL 中尝试了这个,它似乎有效:

=> (reduce + (map (fn [x] (* x x)) (rest (sort '(2 1 0)))))
5

但是定义一个过程并用参数替换数字会给我一个错误:

=> (defn my-procedure [a b c] (reduce + (map (fn [x] (* x x)) (rest (sort '(a b c))))))
ClassCastException clojure.lang.Symbol cannot be cast to java.lang.Number clojure.lang.Numbers.multiply (Numbers.java:146)

我没看到什么?谢谢!

4

2 回答 2

1

这应该适合你:

(defn my-procedure [a b c]
  (reduce + (map (fn [x] (* x x)) (rest (sort (list a b c))))))

这就是为什么:

当您使用报价表单时,不会评估表单,也不会解析您的变量。在您的情况下,您会得到一个符号列表。

user=> (def a 1)
#'user/a
user=> '(a)
(a)
user=> (list a)
(1)
user=> `(a) ;; backtick causes vars to be namespace qualified
(user/a)
user=> (class (first '(a)))
clojure.lang.Symbol

list您应该使用函数或其他集合,而不是创建未评估的表单

user=> [a] ;; vector
[1]
user=> #{a} ;; set
#{1}

;; (defn sum-of-squares [& args]
;;   (apply + (map #(* % %) args)))
于 2013-01-18T21:55:20.730 回答
0

自动将函数的参数放入集合中:

(defn foo [& x]
  (reduce + (map #(* % %) (rest (sort x)))))
于 2013-01-27T20:19:31.850 回答