使用命名参数管道进入案例

Pipe into case with named parameter

通过管道传输到 case 语句并使用管道参数之前的语法是什么?我似乎无法在任何地方找到它。我有两个“想法”,但我不知道哪个是正确的。

something
|> do_something()
|> case do
  nil -> {:error, "ITS REAL NIL"}
  %MyStruct{} -> Methods.next_something(&1.attrib)
  _ -> {:error, "NAH BRUH. THE WEIRD HAPPENED."}
something
|> do_something()
|> case do
  nil -> {:error, "ITS REAL NIL"}
  struct = %MyStruct{} -> Methods.next_something(struct.attrib)
  _ -> {:error, "NAH BRUH. THE WEIRD HAPPENED."}

这应该有效...

something
|> do_something()
|> case do
  nil -> {:error, "ITS REAL NIL"}
  %MyStruct{atrib: atrib} -> Methods.next_something(atrib)
  _ -> {:error, "NAH BRUH. THE WEIRD HAPPENED."}
end

管道与问题无关。这将起作用:

case %{foo: "bar"} do
  map = %{} -> {:success, map.foo}
end

但是,将要在右侧使用的值与左侧的值相匹配是更清晰、更好的做法:

case %{foo: "bar"} do
  %{foo: foo} -> {:success, foo}
end

问题本身揭示了您对 do 块的基本误解。

Kernel.SpecialForms.case/2接受两个参数:conditionclausesdo ... end 语法只不过是 do: ... 关键字列表参数的语法糖,由编译器内联。

当你有一个 arity 2 的函数时,你会毫不犹豫地使用管道运算符将第一个参数传递到那里,而第二个保持不变。 do ... end block 就是第二个参数。

考虑以下代码:

case :ok, do: (:ok -> 42; _ -> nil)    
#⇒ 42

以上等同于

case(:ok, [do: (:ok -> 42; _ -> nil)])
#⇒ 42

现在我们显然看到了两个参数,第一个是 term() 类型,第二个是关键字列表。就是这样。

因此不能有任何捕获参数:我们没有捕获,我们有一个常规调用(对宏 case。)

也就是说,你的第二种方法是正确的。