我想访问地图和记录中的值,当密钥不存在时抛出异常.这是我尝试过的.有更好的策略吗?
这不起作用,因为throw
每次评估:
(defn get-or-throw-1 [rec key]
(get rec key (throw (Exception. "No value."))))
Run Code Online (Sandbox Code Playgroud)
也许有一个使用宏的简单方法?嗯,这不是它; 它与第一个定义具有相同的问题,即使评估throw
发生在以后:
(defmacro get-or-throw-2 [rec key]
`(get ~rec ~key (throw (Exception. "No value."))))
Run Code Online (Sandbox Code Playgroud)
这个通过让get
返回一个(理论上)永远不会以任何其他方式生成的值来工作:
(defn get-or-throw-3 [rec key]
(let [not-found-thing :i_WoUlD_nEvEr_NaMe_SoMe_ThInG_tHiS_021138465079313
value (get rec key not-found-thing)]
(if (= value not-found-thing)
(throw (Exception. "No value."))
value)))
Run Code Online (Sandbox Code Playgroud)
我不想猜测哪些关键字或符号永远不会通过其他进程发生.(我可以用gensym
产生的特殊价值not-found-thing
,但我不明白为什么这会更好.我没有利用未发现-价值担心有人蓄意试图打败功能的目的地图或记录中的东西.)
有什么建议?
这是先决条件的意思.它们内置于语言中,应该用于输入验证(尽管如果前提条件对于特定情况不灵活,您也可以使用断言).
user> (defn strict-get
[place key]
{:pre [(contains? place key)]}
(get place key))
#'user/strict-get
user> (strict-get {:a 0 :b 1} :a)
0
user> (strict-get {:a 0 :b 1} :c)
AssertionError Assert failed: (contains? place key) user/eval6998/fn--6999/strict-get--7000 (form-init7226451188544039940.clj:1)
Run Code Online (Sandbox Code Playgroud)
这是什么样find
的功能是:(find m k)
回报nil
,如果没有被发现,或者[k v]
如果从一个映射k
到v
被发现.您可以随时区分这两者,而无需猜测地图中可能存在的内容.所以你可以写:
(defn strict-get [m k]
(if-let [[k v] (find m k)]
v
(throw (Exception. "Just leave me alone!"))))
Run Code Online (Sandbox Code Playgroud)
您可以使用命名空间限定的关键字,这可以减少意外使用关键字的机会:
(defn get-or-throw [coll key]
(let [result (get coll key ::not-found)]
(if (= result ::not-found)
(throw (Exception. "No value."))
result)))
Run Code Online (Sandbox Code Playgroud)
或者,您可以只使用contains?
:
(defn get-or-throw [coll key]
(if (contains? coll key)
(get coll key)
(throw (Exception. "No value."))))
Run Code Online (Sandbox Code Playgroud)
这应该是安全的,因为您的地图/记录应该是不可变的。
归档时间: |
|
查看次数: |
824 次 |
最近记录: |