Clojure NullPointerException 错误

发布于 2024-12-07 13:11:32 字数 476 浏览 0 评论 0原文

我是 clojure 的新手,尝试编写简单的函数来获取数字列表并仅过滤偶数。

我想在没有过滤器的情况下执行此操作,甚至?,只有纯 clojure

(defn my-even [ilist]
   (if
    (= (mod (first ilist) 2) 0)
    (concat (list (first ilist)) (my-even (rest ilist)))
    (my-even (rest ilist))
   )
)

我尝试运行它:

(my-even '(1,2,3,4,5))

但出现错误:出了

#<CompilerException java.lang.NullPointerException (NO_SOURCE_FILE:0)>

什么问题?

谢谢。

I'm new in clojure and try to write simple function which get list of numbers and filter only even numbers.

I want to do it witout filter or even?, only pure clojure

(defn my-even [ilist]
   (if
    (= (mod (first ilist) 2) 0)
    (concat (list (first ilist)) (my-even (rest ilist)))
    (my-even (rest ilist))
   )
)

I try to run it:

(my-even '(1,2,3,4,5))

But get error:

#<CompilerException java.lang.NullPointerException (NO_SOURCE_FILE:0)>

What's wrong?

Thank you.

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

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

发布评论

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

评论(4

半世蒼涼 2024-12-14 13:11:32

正如乔纳斯所说,你没有基本情况;你没有基本情况。除此之外,将括号放在单独的行上并不是 Clojure(或任何其他 Lisp)惯用的做法,还要将 if 的谓词保持在同一行。

通过解构,它的可读性更强:

(defn my-even? [coll]
  (if-let [[first & rest] coll]
    (if (= (mod first 2) 0)
      (cons first (my-even? rest))
      (my-even? rest))))

As Jonas said, you do not have a base case; in addition to that it is not idiomatic Clojure (or any other Lisp) to put parens on separate lines, also keep the if's predicate on the same line.

With destructuring it is a bit more readable:

(defn my-even? [coll]
  (if-let [[first & rest] coll]
    (if (= (mod first 2) 0)
      (cons first (my-even? rest))
      (my-even? rest))))
稚然 2024-12-14 13:11:32

您的递归函数my-even没有基本情况。当列表中没有更多元素时会发生什么? (first ilist) 返回 nil 并且 (mod nil 2) 抛出 NullPointerException。

您必须以某种方式测试空列表。

Your recursive function my-even does not have a base case. What happens when there are no more elements in the list? (first ilist) returns nil and (mod nil 2) throws a NullPointerException.

You must somehow test for the empty list.

乖乖兔^ω^ 2024-12-14 13:11:32

很高兴本周看到这么多人学习 Clojure :) 从像这样的基本问题开始是一个非常好的开始。哈姆扎和乔纳斯的回答显然很好地涵盖了最初的问题。我想主动提供一些关于从这里获取它的建议,希望对您有所帮助。

一旦你有了基本的递归形式,你通常可以通过以下方式将其转换为惯用的 Clojure:

1)尽可能使用尾递归形式(你已经这样做了)
2) 用 recur 调用替换直接递归,以防止堆栈溢出。 (从 Hamza 的工作答案开始)

(defn my-even? [coll]
   (if-let [[first & rest] coll]
    (if (= (mod first 2) 0)
      (cons first (my-even? rest))
      (recur rest))))

recur 导致编译器跳转到堆栈帧的开头,而不是分配一个新的堆栈帧。没有这个它会破坏堆栈。

3) 在许多情况下,您可以使用 mapreduce 等高阶函数消除 (defn [] ... (recur)) 模式>、filterfor 等。在本练习中,我看到您尝试不使用 filtereven ,所以显然你可以写 my-filter 和 my-even 就可以了;)

4) 将可分割的部分(构建列表,选择要包含的内容)提取到可重用的函数中,并上传对 clojure contrib 项目通常有用的任何部分:)

5) 仔细思考您是否应该使用 ( lazy-seq ...) 因为你很有可能重新发明轮子。

It's great to see so many people learning Clojure this week :) starting with a fundamental problem like this is a really good start. Hamza and Jonas's answers clearly cover the original question quite well. I would like to offer some unsolicited advice on where to take it from here in the hopes that it will be helpful.

Once you have the base recursive form you can turn it into idiomatic Clojure generally by:

1) use tail recursive forms when you can (you already did this)
2) replace direct recursion with the recur call to keep from blowing the stack. (starting with Hamza's working answer)

(defn my-even? [coll]
   (if-let [[first & rest] coll]
    (if (= (mod first 2) 0)
      (cons first (my-even? rest))
      (recur rest))))

the recur causes the compiler to jump to the start of the stack frame instead of allocating a new one. without this it will blow the stack.

3) in many cases you can eliminate the (defn [] ... (recur)) pattern with a higher order function like map, reduce, filter, for, etc. In this excercise I see you are trying to not use filter or even, so obviously you could write my-filter and my-even and that would be ok ;)

4) extract the divisible parts, (building a list, choosing what to include) into reusable functions and upload any that are generally useful to a clojure contrib project :)

5) think very carefully should you find yourself using (lazy-seq ...) as there is a good chance you are re-inventing the wheel.

木落 2024-12-14 13:11:32

这是另一个不需要解构的解决方案,只需要基本的 lisp 和类似方案的函数。

(defn my-even [ilist]                                                                                                                                                                                                                       
  (cond (empty? ilist) '() ;; base case                                                                                                                                                                                                               
        (= (mod (first ilist) 2) 0)                                                                                                                                                                                                         
        (cons (first ilist) (my-even (next ilist)))                                                                                                                                                                                         
        :else (my-even (next ilist))))

Here is another solution that does not require destructuring, only basic lisp and scheme-like functions.

(defn my-even [ilist]                                                                                                                                                                                                                       
  (cond (empty? ilist) '() ;; base case                                                                                                                                                                                                               
        (= (mod (first ilist) 2) 0)                                                                                                                                                                                                         
        (cons (first ilist) (my-even (next ilist)))                                                                                                                                                                                         
        :else (my-even (next ilist))))
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文