サンプルプログラム1 (NP Erlang/Elixir編)

回数を決めた繰返し

% 長さ n のリストを生成して、その要素毎に何か(foreachの第一引数)をさせる
lists:foreach(fun(X)->io:format("hello\n") end,lists:seq(1,10)).
% リスト内包表記(結果のリストとして返される値は廃棄する)で実現
[io:format("hello\n")||X<-lists:seq(1,10)].
% 再帰関数で実現(下記はモジュール名と同名の単独ファイルにする必要あり)
-module(rep).
-export([rep/1]).
rep(0)->nil;
rep(X)->io:format("hello\n"),rep(X-1).
% 呼出は  c(rep). のあと rep:rep(10).  のように回数を数値で与える
# リスト(またはRange Stream などのオブジェクト)でループ
Enum.each(1..5,fn(x)->IO.puts("hello")end)
1..5|>Enum.each(fn(x)->IO.puts("hello")end)
    # パイプで繋ぐ書き方
Range.new(1,5)|>Enum.each(fn(x)->IO.puts("hello")end)
    # まだるっこしい書き方もある
1..5|>Stream.each(fn(x)->IO.puts("hello")end)|>Stream.run()
    # Streamの形だと、Streamを実行する(run)まで出力の動作は行われない
# 内包表記で書く
for x<-1..5, do: IO.puts(x)
    # 上記のリストによる記法で、eachの代わりにmap を使ったものと同じ       # (putsメソッドの結果の値であるnilをリストの形で並べたものを値として返す)
# 再帰を使う場合
defmodule Rep do
  def rep(0), do: 0
  def rep(n) do; IO.puts(n) ; rep(n-1) ;end
end     # 以上をファイルに用意してコンパイルする必要がある
Rep.rep(5)      # この場合、整数を降順に印字する

ファイルを読む

ファイルに書き込む

ファイルのコピー

  1. リストの形で連結

    =>ソース(cp1.erl)

    -module(cp1).
    -export([cp/1]).
    rd(F,Ls)->
      case io:get_line(F,'') of
        eof -> Ls;
        Line -> rd(F, Ls++[Line])
      end.
    cp(Filename)->
      {ok,Ifile}=file:open(Filename,read),
      List=rd(Ifile,[]),
      file:close(Ifile),
      % ここまでが入力 このあと出力
      {ok,Ofile}=file:open(Filename++".bak"),
      [io:write(Ofile,E)||E<-List],
      file:close(Ofile).
    defmodule Cp1 do
      defp rd(f,ls) do
        case IO.read(f,:line) do
          :eof -> ls
          line -> rd(f, ls++[line])
        end
      end
      def cp(filename) do
        {:ok,list}=File.open(filename,[:read],fn ifile->
          rd(ifile,[])
        end)
        # IO.puts(list)
        File.open(filename<>".bak",[:write],fn ofile->
          for e<-list , do: IO.write(ofile,e)
        end)
      end
    end
  2. 1行ずつ、同時進行で読み書き

    -module(cp2).
    -export([cp/2]).
    cp1(Ifile,Ofile)->
      case io:get_line(Ifile,'') of
        eof->file:close(Ofile),file:close(Ifile);
        Line->file:write(Ofile,Line),cp1(Ifile,Ofile)
      end.
    cp(Filename,Newname)->
      {ok, Ifile} = file:open(Filename,read),
      {ok, Ofile} = file:open(Newname,write),
      cp1(Ifile,Ofile).

    =>ソース(cp2.erl)

    defmodule Cp2 do
      defp cp1(ifile,ofile) do
        case IO.read(ifile,:line) do
          :eof->File.close(ofile); File.close(ifile)
          line->IO.write(ofile,line); cp1(ifile,ofile)
        end
      end
      def cp(filename,newname) do
        {:ok, ifile} = File.open(filename,[:read])
        {:ok, ofile} = File.open(newname,[:write])
        cp1(ifile,ofile)
      end
    end

    =>ソース(cp2.ex)

  3. reader, writer を別プロセスにしてプロセス間通信で受け渡す

    -module(cp3).
    -export([cp/2,writer/1]).
    writer(Ofile)->
      receive
        eof->file:close(Ofile);
        Line->file:write(Ofile,Line), writer(Ofile)
      end.
    cp1(Ifile,Pid)->
      case io:get_line(Ifile,'') of
        eof->Pid!eof,file:close(Ifile);
        Line->Pid!Line, cp1(Ifile,Pid)
      end.
    cp(Filename,Newname)->
      {ok,Ofile} = file:open(Newname,write),
      {ok,Ifile} = file:open(Filename,read),
      Pid=spawn(cp3,writer,[Ofile]),
      cp1(Ifile,Pid).

    =>ソース(cp3.erl)

    defmodule Cp3 do
      def writer(ofile) do   # この関数が別プロセスとしてspawnされる
        receive do           # メッセージを受信
          :eof->File.close(ofile)
          line->IO.write(ofile,line); writer(ofile)
        end
      end
      defp cp1(ifile,pid) do
        case IO.read(ifile,:line) do     # 読んだ行をそのまま送信
          :eof->send(pid,:eof)
          line->send(pid,line); cp1(ifile,pid)
        end
      end
      def cp(filename,newname) do
        {:ok, ofile} = File.open(newname,[:write])
        File.open(filename,[:read],fn(ifile)->
          pid=spawn(Cp3,:writer,[ofile])
          cp1(ifile,pid)
        end)
      end
    end

    =>ソース(cp3.ex)