【问题标题】:What is the "|>" symbol's purpose in Elixir?Elixir 中“|>”符号的用途是什么?
【发布时间】:2015-10-23 16:24:13
【问题描述】:

我搜索了 Elixir 和 Phoenix 文档,以及其他一些网站,例如 Learn Elixir,但没有成功。这是它的样子:

defp update_positions(item_ids) do
  item_ids = String.split(item_ids, ",")
                    |> Enum.map fn item_id -> String.to_integer(item_id) end

  items = Repo.all(Item |> where([item], item.id in array(^item_ids, :integer)))
  item_hash = Enum.reduce items, %{}, fn item, map -> Map.put(map, item.id, item) end

  item_ids
    |> Stream.with_index
    |> Enum.each fn {item_id, index} ->
      item = item_hash[item_id]
      Repo.update(%{item | position: index + 1})
    end
end

起初我以为它只是一个续行符号,以保持代码的可读性,但上面的 Item |> where 行表明并非如此。是列表推导还是指定输入类型的东西?

【问题讨论】:

标签: elixir


【解决方案1】:

我将从我的 Elixir Express 研讨会材料中复制: https://github.com/chrismccord/elixir_express/blob/master/basics/06_pipeline_operator.md

管道运算符

Elixir 中最简单但最有效的功能之一是管道操作符。管道运算符解决了许多函数式语言在组合一系列转换时面临的问题,其中一个函数的输出需要作为输入传递给另一个函数。这需要反向阅读解决方案以了解正在执行的操作,这会妨碍可读性并掩盖代码的真实意图。 Elixir 优雅地解决了这个问题,它允许将函数的输出管道 作为另一个函数的输入的第一个参数。在编译时,功能层次结构被转换为嵌套的“向后”变体,否则将需要这些变体。

iex(1)> "Hello" |> IO.puts
Hello
:ok
iex(2)> [3, 6, 9] |> Enum.map(fn x -> x * 2 end) |> Enum.at(2)
18

要掌握管道提供的完整实用程序,请考虑一个从 API 获取新消息并将结果保存到数据库的模块。步骤顺序是:

  • 通过授权用户令牌查找账户
  • 使用授权帐户从 API 获取新消息
  • 将 JSON 响应转换为消息的关键字列表
  • 将所有新消息保存到数据库中

没有管道:

defmodule MessageService do
  ...
  def import_new_messages(user_token) do
    Enum.each(
      parse_json_to_message_list(
        fetch(find_user_by_token(user_token), "/messages/unread")
    ), &save_message(&1))
  end
  ...
end

适当的命名和缩进有助于前一个块的可读性,但如果不先花点时间从内到外分解步骤以掌握对数据流的理解,其意图不会立即显现。

现在考虑管道操作符的这一系列步骤:

有管道

defmodule MessageService do
  ...
  def import_new_messages(user_token) do
    user_token
    |> find_user_by_token
    |> fetch("/messages/unread")
    |> parse_json_to_message_list
    |> Enum.each(&save_message(&1))
  end
    ...
end

将每个步骤的结果作为第一个参数传递给下一个允许将程序编写为一系列转换,任何读者都可以立即阅读和理解,而无需花费额外的精力来解开函数,如第一个解决方案。

Elixir 标准库侧重于将函数的主题作为第一个参数,帮助和鼓励管道的自然使用。

【讨论】:

    猜你喜欢
    • 2010-11-05
    • 2011-03-28
    • 2013-03-10
    • 1970-01-01
    • 1970-01-01
    • 2022-04-11
    • 2021-10-09
    相关资源
    最近更新 更多