如何自省Elixir模块中同元数不同守卫子句的同名函数?
查看Elixir同名同元数函数的守卫子句方法
我来给你分享几个实用的办法,帮你查看这类带守卫的函数子句,或者确认它们的存在:
方法一:用
Code.get_docs/2提取函数元数据
Elixir的Code模块自带的get_docs/2函数,能提取模块里函数的详细子句信息,包括守卫条件。你可以在IEx里直接执行:Code.get_docs(Test, :functions)执行后会返回一个列表,每个元素对应一个函数子句的详情。比如你的
Test.greet/1会返回类似这样的内容:[ {{:greet, 1}, 1, ["Hello, bar"], [when: name == "foo"]}, {{:greet, 1}, 4, ["Hello, #{name}"], []} ]这里的
[when: name == "foo"]就是第一个子句的守卫条件,第二个子句没有守卫,所以是空列表,一眼就能看清两个子句的差异。方法二:通过
:code.get_abstract_code/1解析底层代码结构
如果你需要更底层的代码细节,可以借助Erlang的:code模块获取模块的抽象代码,再解析函数子句:{:ok, {_module, abstract_code}} = :code.get_abstract_code(Test)之后你可以从
abstract_code里筛选出目标函数的子句,比如用这段代码定位greet/1:Enum.find(abstract_code, fn {:function, :greet, 1, clauses} -> clauses _ -> false end)得到的
clauses就是greet/1的所有子句,里面会明确包含每个子句的守卫定义,能直接看到when name == "foo"这样的条件。快速验证小技巧:通过调用函数间接确认
如果你只是想快速确认是否存在多个子句,不用直接看守卫的话,可以给函数传不同参数测试:Test.greet("foo") # 输出 Hello, bar Test.greet("baz") # 输出 Hello, baz不同的输出结果就能间接证明存在两个不同逻辑的子句,不过这个方法没法直接查看守卫条件。
内容的提问来源于stack exchange,提问作者intentionally-left-nil
相关产品推荐
相关产品推荐

