使用可变参数定义我自己的 max 函数

发布于 2024-12-05 15:32:14 字数 1034 浏览 1 评论 0原文

我正在学习 Clojure,解决 4clojure 上列出的问题。练习之一是创建您自己的带有可变参数的 max 函数。

我正在尝试使用 REPL 解决这个简单的问题,并且得到了这个解决方案:

(defn my-max 
    [first & more] (calc-max first more))

(defn calc-max 
    [m x] 
        (cond (empty? x) m
            (> (first x) m) (calc-max (first x) (rest x))
            :else calc-max m (rest x)))

效果很好,但练习不允许使用 def,因此我必须将这两个函数合而为一。当我用其代码替换 calc-max 引用时,结果是:

(defn my-max 
    [first & more] 
    ((fn calc-max 
        [m x] 
            (cond (empty? x) m
                (> (first x) m) (calc-max (first x) (rest x))
                :else calc-max m (rest x)))
                    first more))

但是此代码不起作用并返回下一个错误:

user=> (my-max 12 3 4 5 612 3)
java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn (NO_SOURCE_FILE:0)

我猜这个错误来自于尝试评估 的结果>calc-max 函数,我猜这是我的语法错误,但我不知道如何解决它。

I'm learning Clojure solving the problems listed on 4clojure. One of the exercises is to create your own max function with variable arguments.

I'm trying to solve this easy problem using the REPL and I got to this solution:

(defn my-max 
    [first & more] (calc-max first more))

(defn calc-max 
    [m x] 
        (cond (empty? x) m
            (> (first x) m) (calc-max (first x) (rest x))
            :else calc-max m (rest x)))

Which works fine but the exercise doesn't allow the use of def and therefore I must crunch both functions into one. When I replace the calc-max reference with its code the result is:

(defn my-max 
    [first & more] 
    ((fn calc-max 
        [m x] 
            (cond (empty? x) m
                (> (first x) m) (calc-max (first x) (rest x))
                :else calc-max m (rest x)))
                    first more))

But this code doesn't work and returns the next error:

user=> (my-max 12 3 4 5 612 3)
java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn (NO_SOURCE_FILE:0)

I guess this error comes from trying to evaluate the result of the calc-max function and I guess it's a syntax error on my part, but I can't figure out how to resolve it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

旧伤还要旧人安 2024-12-12 15:32:14

这是我用来解决这个问题的函数。重点是根本不使用 max。

(fn [& args] (reduce (fn [x y] (if (> x y) x y) ) args ) )

Here is the function I used to solve it. The point is not to use max at all.

(fn [& args] (reduce (fn [x y] (if (> x y) x y) ) args ) )
暮光沉寂 2024-12-12 15:32:14

真正的错误是您调用了参数first - 它将真正的first函数重新绑定到数字!只需将名称更改为其他名称,您的变体就会起作用。虽然显式命名函数可能更好,但您可以使用 letfn 将 calc-max 声明为本地函数,而不是调用匿名函数。所以你的 my-max 看起来像:

(defn my-max [ff & more]
  (letfn [(calc-max [m x] 
            (cond (empty? x) m
                  (> (first x) m) (calc-max (first x) 
                                            (rest x))
                  :else (calc-max m (rest x))))]
    (calc-max ff more)))

虽然,我认为,你可以编写更简单的代码:

(defn my-max [& more] (reduce max more))

Real error is that you called parameter first - it rebinds real first function to number! Just change name to something other, and your variant will work. Although it maybe better explicitly name function, instead of calling anonymous function, for example, you can declare calc-max as local function using letfn, for example. So your my-max will look like:

(defn my-max [ff & more]
  (letfn [(calc-max [m x] 
            (cond (empty? x) m
                  (> (first x) m) (calc-max (first x) 
                                            (rest x))
                  :else (calc-max m (rest x))))]
    (calc-max ff more)))

Although, I think, that you can write simpler code:

(defn my-max [& more] (reduce max more))
伤痕我心 2024-12-12 15:32:14

您的函数不起作用,因为 fn 中的 first 被视为函数而不是输入值。所以当你写

user=> (my-max 12 3 4 5 612 3)

它的时候,它不能将 12 转换为函数。简单地说,它可以重写为

(defn my-max1 [fst & more]
  ((fn calc-max [m x]
     (cond (empty? x) m
           (> (first x) m) (calc-max (first x) (rest x))
           :else (calc-max m (rest x))))
    fst more))

或什至不重写为 fn

(defn my-max [x & xs]
  (cond (empty? xs) x
        (> (first xs) x) (recur (first xs) (rest xs))
        :else (recur x (rest xs))))

Your function doesn't work because first in fn treated as function and not as input value. So when you write

user=> (my-max 12 3 4 5 612 3)

it's talling that can't cast 12 to function. Simply, it can be rewrited as

(defn my-max1 [fst & more]
  ((fn calc-max [m x]
     (cond (empty? x) m
           (> (first x) m) (calc-max (first x) (rest x))
           :else (calc-max m (rest x))))
    fst more))

or even without fn

(defn my-max [x & xs]
  (cond (empty? xs) x
        (> (first xs) x) (recur (first xs) (rest xs))
        :else (recur x (rest xs))))
二智少女猫性小仙女 2024-12-12 15:32:14

详细说明一下您所看到的异常:每当 Clojure 向

java.lang.Integer cannot be cast to clojure.lang.IFn

您抛出类似的内容时,这意味着它试图调用一个函数,但它试图调用的不是一个函数,而是其他东西。当您有这样的代码时,通常会发生这种情况:

(smbl 1 2 3)

如果 smbl 引用一个函数,clojure 将使用参数 1 2 和 3 执行它。但是如果 smbl 不引用函数函数,然后你会看到类似上面的错误。这是我查看代码时的指针,正如 4e6 指出的那样,(first x) 是这里的罪魁祸首,因为您将函数参数命名为 first

To elaborate a little more on the exception that you are seeing: whenever Clojure throws something like

java.lang.Integer cannot be cast to clojure.lang.IFn

at you it means that it tried to call a function but the thing it tried to call was not a function but something else. This usually occurs when you have code like this

(smbl 1 2 3)

If smbl refers to a function, clojure will execute it with parameters 1 2 and 3. But if smbl doesn't refer to a function then you will see an error like the one above. This was my pointer in looking through your code and, as 4e6 pointed out, (first x) is the culprit here because you named your function argument first.

感性不性感 2024-12-12 15:32:14

不如reduce那么好,但还可以吧:

(fn [& args]
(循环[l args, maxno (第一个参数)]
(如果(空?l)
最大号
(if (> maxno (第一个 l) )
(重复(剩余 l)maxno)
(recur (rest l) (first l))))))

我想可以使用 cond

Not as good as the reduce but ok ba:

(fn [& args]
(loop [l args, maxno (first args)]
(if (empty? l)
maxno
(if (> maxno (first l) )
(recur (rest l) maxno)
(recur (rest l) (first l))))))

Can use cond I suppose

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文