【问题标题】:Is pattern matching (Elixir, Haskell, etc) a limited form of predicate dispatch?模式匹配(Elixir、Haskell 等)是一种有限的谓词调度形式吗?
【发布时间】:2021-06-26 00:39:27
【问题描述】:

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

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

考虑一下这个 Elixir 代码:

def function(%{a_flag: True}=struct) do
    # do smth
end

def function(struct) when is_nil(struct.field) do
    # do smth else
end

def function(struct) do
    # default case
end

看起来函数是在运行时根据输入参数的属性选择的,这正是谓词调度的内容。 when 部分看起来类似于本文中提出的谓词调度方式:http://web.cs.ucla.edu/~todd/research/oopsla04.pdf

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

【问题讨论】:

  • def function(%{a_flag = True}=struct) 首先甚至不是有效的elixir 代码。
  • @AlekseiMatiushkin 对不起,小错字,应该是def function(%{a_flag: True}=struct)

标签: oop functional-programming pattern-matching elixir multiple-dispatch


【解决方案1】:

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

Elixir 函数中的模式匹配有点像 Web 应用程序中的路由:按列出的顺序尝试函数,直到可以匹配,然后执行该函数。这意味着特定的匹配应该列在第一个,而最不特定(或包罗万象)应该列在最后。事实上,如果您使用合适的 linter/language-server,如果您以无法访问的方式构造函数,您会看到警告。

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

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

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

【讨论】:

  • 谢谢@Everett,即使我不是在寻找模式匹配如何工作的解释,而是它是否等同于谓词调度的概念。
猜你喜欢
  • 2014-07-26
  • 1970-01-01
  • 2017-05-08
  • 1970-01-01
  • 1970-01-01
  • 2017-10-12
  • 1970-01-01
  • 2021-03-12
  • 1970-01-01
相关资源
最近更新 更多