Gen*_*Hal 3 if-statement idiomatic clojure
我有一个Clojure函数,看起来像下面这样.
(defn calculate-stuff [data]
(if (some-simple-validation data)
(create-error data)
(let [foo (calculate-stuff-using data)]
(if (failed? foo)
(create-error foo)
(let [bar (calculate-more-stuff-using foo)]
(if (failed? bar)
(create-error bar)
(calculate-response bar)))))))
Run Code Online (Sandbox Code Playgroud)
哪个工作正常,但有点难以阅读,所以我想知道是否有更惯用的Clojure写作方式?
我考虑过制作some-simple-validation
,calculate-stuff-using
并calculate-more-stuff-using
抛出异常并使用try/catch块,但感觉就像使用控制流的异常一样,感觉不正确.
我不能让异常逃避这个功能,因为我正在使用它来映射一系列地图,我仍然想继续处理剩余部分.
我猜我所追求的是这样的?
(defn calculate-stuff [data]
(let-with-checking-function
[valid-data (some-simple-validation data)
foo (calculate-stuff-using valid-data)
bar (calculate-more-stuff-using foo)]
failed?) ; this function is used to check each variable
(create-error %) ; % is the variable that failed
(calculate-response bar)) ; all variables are OK
Run Code Online (Sandbox Code Playgroud)
谢谢!
如果验证失败指示错误情况,则异常(和try-catch块)可能是处理错误的最佳方式.特别是如果它不是"正常"的出现(即无效的cust-id等).
对于更"正常"但仍然"无效"的情况,您可以使用some->
(发音为"some-thread")来静静地压制"坏"情况.只需让验证器返回nil
错误数据,并some->
中止处理链:
(defn proc-num [n]
(when (number? n)
(println :proc-num n)
n))
(defn proc-int [n]
(when (int? n)
(println :proc-int n)
n))
(defn proc-odd [n]
(when (odd? n)
(println :proc-odd n)
n))
(defn proc-ten [n]
(when (< 10 n)
(println :proc-10 n)
n))
(defn process [arg]
(when (nil? arg)
(throw (ex-info "Cannot have nil data" {:arg arg})))
(some-> arg
proc-num
proc-int
proc-odd
proc-ten))
Run Code Online (Sandbox Code Playgroud)
结果:
(process :a) => nil
(process "foo") => nil
:proc-num 12
:proc-int 12
(process 12) => nil
:proc-num 13
:proc-int 13
:proc-odd 13
:proc-10 13
(process 13) => 13
(throws? (process nil)) => true
Run Code Online (Sandbox Code Playgroud)
说完这个,你现在nil
用来表示"数据验证失败",所以你不能拥有nil
数据.
使用nil
短路处理的特殊值可以起作用,但使用普通的异常可能更容易,特别是对于明显是"坏数据"的情况:
(defn parse-with-default [str-val default-val]
(try
(Long/parseLong str-val)
(catch Exception e
default-val))) ; default value
(parse-with-default "66-Six" 42) => 42
Run Code Online (Sandbox Code Playgroud)
我有一个小宏来自动化这个过程,称为with-exception-default
:
(defn proc-num [n]
(when-not (number? n)
(throw (IllegalArgumentException. "Not a number")))
n)
(defn proc-int [n]
(when-not (int? n)
(throw (IllegalArgumentException. "Not int")))
n)
(defn proc-odd [n]
(when-not (odd? n)
(throw (IllegalArgumentException. "Not odd")))
n)
(defn proc-ten [n]
(when-not (< 10 n)
(throw (IllegalArgumentException. "Not big enough")))
n)
(defn process [arg]
(with-exception-default 42 ; <= default value to return if anything fails
(-> arg
proc-num
proc-int
proc-odd
proc-ten)))
(process nil) => 42
(process :a) => 42
(process "foo") => 42
(process 12) => 42
(process 13) => 13
Run Code Online (Sandbox Code Playgroud)
这避免给予特殊含义nil
或任何其他"sentinal"值,并且Exception
用于在出现错误时改变控制流的正常目的.
归档时间: |
|
查看次数: |
673 次 |
最近记录: |