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 (/tmp/clojure-4521524603536338044.edn文件路径在错误信息中)中的堆栈跟踪。

  2. 问题可能出在cond语句中

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

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

(nil nil)

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

修复方法是将 (do ...) 循环放在cond语句中的打印操作周围。

  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_ 变量中
        (cond
          (= input_ "1")
          (do (println "客户表:")
                                                 运行 >>> 每个元素换行输出
              (run! println (db/load-data "cust.txt"))
             (recur))
    
          (= input_ "2")
          (do (println "产品表:")
                                                 运行 >>> 每个元素换行输出
              (run! println (db/load-data "prod.txt"))
             (recur))
    
          (= input_ "6")
          (println "再见!") ; 如果用户选择6
    
          :else
          (println "未处理选项!"))))

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