-module(tut).
-export([folders/1]).
-export([main/0,incr/1]).
main() ->
Folders = folders("C:/Users/David/test"),
LCounter = [0],
pretty_print(Folders, 0, LCounter),
ok.
folders(PATH) ->
{_, DD} = file:list_dir(PATH),
A = [H || H <- DD, filelib:is_dir(PATH ++ "/" ++ H) =:= true], %%please note the "/" is added here
%io:format("Path: ~p, A: ~p~n", [PATH, A]),
case A of
[] -> %%Base case, i.e. folder has no sub-folders -> stop here
{PATH, []};
_ -> %%Recursive case, i.e. folder has sub-folders -> call @folders
{PATH, [folders(PATH ++ "/" ++ H2) || H2 <- A]}
end.
pretty_print(Folders, Depth, LCounter) ->
{CurrrentFolder, ListSubfolders} = Folders,
SignTemp = lists:duplicate(Depth, "-"),
case Depth of
0 -> Sign = SignTemp;
_ -> Sign = "|" ++ SignTemp
end,
io:format("Depth ->~p", [ io_lib:format("~p", [Depth])]),
io:format("| Lcounter ->~p", [LCounter]),
io:format("~s~s~n", [Sign, CurrrentFolder]),
[pretty_print(Subfolder, Depth+1,map(fun tut:incr/1, LCounter))|| Subfolder <- ListSubfolders].
map(_, []) -> [];
map(F, [H|T]) -> [F(H)|map(F,T)].
incr(X) -> X + 1.
I'm quite new to Erlang, I've only been learning for two or three days and it's hard for me to change the paradigm.
What I was trying to do is a counter (in this case Lcount). Actually I thought that in each call to the function it would increase, but I realize that it works like the variable Depth.
On the other hand I do not understand how it is possible that Depth does not also increase in each call.
How does it work? Am I missing something?
I have trouble not trying to use c++ (increment) variables in for or while loops.
I think it is going to be a bit hard for me to learn this nice functional language.
Here are the log results:
What I want to do in this exercise is to simply count all the folders and subfolders from a path. It is just an exercise, but I am having a hard time understanding and finishing it. More than anything because I am not fluent in the language at all.
There might even be a function to do that, but I want to try and get it using what little I know
2条答案
按热度按时间zzoitvuj1#
To start with, in Erlang we will deal a lot with list data type. One starting point is to familiarize with the concise lists function from Erlang documentation.
Back to the question, folders are like tree, so need to walk down the path from root to all branches.
Howto call from main function:
7vhp5slm2#
I add this answer to complete @Agus one's.
As you are starting with Erlang, it is a good idea to get familiar with recursion. It is central in Erlang, despite of the fact that Erlang's libraries take care of it in numerous situations : lists, maps, gb_trees, gen_server, gen_statem ... and therefore it seems to disappear in many cases.
At the very beginning, I advice you to avoid the usage of those libraries until you master the concept of recursion and tail recursion. Then, as Agus says, you should dig into the numerous Erlang libraries, they already solve most of the common problems you could have.
In your code, you are using list comprehension. It is an elegant syntax (in my opinion) but I think that it does not fit to your goal (mastering recursion) and, in the particular cases you used it, it hides what you are really doing:
Here you want to filter the directories, I think that lists:filter/2 is more explicit (even if the comprehension syntax is easy to understand in this case):
At the end of my answer, I propose you a code were I have used a "hand made" recursion
With
You want to map the function folders/1 on each element of A, lists:map/2 does exactly this
Finally, with
The list comprehension does not what you expect, like in previous case it simply maps the function pretty_print on each element of the list A, while you want to accumulate on each element. The function lists:foldl/3 does this (it needs a modification of the pretty_print function)
In my example I propose a different hand made version that also print the result in a more standard tree representation.
It gives: