用于在Clojure中将字符串转换为整数向量的函数解决方案

Aut*_*ton 3 eclipse string vector clojure

我已经成功编写了一个函数,它将空格分隔的整数字符串转换为Clojure中的整数向量,但由于我(非常)新的函数式语言,我担心我仍然在考虑程序性.

该函数用于split对字符串进行标记,然后迭代通过返回的向量,将标记单独转换为整数,然后将它们附加到新向量.我正在使用,read-string因为输入是自我提供的,我并不真正关心安全性.

    (defn parser [myStr]
        ;;counter
        (def i 0)
        ;;tokenizes string and returns vector of tokens
        (def buffer (clojure.string/split myStr #"\s"))
        ;;reads vector of strings as integers then appends them to a new vector x
        (def x (vector-of :int))
        (while ( < i (count buffer))
            (def x (conj x (read-string (nth buffer i)))) 
            (def i (inc i)))
        (println x))
Run Code Online (Sandbox Code Playgroud)

我的代码有效,但我担心通过改变状态并迭代缓冲向量,我有点作弊并坚持我的程序根源.

是否有更优雅或功能性的方法来解决这个问题?

Car*_*ate 6

这里有一些非常值得注意的事情:

  • 除非你有充分的理由def,defn否则不要在里面使用.这里的用例是不合理的.只需使用:let

    (defn parser [myStr]
      (let [i 0
            buffer (clojure.string/split myStr #"\s")
            x (vector-of :int)]
         ...)
    
    Run Code Online (Sandbox Code Playgroud)

    要查看区别是什么,运行您的函数,然后检查是什么i.def创建在函数退出后持久存在的全局变量,这会泄漏函数的状态并污染命名空间.

  • 你正在使用read-string解析.不要那样做.只需使用Java Long/parseLong.read-stringeval行为,从来没有好处滥用.您也可以使用clojure.edn/read-string哪些可以读取Clojure结构和文字,但不执行代码.

  • while当您真正使用loop或使用许多其他功能方法时,您正在使用副作用.@ xs0基本上是正确的.我把你的功能写成:

    (defn parser [myStr]
      ; The v in mapv means it returns a vector
      ; Just map returns a lazy seq
      (mapv #(Long/parseLong %) (clojure.string/split myStr #"\s"))
    
    Run Code Online (Sandbox Code Playgroud)

    遗憾的是Long/parseLong需要将函数包装在函数中,因为Java互操作方法不能像普通的Clojure函数一样使用.

    Long/parseLong如果您可以保证每个令牌split返回是可解析的,则只能安全使用.当然,如果没有这样的保证,你需要做一些错误处理,或者在尝试解析之前清理输入.