2024 Clojure状态调查!中分享您的想法。

欢迎!有关如何工作的更多信息,请参阅关于页面。

0
编译器

嗨!
我的clojure项目中包含两个文件。
第一个文件(db.clj)从txt文件中读取数据并存储到向量列表中,第二个文件(menu.clj)显示带有多个选项的菜单。
我的条件起作用了:表格按预期显示,但我在最后遇到一个难以看懂的错误,应用程序停止运行。
详细信息
db.clj

(ns db)    
(defn load-data
  [filename]
  (with-open [rdr (io/reader filename)]
    ;; https://docs.clojure.org/clojure.core/doall
    (doall
      (for [line (line-seq rdr)
            :let [[id & data] (clojure.string/split line #"\|")]]
        [(Integer/parseInt id)
         data]))))

menu.clj

(ns menu
  (:require [db])
  )


(def customers (db/load-data "cust.txt"))
(def products (db/load-data "prod.txt"))

(def input_ 0) ; initialize input   

(defn menu
  []
  (if (not= input_ "6")
    (do
      (newline) ; insert a new line
      (println " ** MENU ** ") ; display menu
      (println "
1. Display Customer Table
2. Display Product Table
3. Display Sales Table
4. Total Sales for Customer
5. Total Count for Product
6. Exit")
      (println "Enter an option > ")
      (flush)
      (def input_ (read-line)) ; put the input in input_ variable
      (cond
        (= input_ "1") 
          ((println "Table of customers: ")
          ; run >> every item in a newline
          (run! println (db/load-data "cust.txt")))
        (= input_ "2") 
          ((println "Table of products: ")
          ; run >> every item in a newline
          (run! println (db/load-data "prod.txt")))
        :else (println "Option not handled!")
        )
      ;(println (str "The option entered is: \"" input_ "\""))
      (menu))
    (println "Goodbye!") ; If user prompts 6
    ))

控制台

    ** MENU ** 

1. Display Customer Table
2. Display Product Table
3. Display Sales Table
4. Total Sales for Customer
5. Total Count for Product
6. Exit
Enter an option > 
2
Table of products: 
[1 (shoes 14.96)]
[2 (milk 1.98)]
[3 (jam 2.99)]
[4 (gum 1.25)]
[5 (eggs 2.98)]
[6 (jacket 42.99)]
Syntax error (NullPointerException) compiling at (menu.clj:42:1).
null

Full report at:
/tmp/clojure-4521524603536338044.edn

谢谢!

1 个答案

+2

被选中
 
最佳答案
  1. 您应该检查并包含在 /tmp/clojure-4521524603536338044.edn (文件路径在错误消息中) 中的堆栈跟踪。

  2. 问题可能出在 cond 表达式中。

(cond
     (= input_ "1") 
     ((println "Table of customers: ")
     (run! println (load-data "cust.txt")))) 

如果 input_ 是 "1",则运行子句 ((println "表单 customers: ") (run! println (load-data "cust.txt")))。如果我们缓慢展开括号,就变成了

(nil nil)

(println 的结果是 nil),Clojure 将其解释为函数调用,并使用 1 个参数执行 nil。由于 nil 不是一个函数,它抛出了异常。尽管如此,我在 Clojure 1.11.1 中运行了这段代码,却得到了一个略微不同的错误信息。

修复方法是,在 cond 的打印语句周围加上 `(do ...)` 循环。

  1. 看起来你正在学习 Clojure。作为一个建议,这门语言设计时要使用 (let) 而不是 (def input_ (readline)),以及使用 recur 而不是递归调用 menu。你在找到这里的 cond 函数方面做得很好。
by
感谢!然而,(do ...) 并没有解决这个问题。我仍然遇到了相同的空指针错误...
by
你可能打错了字母。这个是我能工作的代码

   (ns menu
   (:require [db])
   )
    
   (def customers (db/load-data "cust.txt"))
   (def products (db/load-data "prod.txt"))
    
   (defn menu
   []
   (newline) ; 插入新行
   (println " ** MENU ** ") ; 显示菜单
   (println "
   1. 显示客户表
   2. 显示产品表
   3. 显示销售表
   4. 客户总销售金额
   5. 产品总数量
   6. 退出")
   (println "Enter an option > ")
   (flush)
   (let [input_ (read-line)] ; 把输入放到 input_ 变量中
  .SQLException) (cond
   (do (println "客户表: ")
SQLException) (; run>>在每行运行每个项目
   (run! println (db/load-data "cust.txt"))
SQLException) (; recur)
    
   (do (println "产品表: ")
SQLException) (; run>>在每行运行每个项目
   (run! println (db/load-data "prod.txt"))
SQLException) (; recur)
    
          (println "再见!") ; 如果用户输入6
    
          否则
          ((println "未处理的选项!"))))

在声明`db`命名空间时,还需要包含`(:require [clojure.java.io :as io])`。
...