这是带有测试的代码示例,其中有一个函数可以检查传入的值是否在允许的值集中,如果不是,则引发异常,但是如果传入的值为nil或空白字符串,它只返回false。这里的想法是,任何一种空白值都意味着没有价值。如果存在与有效值之一不匹配的非空白值,那么我们确实要引发异常,因为该值无效。还要想象这个值来自命令行参数或Phoenix请求参数,在这里我们不能将输入值控制为nil,我们必须检查一个空值,nil,一个空字符串或仅包含一个字符串的所有排列。空格。
ExUnit.start()
defmodule ValidColor do
@valid_colors MapSet.new(~w[red green blue])
def valid?(color) do
cond do
blank?(color) -> false
MapSet.member?(@valid_colors, color) -> true
true -> raise "invalid color"
end
end
defp blank?(value) do
case value do
nil -> true
v when is_binary(v) -> v =~ ~r/\A\s*\z/
_ -> false
end
end
end
defmodule ValidColorTest do
use ExUnit.Case, async: true
test "nil" do
refute ValidColor.valid?(nil)
end
test "empty string" do
refute ValidColor.valid?("")
end
test "string with only blank characters" do
refute ValidColor.valid?(" ")
end
test "invalid color" do
assert_raise RuntimeError, "invalid color", fn ->
ValidColor.valid?("yellow")
end
end
test "valid color" do
assert ValidColor.valid?("red")
end
end
Run Code Online (Sandbox Code Playgroud)
blank?就像我在本示例中所做的那样,当辅助函数有用时,似乎是这种情况。似乎有药剂程序员之间的感情,这种类型的helper方法是不必要的,可以用模式匹配来完成。
您如何仅通过模式匹配而不是blank?辅助函数来实现这样的功能?
尽管此处给出的所有答案在某种程度上都是正确的,但它们在语义上并不完美。您实际上想要的是将其nil视为空字符串并拒绝它。做到简单:
defp blank?(str_or_nil),
do: "" == str_or_nil |> to_string() |> String.trim()
Run Code Online (Sandbox Code Playgroud)
请注意,该解决方案与到目前为止提供的其他解决方案不同,它适用于所有空格,在UTF-8规范中定义为空格。
Elixir 函数可以有多个函数头。有了这个,创建一个辅助函数就变得非常简单了blank?/1。
defp blank?(nil), do: false
defp blank?(""), do: false
defp blank?(_), do: true
Run Code Online (Sandbox Code Playgroud)