我只是想读一个标准的linux' / etc / passwd' file:拆分成记录。 这似乎工作(所有行都回显到终端)但最后抛出一个异常? (见下文)
该计划的内容是什么?
(use 'clojure.java.io)
(use 'clojure.string)
(defn process_file[infile] (
(defstruct user :username
:password
:uid
:gid
:comment
:home_dir
:shell)
(def record_separator #":")
(with-open [rdr (reader infile)]
(doseq [line (line-seq rdr)]
(def fields (split line record_separator) )
(def user_record (apply struct user fields) )
(println (user_record :username) )
)
)
)
)
; main
(process_file "/etc/passwd")
[ after all the lines read have been output ]
Exception in thread "main" java.lang.ClassCastException: clojure.lang.PersistentStructMap$Def cannot be cast to clojure.lang.IFn
at clojure.lang.Var.fn(Var.java:392)
at clojure.lang.Var.invoke(Var.java:419)
at user$process_file.invoke(readfile.clj:15)
at user$eval14.invoke(readfile.clj:26)
at clojure.lang.Compiler.eval(Compiler.java:6514)
at clojure.lang.Compiler.load(Compiler.java:6955)
at clojure.lang.Compiler.loadFile(Compiler.java:6915)
at clojure.main$load_script.invoke(main.clj:283)
at clojure.main$script_opt.invoke(main.clj:343)
at clojure.main$main.doInvoke(main.clj:427)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.lang.Var.invoke(Var.java:415)
at clojure.lang.AFn.applyToHelper(AFn.java:161)
at clojure.lang.Var.applyTo(Var.java:532)
at clojure.main.main(main.java:37)
java version "1.7.0_21"
OpenJDK Runtime Environment (IcedTea 2.3.9) (7u21-2.3.9-1ubuntu1)
OpenJDK 64-Bit Server VM (build 23.7-b01, mixed mode)
Clojure 1.4.0
答案 0 :(得分:7)
你的整个函数体周围有一组额外的括号。删除它看起来如下(虽然我不建议这样编写代码,见下文):
(defn process_file[infile]
(defstruct user :username
:password
:uid
:gid
:comment
:home_dir
:shell)
(def record_separator #":")
(with-open [rdr (reader infile)]
(doseq [line (line-seq rdr)]
(def fields (split line record_separator))
(def user_record (apply struct user fields))
(println (user_record :username)))))
在你的程序中,你在一个函数中使用def
,这是不鼓励的。编写代码的一种更惯用的方法是使用命名空间,并在函数外部定义结构和记录分隔符,然后在函数中使用let
作为局部变量。以这种方式重新格式化代码如下所示:
(ns scratch
(:require
[clojure.java.io :as io]
[clojure.string :as string]))
(defstruct user-rec
:username
:password
:uid
:gid
:comment
:home-dir
:shell)
(def record-separator #":")
(defn process-file [fname]
(with-open [rdr (io/reader fname)]
(doseq [line (line-seq rdr)]
(let [fields (string/split line record-separator)
user (apply struct user-rec fields)]
(println (format "user: %s" user))))))
(process-file "/etc/passwd")
上面的代码运行,打印出为密码文件的每一行创建的结构。
答案 1 :(得分:4)
您的例外原因是defstruct
来电之前的额外括号。函数在表单中处于领先位置,因此编译器会尝试将defstruct
的结果强制转换为函数,因此异常。