首页 > 解决方案 > 为什么在解析选项映射输入时使用双感叹号 (!!)?

问题描述

例如,在ExUnit.Case.__using__/1宏中:

defmacro __using__(opts) do
  # ...
  quote do
    async = !!unquote(opts)[:async]
    # ...
  end
  # ...
end

where是ing:async时的布尔选项。useExUnit.Case

defmodule AssertionTest do
  use ExUnit.Case, async: true

  test "always pass" do
    assert true
  end
end

标签: elixir

解决方案


这意味着两次否定该语句(Kernel.!/1)。Credo在的文档中找到了关于为什么这样做的最佳描述:

代码中的双重否定会掩盖参数的原始值。

  # NOT preferred
  !!var

这将返回false和,以及false其他任何东西。起初,这似乎是一个非常聪明的速记,可以将任何真实的东西投射到 和任何不真实的东西到。但在大多数情况下,您希望明确输入参数(因为更容易推理边缘情况、代码路径和测试)。 niltruetruefalse

另外:nil并且false确实意味着两个不同的东西。

但是,您需要这种灵活性的场景是解析外部数据,例如第三方 JSON-API,其中有时有时会出现值nullfalse并且您希望在将其传递到程序中之前对其进行规范化。在这些情况下,最好通过引入辅助函数来明确强制转换:

  # preferred
  defp present?(nil), do: false
  defp present?(false), do: false
  defp present?(_), do: true

这使您的代码比依赖!!.

在问题的示例中,这是必要的,因为如果该:async选项不存在,那么获取该键将导致nil,但需要将其转换false为以后仅查找布尔值的检查。


推荐阅读