「何かを行う」疑似コードが曖昧すぎるため、どの方法を使用すべきかを正確に推奨することは困難です。
Erlang のような関数型言語で何かのリストを反復処理するには、主に 2 つの方法があります:map
とfold
.
大きな問題は次のようになります。ファイルをどうしたいですか? ファイルを合計したいですか (つまり、ファイルの合計サイズか何か)、それともファイルごとに値を保存したいですか (つまり、各ファイル サイズを個別に)、またはファイルに対して何かをしたいと思いますか?それらのファイルの戻り値が何であるか (つまり、各ファイルの名前を変更すること) は気にしませんか?
から返されたファイルのリストを使用して、ここでそれぞれの例を簡単に示しますfile:list_dir/1
。
{ok, Filenames} = file:list_dir("some_directory"),
折りたたみ
ここでは、ディレクトリ内のすべてのファイルのファイルサイズを合計しますlists:foldl
(@legoscia が言及したように、この場合filelib:fold_files
はおそらくより良い選択です)
TotalSize = lists:foldl(fun(Filename,SizeAcc) ->
FileInfo = file:read_file_info("some_directory/" ++ Filename),
FileSize = FileInfo#file_info.size,
SizeAcc + FileSize
end, 0, Filenames).
マッピング
ここでは、ファイル名のリストと、lists:map
. 結果のリストは = の形式になります[{"somefile.txt",452}, {"anotherfile.exe",564},...]
。
FileSizes = lists:map(fun(Filename) ->
FileInfo = file:read_file_info("some_directory/" ++ Filename),
FileSize = FileInfo#file_info.size,
{Filename,FileSize}
end,Filenames).
Foreach (マッピングの一種)
ファイルの名前を変更するだけで、ファイルに関するデータの記録を気にしないという代替案は、 の使用を示すことですlists:foreach
。これは通常、戻り値を気にしない副作用プログラミングにのみ使用され、 のように動作しますlists:map
。しかし、有用なものは何も返しません (atom を返すだけですok
):
この場合、各ファイル名に「.old」拡張子を追加して、各ファイルの名前を変更する方法を示します。
lists:foreach(fun(Filename) ->
OldFile = "some_directory/" ++ Filename,
NewFile = OldFile ++ ".old",
file:rename(OldFile, NewFile),
end,Filenames).
再帰
もちろん、これらすべての生のバージョン - if map
、fold
、foreach
、またはリスト内包表記 (これはカバーしませんでしたが、基本的にコンポーネントをmap
使用した別のバリアントfilter
です) は何らかの理由で制限が多すぎます - 再帰的に行うことができます:
do_something_with_files([]) -> ok;
do_something_with_files([CurrentFile|RestOfFiles]) ->
do_something(CurrentFile),
do_something_with_files(RestOfFiles).
Erlang で必要なことを行う方法はたくさんありますが、VB のような手続き型言語とは異なり、リストをどのように反復処理するかを決定するために、何を追跡または実行したいかを少し先に考える必要があります。Erlang の不変変数によって制限されています。
注:レコードを使用する#file_info
には、モジュールの先頭に次のように file.hrl ファイルを含める必要があります。
-include_lib("kernel/include/file.hrl").