模式匹配Elixir、Haskell 等是谓词调度的一种有限形式吗?

问题描述

我是函数式编程的忠实粉丝,我确实了解模式匹配和多重分派,这就是我发现谓词分派的方式,并且一直想知道它是否与模式匹配有关。

我确实阅读了这个 SO 线程:What is Predicate Dispatch 但仍然无法得到有关模式匹配和谓词调度之间关系的答案。我相信模式匹配和谓词调度确实相似,如果不等价的话,但想听听一些意见。

考虑这个 Elixir 代码

block in invoke_with_call_chain' C:/Ruby266-x64/lib/ruby/2.6.0/monitor.rb:235:in 

看起来函数是在运行时根据输入参数的属性选择的,这正是谓词分派。 invoke_with_call_chain' C:/Ruby266-x64/lib/ruby/gems/2.6.0/gems/rake-13.0.3/lib/rake/task.rb:243:in 部分看起来类似于本文中提出的谓词分派方式:http://web.cs.ucla.edu/~todd/research/oopsla04.pdf

分享您对此事的了解/意见。

解决方法

我没听说过“谓词分派”,但我可以和你分享一些关于 Elixir 如何处理函数子句中模式匹配的见解。

Elixir 函数中的模式匹配有点像 Web 应用程序中的路由:函数被尝试按照列出的顺序,直到可以进行匹配,然后执行该函数。这意味着特定的匹配应该列在第一,而最不特定的(或全部)应该列在最后。事实上,如果您以一种无法访问的方式构造函数,如果您使用适当的 linter/语言服务器,您将看到警告。

例如,这些定义是有问题的:

def something(_) do
   # This would always match 
end

def something(%{foo: nil}) do
   # so this can never match; the previous function def is too broad
end

我们可以稍微重写您的示例以仅使用模式匹配(而不是使用模式匹配和保护):

def function(%{x: true} = struct) do
    # do something when x == true
end

def function(%{y: nil}) do
    # do something else when x != true AND y == nil
end

def function(struct) do
    # default case
end

编译器实际上将所有这些转换为一系列条件,但函数子句提供了很好的表达语法。