Elixir有一个著名的管道运算符(|>),它可以把多个函数组合起来按顺序执行,从而大幅提高代码的可读性。其他函数式语言有专门用来组合函数的高阶函数。Elixir虽然没有这样的高阶函数,但是它提供了管道运算符。本节将讲解管道运算符的用法及优势。
首先,让我们创建一个HighOrderFunctions模块,看看将两个函数组合起来使用的普通方法:
函数compose/2接收两个函数,并创建了一个接收单个参数的新函数。这个新函数使用给定的参数调用g函数,然后用返回结果调用f函数。这里我们将两个函数包装成了一个函数。我们可以像这样使用它:
我们传递了两个函数给compose/2。这两个函数组合成了一个函数,使用起来很方便。但是这种组合函数的方式可读性比较差。更好的办法是使用管道运算符。让我们用管道运算符重构上面的代码:
优雅吧?当出现在|>后面的函数被调用时,Elixir会将前一个表达式的计算结果作为参数传给它。我们用分解版本看看每一步发生了什么:
Elixir接受|>前面表达式的值,并将其作为第一个参数传递给下一个函数调用。让我们创建一个更大的函数,它接收文本并将每个单词的首字母变成大写。我们将这个函数放在MyString模块里:
在讲解细节之前,让我们看看它的工作情况:(www.xing528.com)
函数首先将文本拆分,生成单词列表;然后将每个单词的首字母变成大写;最后再把它们连成一个用空格分隔的句子。注意,我们把每一步的结果都放在一个变量中,以说明操作步骤。我们也可以去掉这些变量,那么组合函数的方法就是直接在函数调用中使用它们:
这种代码的可读性比较差。数据转换的第一步出现在函数中间,要理解执行顺序,你必须来回读代码,这是违反直觉的,也难以维护。让我们用管道运算符重写capitalize_words/1:
漂亮吧!代码的顺序与实际转换的顺序完全相同。管道运算符非常适合用来组合一系列函数。让我们看看每一步的细节,在IEx中输入:
Elixir将“a whole new world”字符串传递给String.split/1。注意,对于简单的函数调用,最好避免使用管道,因为String.split("a whole new world")具有更好的可读性,尤其是要传递多个参数时。现在让我们再添加一个函数调用:
拆分字符串后,管道的下一个函数是Enum.map/2。该函数有两个参数,第一个参数由前一个表达式提供。我们的工作是给出第二个参数,即函数String.capitalize/1。接下来,还可以给capitalize_words/1函数添加辅助函数:
辅助函数可以更清楚地说明代码的含义。capitalize_all/1接收单词列表并将所有单词的首字母变成大写。join_with_whitespace/1接收单词列表并返回用空格连接的句子。使用有意义的名称创建小函数是一个好习惯。管道操作符不仅可用来组合函数,还能提高代码的可读性。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。