Erlang第三課---moduleの作成と使用

7501 ワード

----------------------------------------------------
この授業が始まると、Erlangファイルを使用して操作するので、shellを起動するときは、erl shell環境を開くなど、現在のディレクトリが作業ディレクトリであることを期待します.デフォルトのディレクトリは「C:/Users/Kenneth/Documents/Erlang」です.C:/Program Files/erl 5.9.1/usr(shellを起動した後、pwd()を実行します.現在のディレクトリが何であるかを確認します)の下の.erlangファイルを編集して、この目的を達成する必要があります.Windowsで.erlangを作成するのは頭が大きいので、グラフィックインタフェースで操作すると、「ファイル名を入力しなければならない」というプロンプトが表示され、まずテキストドキュメントを作成し、cmd環境でmove xxx.erlangを実行してファイル名を変更することができます.
.erlangファイルの内容は次のとおりです.
io:format("according to the file .erlang in ~p~n",
            [element(2, file:get_cwd())]).
%% Edit to the directory where you store your code
io:format("cd ").
c:cd("C:/Users/Kenneth/Documents/Erlang").
io:format("...~n").
io:format("OK! Now in:~p~n", [element(2, file:get_cwd())]).

次にshellを起動すると、現在のディレクトリが作業ディレクトリに自動的に切り替わります.
---------------------------------------------------
Erlangでは、ある種類のfunctionを別のファイルに配置し、この全体をModuleと呼びます.Erlangのすべての関数はModuleに入れなければなりません.したがって、前の2つの授業で述べた基本データ型に加えて、ModuleもErlangの基本要素の一つです.
 
1、関数を呼び出すときは、Module:Function(Arguments)という構造でなければなりません.BIFsを除く.
 
2、BIF(Build In Function)の使用時にmoduleを指定する必要はありません.これは、仮想マシンの起動時にErlangというmoduleのすべての関数がデフォルトでロードされているためです.すべてのarithmetic,logic,boolean operatorもErlangというmoduleにあります.例:
> erlang:element(2,{a,b,c}).
b
> element(2,{a,b,c}).
b
> lists:seq(1,4).
[1,2,3,4]
> seq(1,4).
** exception error: undefined shell command seq/2

上記のコードでは、element関数がErlangモジュールに属することを示すかどうかにかかわらず、実行できます.一方,seqはlistsモジュールに属するため,どのmoduleに属するかを指定しないとシステムはエラーを投げ出す.
ps:すべてのErlangのすべての関数がロードされているわけではありません.ロードされていないものもあります.
 
3、単独のファイルが必要で、彼にユニークな名前をつける以外に、FunctionsとAttributesの2つもModuleに不可欠です.Functionは言うまでもなく、Functionがなくて、Moduleを創立して何をしますか?はい、Attributesは何に使いますか?Attributesには、Module自体を記述するmetadataが格納されています.例えば、自分の名前、外部で呼び出せる関数、コード作成者などです.コンパイラは、これらの情報をコンパイル済みのコードに格納します.これにより、コンパイルされたコードを手に入れても、source codeをひっくり返すことなく、このmoduleの基本情報を表示することができます.
attributesの定義方法は-name(Attribute)である.
 
4、最初のAttributesは「-module(Name)」;ここのNameはModuleが保存されているfileと同じ名前でなければなりません.ここでのnameは,我々がMF(A)のように関数を呼び出す際に用いなければならないmodule nameである.
 
5、そしてもう一つ欠かせないAttributesは「-export([Function 1/Arity,Function 2/Arity,...,Function 3/Arity])」です.ここでFunctionは関数名であり,Arityはこの関数がいくつかのパラメータを受け入れる.Erlangでは,同じ名前の異なるパラメータ個数の関数は異なる関数として扱われ,これはOOP内のリロードに似ている.
 
6、もう一つのattributesが重要な「-import(Module,[Function/ARity,...,Function/ARity])」は、moduleの関数をロードし、呼び出したときに直接F(A)でいい(仮想マシンが最初にErlangというmoduleにやったように).ここに問題がありますが、importで仕事を完成することにあまり賛成しない人が多いです.主に、本来moduleを設計する際には、function nameが本module内で唯一であることを考慮するだけでよいのですが、今は異なるmoduleからfunctionを導入し、使用する場合は、慎重にしなければなりません.
 
7、defineはもう一つの重要なattributesであり、使用方法は「-define(MACRO,some_value)」である.これはCの中のdefineと少し似ています.同じdefineも定数と短い関数を定義するのによく使われています.Erlangのマクロ定義を使用する場合、フォーマットは「?MACRO」です.
ps:?MODULEはmodule nameに変更され、as a atom;?FILEはコストファイルのfilename、as a string;?LINEは行番号に変更されます.
ps:同様に、-ifdef(MACRO)、-else、-endifなどのマクロ定義チェック文を使用します.たとえば、次のようにします.
-ifdef(DEBUGMODE).
-define(DEBUG(S), io:format("dbg: "++S)).
-else.
-define(DEBUG(S), ok).
-endif.

これで、後のコードで使用できますか?DeBUG("entering xxx function!~n")という文でデバッグ情報を追加します.このように、コンパイル時にDEBUGMODEスイッチを使用すると、デバッグ情報が印刷されます.もし私たちがDEBUGMODEスイッチを使っていなければ、この文はokというatomに置き換えられただけで、単独でこのような文は何もできません.
 
8、関数の定義構文はName->Bodyです.Nameはatomでなければなりません.Bodyは、カンマで区切られた1つまたは複数のErlang文であってもよい.(終端記号)はセミコロンまたはピリオドの1つで、同じ名前の複数の関数を定義するときに、各関数の間に「;」記号で区切られ、すべての関数定義の実装が完了したら、最後に「.」を追加します.
 
9、もう一つの一般的なattributesは次のとおりです.
-spec Module:Function(ArgType1, ..., ArgTypeN) -> ReturnType."
ここでは、同じmodule内であれば、「Module」フィールドを省略して書くことができます.
この文は、関数仕様を定義するために使用されます.関数仕様を定義すると、実行前にdialyzerを使用してプログラムを静的にチェックすることができます.これにより、手振れによるエラーを発見することができます.
次の文は、任意のデータ型であってもよく、2番目は正の整数であり、3番目のパラメータはlist(ここでは[any()]とlists()が等価である)であり、returnは非負の数である関数index()を定義することを意味します.
-spec( index(any(), pos_integer(), [any()]) -> non_neg_integer() ).

またspecに関連するtypeもあり、具体的には以下のようにスタンプすることができます.
http://erlangdisplay.iteye.com/blog/404570
 
==============================
so、moduleがこのように建てられました.私たちが建てた最初のmoduleを見てみましょう.
-module(helloworld).
-export([greet_and_add_two/1]).

add(A,B) ->
    A + B.
    
%%% Shows greeting.
%%% io:format/1 is the standard function used to output text.

hello() ->
    io:format("Hi Erlang!~n").
    
greet_and_add_two(X) ->
    hello(),
    add(X,2).

 次にmoduleをコンパイルして使用します.
> cd("C:/Users/zhenxingluo/Documents/Erlang").
C:/Users/zhenxingluo/Documents/Erlang
ok
> c(helloworld).
{ok,helloworld}  
> helloworld:greet_and_add_two(3).
Hi Erlang!
5
> helloworld:module_info().
[{exports,[{greet_and_add_two,1},
           {module_info,0},
           {module_info,1}]},
 {imports,[]},
 {attributes,[{vsn,[251566447801502640269456451546098169641]}]},
 {compile,[{options,[]},
           {version,"4.8.1"},
           {time,{2014,4,2,7,22,18}},
           {source,"c:/Users/zhenxingluo/Documents/Erlang/helloworld.erl"}]}]

ここでcdはErlang shell専用の関数で、change directoryです.そして、Erlang shellのコンパイル関数c()を呼び出します.コンパイルにエラーがなければ、helloworld.erlファイルの横にhelloworld.beamというファイルが生成されます.
実際、beamはBogdan/Bjorn's Erlang Abstract Machineを表しています.このVMは多くのErlangの仮想マシンの一つにすぎませんが、他はあまり使われていないようです.うん、コンパイルを続けても間違いがなければ、私たちの現在のディレクトリはhelloworld.beamがあるディレクトリなので、VMはこのファイルが見えます.では、shellウィンドウで直接彼を呼び出すことができます.私たちが見たように.
ここでmodule_info()は、コンパイラが追加する関数です.この関数を呼び出すと、moduleのmetadataを表示できます.また、module_info/1を使用して、helloworld:module_info(attributes)などの項目を表示することもできます.