Elixir:如果没有语法糖,多生成器列表理解会是什么样子?

Elixir: What does a multiple-generator list comprehension look like without the syntax sugar?

我正在尝试了解 Elixir 中的列表理解。

我正在查看的示例是从 this answer.

生成字符串的排列
def shuffle([], _), do: [[]]
def shuffle(_,  0), do: [[]]
def shuffle(list, i) do
  for x <- list, y <- shuffle(list, i-1), do: [x|y]
end

在没有理解的情况下重写这个双生成器理解看起来如何?我做了一个 attempt to implement the algorithm myself,但我的实现是附加到列表中,而不是像在理解中那样放在前面。我想在没有理解但具有相同行为的情况下编写算法。

没有过滤器的理解可以转换为 Enum.flat_mapEnum.map 的序列。具体来说,除最后一个以外的所有内容都将变为 flat_map,最后一个将变为 map。这是您的代码的翻译:

list
|> Enum.flat_map(fn x ->
  shuffle(list, i - 1)
  |> Enum.map(fn y ->
    [x | y]
  end)
end)

我用 A.shuffle([1, 2, 3, 4, 5], 2) 进行了测试,输出看起来与该问题中的原始代码相同。

运行 Dogbert 将 flat_map 替换为 map 的示例确实帮助我了解了发生了什么:

iex(1)> Permute.shuffle(~w(A B C), 3)
[
  [
    ["A", ["A", ["A"]], ["A", ["B"]], ["A", ["C"]]],
    ["A", ["B", ["A"]], ["B", ["B"]], ["B", ["C"]]],
    ["A", ["C", ["A"]], ["C", ["B"]], ["C", ["C"]]]
  ],
  [
    ["B", ["A", ["A"]], ["A", ["B"]], ["A", ["C"]]],
    ["B", ["B", ["A"]], ["B", ["B"]], ["B", ["C"]]],
    ["B", ["C", ["A"]], ["C", ["B"]], ["C", ["C"]]]
  ],
  [
    ["C", ["A", ["A"]], ["A", ["B"]], ["A", ["C"]]],
    ["C", ["B", ["A"]], ["B", ["B"]], ["B", ["C"]]],
    ["C", ["C", ["A"]], ["C", ["B"]], ["C", ["C"]]]
  ]
]