Elixir崇尚简洁,Unix的一个重要哲学就是管道操作符,Elxiir也完美的试用与函数。
通常而言,程序员把功能点写成一个个精巧的函数。然后通过函数的组合嵌套实现功能。
people = DB.find_customers
orders = Orders.for_customers(people)
tax = sales_tax(orders, 2013)
filing = prepare_filing(tax)
这样的面包黄油(Bread-and-butter)编程。我们还可以选择这样简写:
filing = prepare_filing(sales_tax(Orders.for_customers(DB.find_customers), 2013))
上面的代码一个函数的调用使用上一个函数的结果作为参数,就像小孩子吃蔬菜一样。不仅比较难读,而且如果你想知整个过程的顺序,不得不阅读里面的内容。
Elixir有一个更好的方式:
filing = DB.find_customers
|> Orders.for_customers
|> sales_tax(2013)
|> prepare_filing
|>
操作符会把左边表达式的结果当成参数传入右边的函数。第一个函数调用返回customers的列表,这个结果传给for_customers函数。for_customers调用的返回结果order,order作为第一个参数传给sales_tax。此时2013变成了第二个参数。
val |> f(a,b)
等价于 f(val,a,b)
list
|> sales_tax(2013)
|> prepare_filing
等价于 prepare_filing(sales_tax(list, 2013))
.
上面的例子,每一项我都单独的写了一行,这在Elixir已经不过时了。有逼格的方式是写成一行链式的效果:
iex> (1..10) |> Enum.map(&(&1*&1)) |> Enum.filter(&(&1 < 40))
[1, 4, 9, 16, 25, 36]
注意我使用&
语法糖来作为函数的缩写,同时也使用了管道操作符。
我再重复一次,你总是需要在管道符号内使用圆括号调用函数。管道符的好处是让你写的代码符合规范和有条理,简短而漂亮。例如sales-tax 的例子,你可以在纸上写下:
- 获取顾客列表
- 通过顾客列表生成一个订单列表
- 计算出租车的订单价值
- 准备出租车
从餐巾纸到代码规范,你只需要用|>来串联每一个函数的调用。
DB.find_customers # 获取顾客列表
|> Orders.for_customers # 通过顾客列表生成一个订单列表
|> sales_tax(2013) # 计算出租车的订单价值
|> prepare_filing # 准备出租车
编程是数据的转换,|>很好的体现了数据转换。之前Elixir管道一试就针对了一个具体问题做了实践。