理解Erlang列表理解生成器

理解Erlang列表理解生成器,erlang,generator,list-comprehension,Erlang,Generator,List Comprehension,鉴于此功能: pretty_print(Folders, Depth) -> {CurrrentFolder, ListSubfolders} = Folders, SignTemp = lists:duplicate(Depth, "-"), case Depth of 0 -> Sign = SignTemp; _ -> Sign = "|

鉴于此功能:

pretty_print(Folders, Depth) ->
    
        {CurrrentFolder, ListSubfolders} = Folders,
        SignTemp = lists:duplicate(Depth, "-"),
        case Depth of
            0 -> Sign = SignTemp;
            _ -> Sign = "|" ++ SignTemp
        end,
    
        io:format("~s~s~n", [Sign, CurrrentFolder]),
        
        [pretty_print(Subfolder, Depth+1)|| Subfolder <- ListSubfolders].
例如,在这段代码中,通过深度控制另一个变量的行为:

case Depth of
    0 -> Sign = SignTemp;
    _ -> Sign = "|" ++ SignTemp
end,
有件事我不太明白

当函数到达目录的最后一个文件夹时会发生什么情况

?当列表压缩中的生成器为null或空时,Elrang中的递归函数会发生什么情况

当列表理解中的生成器为空时,则理解为空。不管它是否是递归的

那么当变量为空时,函数不会调用自身

没有任何东西可以控制这一行不会发生错误

  {CurrrentFolder, ListSubfolders} = Folders,
不,它只是假设调用者将给出一个与之匹配的参数(并且
ListSubfolders
是一个列表,其中的每个元素也与之匹配)。直接在头部匹配会更为惯用:

pretty_print({CurrrentFolder, ListSubfolders}, Depth) ->    
    SignTemp = lists:duplicate(Depth, "-"),
    ... %% the rest is the same
?当列表压缩中的生成器为null或空时,Elrang中的递归函数会发生什么情况

当列表理解中的生成器为空时,则理解为空。不管它是否是递归的

那么当变量为空时,函数不会调用自身

没有任何东西可以控制这一行不会发生错误

  {CurrrentFolder, ListSubfolders} = Folders,
不,它只是假设调用者将给出一个与之匹配的参数(并且
ListSubfolders
是一个列表,其中的每个元素也与之匹配)。直接在头部匹配会更为惯用:

pretty_print({CurrrentFolder, ListSubfolders}, Depth) ->    
    SignTemp = lists:duplicate(Depth, "-"),
    ... %% the rest is the same
Elrang中的递归函数在列表中时会发生什么情况 压缩生成器是否为空

易于测试:

-module(a).
-compile(export_all).

go(N) ->
    [go(X) || X <- [] ].
您希望以下各项的返回值是多少:

[ X+1 || X <- [] ]
然后执行:

[f(X) || X <- [] ]
[f(X)| | X
Elrang中的递归函数在列表中时会发生什么情况
压缩生成器是否为空

易于测试:

-module(a).
-compile(export_all).

go(N) ->
    [go(X) || X <- [] ].
您希望以下各项的返回值是多少:

[ X+1 || X <- [] ]
然后执行:

[f(X) || X <- [] ]

[f(X)| | X只是为了更加清晰。下面的代码不是为了控制而存在的-它们是'Just'因为对于根文件夹输入,我们不想在文件夹名称(化妆品)的前面加上“|”字符。因此,即使您将其更改为:
Sign=SignTemp
Sign=“|”++SignTemp
仅限,它不会更改逻辑

case Depth of
    0 -> Sign = SignTemp;
    _ -> Sign = "|" ++ SignTemp
end,
在前面的代码中,
文件夹
永远不会是
[]
,它的值至少为
{CurrentFolder,[]}
(可能是空列表的是
列表子文件夹
)。 由于下面的列表理解应用于
ListSubfolders
,因此是安全的,因为如果
ListSubfolders
[]
,则不会调用
pretty\u print

[pretty_print(Subfolder, Depth+1)|| Subfolder <- ListSubfolders].

[pretty_print(Subfolder,Depth+1)| | Subfolder只是为了增加清晰度。下面的代码不是为了控制而存在的-它们是'Just',因为对于根文件夹输入,我们不想在文件夹名称前面加“|”字符(化妆品)。因此,即使将其更改为:
Sign=SignTemp
Sign=“|”++SignTemp
,它也不会更改逻辑

case Depth of
    0 -> Sign = SignTemp;
    _ -> Sign = "|" ++ SignTemp
end,
在前面的代码中,
文件夹
永远不会是
[]
,它的值至少为
{CurrentFolder,[]}
(可能是空列表的是
列表子文件夹
)。 由于下面的列表理解应用于
ListSubfolders
,因此是安全的,因为如果
ListSubfolders
[]
,则不会调用
pretty\u print

[pretty_print(Subfolder, Depth+1)|| Subfolder <- ListSubfolders].

[pretty_print(Subfolder,Depth+1)| | Subfolder我绘制此图是为了说明列表理解是如何工作的,以及函数pretty_print的所有递归调用。

我画这个图是为了说明列表理解是如何工作的,函数的所有递归调用都是pretty\u print。

我明白这一点,但我还有更多的疑问。我想我必须从更基本的事情开始,一步一步来,因为有很多事情我不明白。例如:当我们到达一个没有更多文件夹的文件夹的末尾时,它会再次调用自己来探索另一个分支,这是什么原因我想解释一下上面的评论,为什么我被递归函数的迭代方法而不是递归方法弄糊涂了。最后,我理解了为什么可变深度的行为是这样的。另外,当它发现不包含子文件夹的文件夹时,它并没有阻止函数被调用.我只是在反复思考我已经理解了这一点,但我还有更多的疑问。我想我必须从更基本的事情开始,一步一步来,因为有很多事情我不理解。例如:当我们到达一个不包含更多文件夹的文件夹末尾时,它会再次调用自己的函数是什么为了探索另一个分支?我向自己解释了上面的评论,解释了为什么我被递归函数的迭代方法而不是递归方法弄糊涂了。最后,我理解了为什么变量深度的行为方式是这样的。另外,还因为它没有阻止函数在发现t时被调用hat不包含子文件夹。我只是在反复思考我认为您应该定义一些类似于pretty_print([],N)->…或使用某种案例文件夹[]但我明白这是没有必要的。我将开始学习更多的基本知识…用添加的解释更新评论。我理解得更好一点,因为没有必要进行任何防范。我将不得不大量练习和阅读,最重要的是,学会用这种语言让你思考的方式思考。再次感谢。我想t你应该定义一些像pretty_print([],N)->。。。