启动
erl
说明
.结尾一个语句
-module(geometry). %模块声明,模块名必须与文件名相同。
-export([area/1]). %导出声明,声明可以外部使用的函数
area({rectangle, Width, Height}) -> Width*Height; %子句1
area({square, Side}) -> Side * Side.%子句2
在erl中用c(“文件名.erl”). 去编译
定义一个函数
Double = fun(X)->2*X end. %变量名是必须大写的
Double(2).
使用模块:函数
L=[1,2,3,4].
lists:map(Double,L).
使用=:=来判断相等
lists:filter(fun(X)->(X rem 2)=:=0 end,[1,2,3,4,5,6]). %函数可拿来当作其他函数的参数
高阶函数(返回函数的函数)
Fruit = [pear,apple,orange].
MakeTest = fun(L)->(fun(X)->lists:mamber(X,L) end) end.
isFruit=MakeTest(Fruit).
isFruit(apple).
Type System
– 原子类型
- 以小写开头,原子类型与变量不同,变量有值,原子类型没有
- 原子是一种描述,一种字面常量,它本身就是最小了
- ‘…’ 引导的串是原子
– 元组 - {atom_what_ever,T_OF_VARIABLE}
– 列表可以加入其他任意类型
[{…},{a,{…}} | {…}]
– 没有字符串,但用数字列表来表示字符串 - [97,98,99] => “abc”
- unicode
– 映射map - #{“key”=>32}
– 二进制串 - <<1,2,3,…>>
– 进制值表示 - 2#10101111000
- 16#ffff
io例子
io:format("~w ~w~n",[hello,world]).%格式化输出,类似于printf
模式匹配和case等价性
一些例子
- tut
- temp_convert
- color
- if_case
- case_test
- spawn_test
- process_in_erlang
- reg_a_pro
- proc_dict
- fnc
- err_handle
进程
%变量不可重赋值,这里只有绑定变量概念
%函数名必须是原子
%模块声明,模块名必须与文件名相同。
-module(tut).
%导出声明,声明可以外部使用的函数
-export([area/1, test/0]).
% area函数的定义
%子句1
area({rectangle, Width, Height}) -> Width * Height;
%子句2
area({square, Side}) -> Side * Side.
% area函数定义结束
test() ->
12 = area({rectangle, 3, 4}),
%如果左右不相等,会调用报错
169 = area({square, 13}),
%使用:tut:test().
tests_worked.
%模块声明,模块名必须与文件名相同。
-module(tut).
%导出声明,声明可以外部使用的函数
-export([area/1, test/0]).
% area函数的定义
%子句1
area({rectangle, Width, Height}) -> Width * Height;
%子句2
area({square, Side}) -> Side * Side.
% area函数定义结束
test() ->
12 = area({rectangle, 3, 4}),
%如果左右不相等,会调用报错
169 = area({square, 13}),
%使用:tut:test().
tests_worked.
-module(color).
-export([new/4, blend/2, test/0]).
%宏定义,宏用的作用主要是方便检查V
-define(is_channel(V), (is_float(V) andalso V >= 0.0 andalso V =< 1.0)).
new(R, G, B, A) when ?is_channel(R), ?is_channel(G), ?is_channel(B), ?is_channel(A) ->
#{red => R, green => G, blue => B, alpha => A}.
blend(Src, Dst) ->
blend(Src, Dst, alpha(Src, Dst)).
blend(Src, Dst, Alpha) when Alpha > 0.0 ->
Dst#{
% 更新已存在的映射键值对可以用 := 操作符
red := red(Src, Dst) / Alpha,
green := green(Src, Dst) / Alpha,
blue := blue(Src, Dst) / Alpha,
alpha := Alpha
};
blend(_, Dst, _) ->
Dst#{
red := 0.0,
green := 0.0,
blue := 0.0,
alpha := 0.0
}.
alpha(#{alpha := SA}, #{alpha := DA}) ->
SA + DA * (1.0 - SA).
red(#{red := SV, alpha := SA}, #{red := DV, alpha := DA}) ->
SV * SA + DV * DA * (1.0 - SA).
green(#{green := SV, alpha := SA}, #{green := DV, alpha := DA}) ->
SV * SA + DV * DA * (1.0 - SA).
blue(#{blue := SV, alpha := SA}, #{blue := DV, alpha := DA}) ->
SV * SA + DV * DA * (1.0 - SA).
test() ->
C1 = color:new(0.3, 0.4, 0.5, 1.0),
C2 = color:new(1.0, 0.8, 0.1, 0.3),
color:blend(C1, C2),
color:blend(C2, C1),
%return the atomic value
tests_worked.
% erl
% c(color).
% color:test().
-module(if_case).
-export([test_if/2]).
test_if(A, B) ->
if
A == 5 ->
io:format("A == 5~n", []),
%% this value will return
a_equals_5;
B == 6 ->
io:format("B == 6~n", []),
b_equals_6;
%That is A equals 2 and B equals 3
A == 2, B == 3 ->
io:format("A == 2, B == 3~n", []),
a_equals_2_b_equals_3;
%That is A equals 1 or B equals 7
A == 1; B == 7 ->
io:format("A == 1 ; B == 7~n", []),
a_equals_1_or_b_equals_7
end.
-module(case_test).
-export([month_length/2, test/0]).
month_length(Year, Month) ->
%% 被 400 整除的为闰年。
%% 被 100 整除但不能被 400 整除的不是闰年。
%% 被 4 整除但不能被 100 整除的为闰年。
Leap =
if
trunc(Year / 400) * 400 == Year ->
leap;
trunc(Year / 100) * 100 == Year ->
not_leap;
trunc(Year / 4) * 4 == Year ->
leap;
true ->
not_leap
end,
case Month of
sep -> 30;
apr -> 30;
jun -> 30;
nov -> 30;
feb when Leap == leap -> 29;
feb -> 28;
jan -> 31;
mar -> 31;
may -> 31;
jul -> 31;
aug -> 31;
oct -> 31;
dec -> 31
end.
test() ->
io:format("~w~n", [month_length(2004, feb)]),
io:format("~w~n", [month_length(1944, feb)]),
io:format("~w~n", [month_length(1947, feb)]).
-module(spawn_test).
-export([start/0, say_something/2]).
say_something(_, 0) ->
done;
say_something(What, Times) ->
io:format("~p~n", [What]),
say_something(What, Times - 1).
start() ->
spawn(spawn_test, say_something, [hello, 3]),
spawn(spawn_test, say_something, [goodbye, 3]).
-module(process_in_erlang).
-compile(export_all).
% erlang的发送消息机制就是底层c语言做的复制要发送信息到另一个进程
% 进程看作是数据类型,这个进程不像其他语言中的进/线程,不共享内存,不会有数据共享,也没有上锁机制
% 进程通信就是是相互发消息机制,根据pid,pid可以注册一个名字
% 例子s
run() ->
A_Server = spawn(process_in_erlang, cosume_server, []),
A_Server ! {self(), helloworld},
receive
{Pid, Msg} ->
io:format("receive ~p from ~p~n", [Msg, Pid])
end,
%发一个stop
A_Server ! {self(), stop},
ok.
cosume_server() ->
% 会阻塞以至于模式匹配
receive
{Pid, Msg} ->
case Msg of
% 当接受到的消息是stop
stop ->
true;
% 其他任意
_ ->
io:format("~p~n", [Msg]),
% 发消息到Pid
Pid ! {self(), Msg},
%递归
cosume_server()
end
end.
-module(reg_a_pro).
-compile(export_all).
run() ->
register(me, self()),
register(lServer, spawn(reg_a_pro, loop, [])),
sleep(5000),
lServer ! {me, helloworld},
receive
{Pid, Msg} ->
io:format("receive ~p from ~p~n", [Msg, Pid])
end,
lServer ! {me, stop},
ok.
loop() ->
receive
{Pid, Msg} ->
case Msg of
stop ->
true;
_ ->
io:format("~p~n", [Msg]),
me ! {self(), Msg},
loop()
end
after 1000 ->
io:format("no msg~n"),
loop()
end.
sleep(Internal) ->
receive
after Internal ->
ok
end.
-module(proc_dict).
-compile(export_all).
% 进程字典,键值对,put(),get(),erase(),可在进程存放一些键值对
% 这些键值对只能在本进程可见可写
start(Version) ->
put(xjb, 1),
spawn(proc_dict, loop, [Version]),
tt().
tt() ->
io:format("pid ~p xjb is ~p~n", [self(), get(xjb)]).
sleep() ->
receive
after 2000 -> ok
end.
loop(Version) ->
sleep(),
Val = what,
io:format("version ~p value is ~p~n", [Version, Val]),
loop(Version).
-module(fnc).
-author("etcix").
-compile(export_all).
a_funcname_must_be_atom() ->
ok.
pat_mat_test(X, Y, Z) ->
case X of
add -> Y + Z;
sub -> Y - Z;
_ -> nothing
end.
% 等价于
calc(add, X, Y) ->
X + Y;
calc(sub, X, Y) ->
X - Y;
calc(_, _, _) ->
nothing.
% lambda
% map,filter
% 经典例子
cost(apple) -> 3;
cost(banana) -> 4;
cost(peach) -> 5.
shop([]) -> 0;
shop([{Name, Num} | T]) -> cost(Name) * Num + shop(T).
shop_v2(X) ->
case X of
[{Name, Num} | T] -> Num * cost(Name) + shop_v2(T);
[] -> 0
end.
test() ->
shop_v2([{apple, 5}, {banana, 2}]).
test_lambda() ->
lists:map(fun(X) -> X * 2 end, [1, 1, 2, 3, 4, 4, 1, 213, 42]),
lists:filter(fun(X) -> X + 2 =:= 3 end, [1, 1, 1, 2, 3, 4, 4]).
-module(err_handle).
-author("etcix").
-compile(export_all).
% error
% exit
% throw
% of对于try结果匹配
test() ->
try
1 / 0
catch
% Type,Reson,Stack
% _:R:Stack -> {err, R, Stack}
error:Error -> {error, Error};
exit:Exit -> {exit, Exit};
throw:Throw -> {throw, Throw}
end.
throw_test() ->
try
% 主动引发,写入任意错误字符串
throw("fucking error")
catch
x:R -> {x, R}
after
% 等价于finally
io:format("~p~n", ["final scope"])
end.
of_test() ->
try 1 - 1 of
0 -> ok;
10 -> no
after
io:format("~p~n", ["final scope"])
end.