Clojure China

请问怎么用不同的方法写一个findmax函数

#1

我想找到一个列表里的最大值,我查了下文档,发现只有max函数,这个函数这样声明(max &args)
没有提供在列表的函数,于是我想到解引述~@,然后我定义了一个宏:

(defmacro findmax [l]
`(max ~@l))

单我传入的参数为vec向量时,可以正常使用,但参数为’(1 2 3 4)直接报错,
另外这个宏没办法处理当参数为(vec 1 2 3 4)这样的复合表达式
我又想到了sort函数,于是我这样定义

(defn findmax [l]
    (let [sortedlist (sort l)]
        (last sortedlist)))

我想问一下,除了这种用sort的做法,还有没有用宏定义或函数的做法,我能力有限,实在想不出来,也不知道怎么改进我的findmax宏

#2
user=> (macroexpand-1 '(findmax '(1 2 3)))
(clojure.core/max quote (1 2 3))
user=> (macroexpand-1 '(findmax [1 2 3]))
(clojure.core/max 1 2 3)
user=> (macroexpand-1 '(findmax (list 1 2 3)))
(clojure.core/max list 1 2 3)
#3

不是有apply吗

#4
user=> (defn findmax [l] (apply max l) )
#'user/findmax
user=> (findmax '(32 12 88))
88
user=> (findmax [77 66 55])
77

这样?

#5

用 apply 在 l 元素很多的情况下肯定性能不好, 因为它会把参数列表 pack/unpack 。最好是写成递归的或者直接用 reduce

(defn find-max [v]
  (reduce max v))
#6

那个,好像apply比reduce好理解,不过用reduce却是挺快的

#7

clojure 的函数式编程语言,map reduce filter 这些函数是 clojure 的基本功,就好比 for 循环是 c/c++/java 的基本功一样 。。。如果要认真学 clojure 的话建议扎实地掌握一下。。

#8

涨姿势了。。