gpt4 book ai didi

elixir - 带有 do-block 的关键字参数

转载 作者:行者123 更新时间:2023-12-02 06:50:06 24 4
gpt4 key购买 nike

我有一个看起来像这样的函数。

def test(options \\ []) do
# Fun stuff happens here :)
end

它接受多个(可选)关键字参数,包括 do:。我希望能够这样调用它。

test foo: 1 do
"Hello"
end

但是,这会产生错误。

** (UndefinedFunctionError) function Example.test/2 is undefined or private. Did you mean one of:

* test/0
* test/1

Example.test([foo: 1], [do: "Hello"])
(elixir) lib/code.ex:376: Code.require_file/2

从错误中可以看出,上面的语法被脱糖为两个单独的关键字列表。现在,我可以使用以下稍微不方便的语法来调用这个函数

Example.test foo: 1, do: (
"Hello"
)

但是除了在一个函数调用中提供其他关键字参数之外,有没有办法提供一个 do block ?

最佳答案

虽然@bla提供的答案在技术上是正确的(例如有效),但它几乎没有说明是什么和为什么。

首先,没有什么可以阻止您使用函数而不是宏来使用此语法,您只需要显式地将关键字参数与 do: 部分和其他任何内容分开即可:

defmodule Test do
# ⇓⇓⇓⇓⇓⇓⇓⇓⇓ HERE
def test(opts \\ [], do: block) do
IO.inspect(block)
end
end

Test.test foo: 1 do
"Hello"
end
#⇒ "Hello"

使用函数无法实现的是生成可执行的 block 。正如上面的示例所示,它将是静态的,因为函数是运行时公民。函数执行时的代码已经编译完毕,这意味着无法将代码传递给此 block 。也就是说, block 内容将在调用者上下文中、函数本身之前执行:

defmodule Test do
def test(opts \\ [], do: block) do
IO.puts "In test"
end
end

Test.test foo: 1 do
IO.puts "In do block"
end

#⇒ In do block
# In test

这通常不是您期望的 Elixir block 的工作方式。这就是宏出现的时候:宏是编译时公民。传递给宏的 do: 参数的 block 将作为 AST 注入(inject)到 Test.test/1 do block ,制作

defmodule Test do
defmacro test(opts \\ [], do: block) do
quote do
IO.puts "In test"
unquote(block)
end
end
end

defmodule TestOfTest do
require Test
def test_of_test do
Test.test foo: 1 do
IO.puts "In do block"
end
end
end

TestOfTest.test_of_test
#⇒ In test
# In do block
<小时/>

旁注:在评论中你说“我对将其变成宏没有任何疑虑。”这是完全错误的。函数和宏不可互换(尽管它们看起来像可以互换),它们是完全不同的东西。宏应该作为最后的手段使用。宏注入(inject) AST 就位。函数是 AST

关于elixir - 带有 do-block 的关键字参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51450902/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com