Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
If statement Clojure中的简单流控制和变量绑定_If Statement_Clojure_Functional Programming_Imperative - Fatal编程技术网

If statement Clojure中的简单流控制和变量绑定

If statement Clojure中的简单流控制和变量绑定,if-statement,clojure,functional-programming,imperative,If Statement,Clojure,Functional Programming,Imperative,我正在学习Clojure并编写一个简单的文件解析脚本 我有一个以下格式的文件: pattern1 pattern2 pattern3 pattern1 pattern2 ... 其中每行都有一些我提取的值(数字) 例如,如果我用Java编写这篇文章,我会做类似的事情: Map<String, Integer> parse(String line) { //using Optional in this toy example, but could be an empty ma

我正在学习Clojure并编写一个简单的文件解析脚本

我有一个以下格式的文件:

pattern1
pattern2
pattern3
pattern1
pattern2
...
其中每行都有一些我提取的值(数字)

例如,如果我用Java编写这篇文章,我会做类似的事情:

Map<String, Integer> parse(String line) {
    //using Optional in this toy example, but could be an empty map or something else to
    //signal if first one was actually matched and the values are there
    Optional<Map<String, Integer>> firstMatched = matchFirst(line);
    if (firstMatched.isPresent()) {
        return firstMatched.get();
    }
    //...do the same for 2 remaining patterns
    //...
}
我也可以使用,但这将是大量的嵌套,因为有3种不同的选择。想象一下7种不同的图案会是什么样子


有什么建议吗?显然,Java解决方案是必不可少的,我可以随时“返回”,那么Clojure/FP如何处理这个简单的分支呢

我将使用一些简单的函数返回第一个匹配的模式,过滤模式seq:

(defn first-match [patterns]
  (fn [line]
    (some #(re-find % line) patterns)))
此函数返回函数,该函数将返回第一个匹配项,测试行:

user> (def mat (first-match [#"(asd)" #"(fgh)" #"aaa(.+?)aaa"]))
#'user/mat

user> (mat "aaaxxxaaa")
;;=> ["aaaxxxaaa" "xxx"]

user> (mat "nomatch")
;;=> nil
否则,您可以使用一些简单的宏。也许是这样:

(defmacro when-cond [& conds]
  (when (seq conds)
    `(if-let [x# ~(first conds)]
       x#
       (when-cond ~@(rest conds)))))

user> 
(let [line "somethingaaa"]
  (when-cond
    (re-find #"something" line)
    (re-find #"abc(.*?)def" line)))
;;=> "something"
对于前面的示例,它将扩展到类似这样的内容(示意图)

更多示例:

user> 
(let [line "nomatch"]
  (when-cond
    (re-find #"something" line)
    (re-find #"abc(.*?)def" line)))
;;=> nil

user> 
(let [line "abcxxxxxxdef"]
  (when-cond
    (re-find #"something" line)
    (re-find #"abc(.*?)def" line)))
;;=> ["abcxxxxxxdef" "xxxxxx"]

我将使用一些简单的函数返回第一个匹配的模式,过滤模式seq:

(defn first-match [patterns]
  (fn [line]
    (some #(re-find % line) patterns)))
此函数返回函数,该函数将返回第一个匹配项,测试行:

user> (def mat (first-match [#"(asd)" #"(fgh)" #"aaa(.+?)aaa"]))
#'user/mat

user> (mat "aaaxxxaaa")
;;=> ["aaaxxxaaa" "xxx"]

user> (mat "nomatch")
;;=> nil
否则,您可以使用一些简单的宏。也许是这样:

(defmacro when-cond [& conds]
  (when (seq conds)
    `(if-let [x# ~(first conds)]
       x#
       (when-cond ~@(rest conds)))))

user> 
(let [line "somethingaaa"]
  (when-cond
    (re-find #"something" line)
    (re-find #"abc(.*?)def" line)))
;;=> "something"
对于前面的示例,它将扩展到类似这样的内容(示意图)

更多示例:

user> 
(let [line "nomatch"]
  (when-cond
    (re-find #"something" line)
    (re-find #"abc(.*?)def" line)))
;;=> nil

user> 
(let [line "abcxxxxxxdef"]
  (when-cond
    (re-find #"something" line)
    (re-find #"abc(.*?)def" line)))
;;=> ["abcxxxxxxdef" "xxxxxx"]

给出一些示例数据:

(ns tst.demo.core
  (:use demo.core tupelo.core tupelo.test)
  (:require
    [clojure.string :as str]
    [tupelo.string :as ts]
    [tupelo.parse :as parse]))

(def data-str "
  fred123 1 2 3
  fred456   4 5    6
  wilma12  1.2
  wilma34 3.4
  barney1 1
  barney2 2
  ")
然后,您可以为每种类型的数据定义解析函数:

(defn fred-parser
  [line]
  (let [tokens        (str/split line #"\p{Blank}+")
        root          (first tokens)
        details       (rest tokens)
        parsed-root   (re-find #"fred\n*" root)
        parsed-params (mapv parse/parse-long details)
        result        {:root parsed-root :params parsed-params}]
    result))

(defn wilma-parser
  [line]
  (let [tokens        (str/split line #"\p{Blank}+")
        root          (first tokens)
        details       (rest tokens)
        parsed-root   (re-find #"wilma\n*" root)
        parsed-params (mapv parse/parse-double details)
        result        {:root parsed-root :params parsed-params}]
    result))
我将从模式映射到解析函数:

(def pattern->parser
  {#"fred\d*"  fred-parser
   #"wilma\d*" wilma-parser
   })
以及一些函数,用于为每行(已清理)数据找到正确的解析器:

请注意,不匹配的行返回nil。您可能希望针对问题抛出异常,或者至少过滤掉
nil
值。现在您只会收到一条打印错误消息:

-------------------------------
   Clojure 1.10.1    Java 14
-------------------------------

Testing tst.demo.core
:no-match-found "barney1 1"
:no-match-found "barney2 2"

Ran 2 tests containing 1 assertions.
0 failures, 0 errors.

更多文档和。

给出了一些示例数据:

(ns tst.demo.core
  (:use demo.core tupelo.core tupelo.test)
  (:require
    [clojure.string :as str]
    [tupelo.string :as ts]
    [tupelo.parse :as parse]))

(def data-str "
  fred123 1 2 3
  fred456   4 5    6
  wilma12  1.2
  wilma34 3.4
  barney1 1
  barney2 2
  ")
然后,您可以为每种类型的数据定义解析函数:

(defn fred-parser
  [line]
  (let [tokens        (str/split line #"\p{Blank}+")
        root          (first tokens)
        details       (rest tokens)
        parsed-root   (re-find #"fred\n*" root)
        parsed-params (mapv parse/parse-long details)
        result        {:root parsed-root :params parsed-params}]
    result))

(defn wilma-parser
  [line]
  (let [tokens        (str/split line #"\p{Blank}+")
        root          (first tokens)
        details       (rest tokens)
        parsed-root   (re-find #"wilma\n*" root)
        parsed-params (mapv parse/parse-double details)
        result        {:root parsed-root :params parsed-params}]
    result))
我将从模式映射到解析函数:

(def pattern->parser
  {#"fred\d*"  fred-parser
   #"wilma\d*" wilma-parser
   })
以及一些函数,用于为每行(已清理)数据找到正确的解析器:

请注意,不匹配的行返回nil。您可能希望针对问题抛出异常,或者至少过滤掉
nil
值。现在您只会收到一条打印错误消息:

-------------------------------
   Clojure 1.10.1    Java 14
-------------------------------

Testing tst.demo.core
:no-match-found "barney1 1"
:no-match-found "barney2 2"

Ran 2 tests containing 1 assertions.
0 failures, 0 errors.

更多文档和信息。

很好!返回第一个匹配项的函数是一种非常简单的方法,filly觉得我没有想到:)而带有宏的函数看起来很整洁,仍在学习中,因此我需要对其进行更多的剖析,即正确理解宏。谢谢!美好的返回第一个匹配项的函数是一种非常简单的方法,filly觉得我没有想到:)而带有宏的函数看起来很整洁,仍在学习中,因此我需要对其进行更多的剖析,即正确理解宏。谢谢!康普行吗?康普行吗?太棒了!我从这两个答案中学到了很多。尽管我对Clojure完全是新手,但读起来还是很容易的(我想当你看到干净的代码时,其他语言通常也是这样)。谢谢你,艾伦!令人惊叹的!我从这两个答案中学到了很多。尽管我对Clojure完全是新手,但读起来还是很容易的(我想当你看到干净的代码时,其他语言通常也是这样)。谢谢你,艾伦!