Last active
June 22, 2018 12:48
-
-
Save loggerhead/48facfaab6db640c2b3f to your computer and use it in GitHub Desktop.
Erlang快速入门
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
*.beam |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
% bar.erl | |
-module(bar). | |
-include("bar.hrl"). | |
-compile(export_all). | |
distance(P) when is_number(P#point.x), is_number(P#point.y) -> | |
math:sqrt(P#point.x*P#point.x + P#point.y*P#point.y). | |
% record 在 function clause 中的匹配很违背直觉 | |
% 仅匹配 `#point.y == 1`,而不管 `#point.x` 是不是 `0` | |
test(#point{y = 1}) -> io:fwrite("x=? y=1~n"); | |
% 仅匹配 `#point.x == 1`,而不管 `#point.y` 是什么值 | |
test(#point{x = 1}) -> io:fwrite("x=1 y=?~n"). | |
test() -> | |
P1 = #point{x = 1, y = 0}, | |
P2 = {point, 1, 0}, | |
case distance(P1) =:= distance(P2) of | |
true -> ok; | |
false -> error("Oh My God! This is impossible!") | |
end, | |
test(#point{x = whatever, y = 1}), % x=? y=1 | |
test(#point{x = 1, y = 1}), % x=? y=1 | |
test(#point{x = 1, y = whatever}). % x=1 y=? |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
% bar.hrl | |
% record 将元组中的元素绑定到特定的名称 | |
-record(point, {x = 0, y}). | |
% 等价于 {point, X = 0, Y = undefined} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
% catcher.erl | |
-module(catcher). | |
-compile(export_all). | |
% `throw`, `exit`, `error` 三者都能产生异常 | |
do_something(throw) -> throw(lol); % ** exception throw: lol | |
do_something(exit) -> exit(lol); % ** exception exit: lol | |
do_something(error) -> error(lol); % ** exception error: lol | |
do_something(X) -> X. | |
normal_catcher(X) -> | |
try do_something(X) of | |
Result -> io:format("do_something(~p) => ~p~n", [X, Result]) | |
catch | |
throw:E -> io:format("catch throw: ~p~n", [E]); | |
exit:E -> io:format("catch exit: ~p~n", [E]); | |
error:E -> io:format("catch error: ~p~n", [E]) | |
end. | |
all_catcher(X) -> | |
try do_something(X) of | |
Result -> io:format("do_something(~p) => ~p~n", [X, Result]) | |
catch | |
% 省略错误类型 | |
% 默认为 throw 类型 | |
E -> io:format("catch you: ~p~n", [E]) | |
after | |
io:format("after `try...catch`~n") | |
end. | |
simple_catcher(X) -> | |
% 将异常转换为一个描述异常的元组 | |
% 如果没有异常,则返回表达式的值 | |
catch do_something(X). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-module(if_case). | |
-compile(export_all). | |
% `if` 类似于 guard,并且语法和 guard 一致 | |
hi_if(X) -> | |
% `if` 也有返回值 | |
Result = if | |
% 必须匹配所有的逻辑,否则会 crash | |
X > 0 -> positive; | |
X == 0 -> zero; | |
% 匹配剩下的所有可能 | |
true -> negative | |
end, | |
io:format("if expression result is '~p'~n", [Result]). | |
% `case` 类似于函数头部,其余部分和 `if` 几乎一样 | |
hi_case(X) -> | |
Result = case X of | |
X when X > 0 -> positive; | |
X when X == 0 -> zero; | |
% 匹配剩下的所有可能 | |
_ -> negative | |
end, | |
io:format("case expression result is '~p'~n", [Result]). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
% m.erl | |
-module(m). | |
-export([start_echo/0, start_hurry/0]). | |
echo() -> | |
receive | |
{From, Msg} -> | |
io:format("~p => ~p: ~p~n", [From, self(), Msg]), | |
From ! Msg, | |
% 循环接收消息 | |
echo() | |
% 如果10秒内没收到消息,就执行 after 语句 | |
after 10000 -> | |
io:format("quit echo process~n") | |
end. | |
% `after 0` 的逻辑类似于: | |
% if is_not_empty(message_queue) | |
% receive() | |
% else | |
% after() | |
do_hurry() -> | |
receive | |
Msg -> | |
io:format("message: '~p'~n", [Msg]), | |
do_hurry() | |
after 0 -> | |
io:format("no more message, quit~n") | |
end. | |
% 等待10秒后从消息队列中取出所有消息 | |
hurry(Wait) -> | |
timer:sleep(Wait), | |
do_hurry(). | |
start_echo() -> | |
% 调用 `spawn` 启动新进程,并返回一个pid(进程标识符) | |
% 在 `erl` 中调用为 `spawn(Function)`,在模块中为 `spawn(fun Function/0)` | |
spawn(fun echo/0). | |
start_hurry() -> | |
spawn(fun() -> hurry(10000) end). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
% mymath.erl | |
-module(mymath). | |
-compile(export_all). | |
% 自定义的宏 | |
-define(ONE, 1). | |
-define(ADD(X, Y), X+Y). | |
test() -> | |
io:format("predefined macros: ~n"), | |
% 预定义的宏 | |
io:format("~p ~p ~p ~p ~p~n", [?MODULE, ?MODULE_STRING, ?FILE, ?LINE, ?MACHINE]), | |
% `?MACRO` 调用宏 | |
io:format("one=~p add(1,2)=~p~n", [?ONE, ?ADD(1, 2)]). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
% mymethod.erl | |
-module(mymethod). | |
% 要想在外部调用模块中的函数,首先得将函数导出 | |
% -export([Function1/Arity, ..., FunctionN/Arity]). | |
-export([hi/0, all_the_same/3, is_adult/1, is_triangle/3, is_num/1, bro/1, bro/0, yo/1, sum/1]). | |
% 调试的时候可以使用下面的语句导出所有函数 | |
% -compile(export_all). | |
% 不需要 `end` | |
hi() -> | |
"hello, world". | |
% 按函数分句的先后顺序进行模式匹配 | |
% 找到第一个参数匹配的分句时,执行该分句下的表达式 | |
% 分号表分句的结束,句号表整个函数的结束 | |
all_the_same(X, X, X) -> true; | |
% `_` 是匿名变量 | |
all_the_same(_, _, _) -> false. | |
is_adult(Age) when Age < 18 -> false; | |
is_adult(_) -> true. | |
% 逗号在 guard 中的作用类似于 `and` | |
is_triangle(A, B, C) when A+B > C, B+C > A, A+C > B -> true; | |
is_triangle(_, _, _) -> false. | |
% 分号在 guard 中的作用类似于 `or` | |
is_num(X) when is_integer(X); is_float(X) -> true; | |
is_num(_) -> false. | |
bro(Girlfriend) when Girlfriend == girl -> | |
io:format("fall in love with ~p~n", [Girlfriend]); | |
% 若参数未被使用,编译时会发出警告:`Warning: variable 'Girl' is unused` | |
% 如果参数名以下划线开头,则不会警告 | |
bro(_Girl) -> | |
io:format("cheat!~n"). | |
% 参数数目不同但同名的函数没有任何关系 | |
bro() -> | |
io:format("I'm a single dog~n"). | |
% 根据参数的模式匹配执行不同的分句 | |
yo(brother) -> | |
io:format("Hi, man!~n"); | |
yo(friend) -> | |
io:format("How are you?~n"); | |
yo(People) -> | |
io:format("Are you \"~p\"?~n", [People]). | |
% 计算列表的和 | |
sum(L) -> sum(L, 0). % 句号 | |
sum([], Result) -> Result; % 分号 | |
sum([H|T], Result) -> sum(T, H+Result). % 又是句号,为什么? |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
% 模块属性以 `-` 开头 | |
% module 属性是必须的,且参数必须与除去后缀的文件名一致 | |
-module(test). | |
% import 属性用来导入其他模块的函数,然后才能在模块中使用 | |
% -import(Module, [Function1/Arity, ..., FunctionN/Arity]). | |
% 其中 Arity 是函数的参数数目 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
编译
运行
直接在
erl
中使用,不需要再用c
进行编译了。