读取文本文件时的Clojure异常

mon*_*nny 0 clojure sequence

我只是想读一个标准的linux'/ etc/passwd'文件:拆分成记录.这似乎工作(所有行都回显到终端)但最后抛出一个异常?(见下文)

这项计划有什么用?

(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
Run Code Online (Sandbox Code Playgroud)

Kyl*_*ton 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)))))
Run Code Online (Sandbox Code Playgroud)

在你的程序中,你正在使用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")
Run Code Online (Sandbox Code Playgroud)

上面的代码运行,打印出为密码文件的每一行创建的结构.