elixir - 为什么在解析选项映射输入时使用双感叹号 (!!)?
问题描述
例如,在ExUnit.Case.__using__/1
宏中:
defmacro __using__(opts) do
# ...
quote do
async = !!unquote(opts)[:async]
# ...
end
# ...
end
where是ing:async
时的布尔选项。use
ExUnit.Case
defmodule AssertionTest do
use ExUnit.Case, async: true
test "always pass" do
assert true
end
end
解决方案
这意味着两次否定该语句(Kernel.!/1
)。Credo
在的文档中找到了关于为什么这样做的最佳描述:
代码中的双重否定会掩盖参数的原始值。
# NOT preferred !!var
这将返回
false
和,以及false
其他任何东西。起初,这似乎是一个非常聪明的速记,可以将任何真实的东西投射到 和任何不真实的东西到。但在大多数情况下,您希望明确输入参数(因为更容易推理边缘情况、代码路径和测试)。nil
true
true
false
另外:
nil
并且false
确实意味着两个不同的东西。但是,您需要这种灵活性的场景是解析外部数据,例如第三方 JSON-API,其中有时有时会出现值
null
,false
并且您希望在将其传递到程序中之前对其进行规范化。在这些情况下,最好通过引入辅助函数来明确强制转换:# preferred defp present?(nil), do: false defp present?(false), do: false defp present?(_), do: true
这使您的代码比依赖
!!
.
在问题的示例中,这是必要的,因为如果该:async
选项不存在,那么获取该键将导致nil
,但需要将其转换false
为以后仅查找布尔值的检查。
推荐阅读
- r - R中的ggplot2:为什么箱形图填充颜色很苍白?
- spring - Spring Kafka bean 配置 - 为什么调用 bean 方法而不是 autowire?
- javascript - 限制 Javascript 执行数量 +/-
- discord - discord.py 上的意外缩进
- r - dplyr 可以从 as.character 字符串中删除所有点吗?
- java - 如何将同义词添加到 Java 中的 switch 语句?
- package - 当 nuget.config 中的自定义包文件夹时,repositoryPath 不起作用
- javascript - Animate.css 承诺有时不会在动画结束后清理类
- node.js - 使用 Mongoose 在 MongoDB 上避免重复
- flutter - 无状态小部件列固定白色