Erlang 入门 ---- 基础(一)
Erlang 入门
基础
安装 Erlang Shell
命令安装
For Homebrew on OS X: brew install erlang For MacPorts on OS X: port install erlang For Ubuntu and Debian: apt-get install erlang For Fedora: yum install erlang For FreeBSD: pkg install erlang
基本使用
启动与退出
在终端中输入
erl
即可进入Erlang Shell
% 这是一个单行注释,Erlang 中没有多行注释 % Erlang 中 . 表示语句的结束 (类似 Java/C 语言中的 分号) % Erlang Shell 类似 Python 的 IDLE,可以直接进行运算 % Erlang 为函数式语言,所有函数、表达式都有返回值,运行成功时都会返回一个 atom 类型的 ok io:format("hello world!~n"). % 打印 hello world,~n 表示换行 1 + 1. % 输出 2 q(). % init():stop(). 的快捷方式,退出 Erlang Shell
变量
Erlang
是动态类型(声明变量时候不需要指定类型)同时也是强类型(Erlang 不会自动的进行类型转换)的语言
% pattern match (模式匹配) A = 1. % 在 Erlang 中 = 称为模式匹配,后面会再讲 % 若 A 没有值,则会将右边的值绑定到 A,相当于赋值 % 若 A 有值且两边值相等,则匹配成功,否则报错 % 变量只有绑定才可以使用,虽然称之为变量,但实际是 ‘Immutable‘ (不可变的) _Age = 2. % 下划线开头的变量,即使没有使用/绑定也没关系,编译也不会报错
函数
Add = fun(A, B) -> A + B end. % 声明一个匿名函数,需要两个参数,绑定到 Add 变量上 Add(1,2). % 调用
基本类型
Number
1 + 1. % 2 1 * 2. % 2 2 - 1. % 1 5 / 2. % 2.5 5 div 2. % 2, div 表示整除 5 rem 2. % 1 rem 表示取余 % 不同进制表示,格式:Base#Value,Base 默认为 10 2#10. % 表示二进制的 10,即十进制的 2 8#10. % 表示8进制的 10, 即十进制的 8 ...
Atoms
可以理解为一个常量,atom
类型使用内存很小且运算速度很快,但注意数量是有限制的。
% 以下都是合法的 atom 类型 atom. atom_rule. ‘Atom 123‘. % 包含特殊字符需要写在单引号中 atom = ‘atom‘. % true、false 就是一种 atom 类型
Tuples
元组是不用类型的值组成的一个类型。语法:{element1, element2, ..., elementN}
{1,2}. % 一般情况下,会使用 atom 类型作为第一个值用于标注这个元组的含义,称之为 ‘tagged tuple‘ {point, 1, 2}. % 表示一个点坐标 {rectangle, 2, 3}. % 表示一个矩形的长度和宽度
List
List
就是链表,可以包含各种类型的值
% 常用语法 [1, 2, 3]. [1, [2,3], {4}]. % Erlang 中 String 就是 List "abc" [97, 98, 99]. % 与上一行等效 % 操作符 [1, 2] -- [1]. % [2] [1] ++ [2]. % [1, 2] List = [1,2] hd(List). % 1 tl(List). % 2 [0 | List]. % [0, 1, 2],头部插入一个 0 % List Comprehensions 语法, 可以根据需求生产新的 List [2*N || N <- [1,2]]. % [2, 4], 将列表元素乘 2 [N || N <- [1,2], N rem 2 =:= 0]. % [2],取出列表中的偶数
Tips:
- 列表相对来说拼接等操作比较耗时,同时比较占内存,字符串可以使用内存更小的
Binary
类型,比如:<<"abc">>
Tuple
与List
最大的区别在于定长与不定长(个人理解)
运算符
逻辑运算符
true and false. % false,与 andalso 类似 true or false. % true, 与 orelse 类似 true xor false. % true not false. % true % and/or 和 andalso/orelse 区别在于后者右边的运算不一定会执行
比较运算符
1 < 2. % true 2 > 1. % true 1 =< 2. % true % 注意写法 =< 1 >= 2. % false 1 =:= 1. % true,严格相等 1 == 1.0. % true,大概相等 1 =/= 1. % false,严格不等 1 /= 2. % true,相差很多 % =:= 为判断相等,=/=判断不等(包括类型)
不同类型之间也存在大小关系:
number < atom < reference < fun < port < pid < tuple < list < bit string
Modules
定义与使用
% test.erl -modules(test). % 定义模块,需要与文件名一致 -export([add/2, add/3]). % 指定导出的函数,未导出函数无法调用 % [function/paramNum], 存在同名函数但是参数个数不一样格式如上一行 add(A, B) -> A + B. add(A, B, C) -> A + add(B + C).
当存在参数个数相同的函数用 分号 隔开
% test2.erl -module(test2). -export([add/2]). % 当 A 和 B 都是数字时 add(A, B) when is_number(A), is_number(B) -> A + B; % 此处分号隔开 % 当 A 和 B 都是列表时 add(A, B) when is_list(A), is_list(B) -> A ++ B. % 调用时会从上往下匹配,其余情况没有匹配不执行
单个文件的编译与运行
方法一
在 cmd
中编译 erlang 文件
:: 这是 cmd 中的注释,测试环境为 windows mkdir ebin :: 创建一个文件夹 ebin erlc -o ebin test.erl :: 编译 test.erl,将编译后文件放到 ebin 文件夹中 erl -pa ebin :: 将 ebin 文件夹加入 erlang beam 文件查找目录并启动 erlang shell
在 Erlang Shell
中调用函数
% 只有按照上面的操作后以下方法才会生效 test:add(1, 2). % 3 test:add(1, 2, 3). % 6
方法二
% 在 erl 文件所在的地方打开 cmd, `erl` 进入 erlang shell c(test). % 编译后原地生成 beam 文件 test:add(1, 2). % 3 test:add(1, 2, 3). % 6
模式匹配
case clauses
类似其他语言中的
switch case
语句,通过匹配不同的条件选择不同分支
% test.erl -modules(test). -export([show/1]). % 示例函数 show(Color) -> case Color of red -> io:fomat("So hot."); blue -> io:fomat("So cool."); _ -> io:fomat("So ...") % _ 是一个特殊的变量,单独使用可以匹配任何东西 end.
function clauses
% test.erl -modules(test). -export([show/1]). % 示例函数 show(red) -> io:fomat("So hot."); show(blue) -> io:fomat("So cool"); show(_) -> io:fomat("So ...").
匹配获取值
{X | 2} = {1, 2}. % X = 1 [X | Y] = [1, 2, 3] % X = 1, Y = [2,3] [_ | X] = [1, 2] % X = 2 f(). % 解绑所有变量
When
% 18 岁才可以... fun(X) when X >= 18 -> true; fun(_) -> false. % 14-18岁之间... fun(X) when X <= 18, X >=14 -> true; fun(_) -> false.
when 中
,
表示 and;
表示 or,可以使用andalso
和orels
Records
与
tagged tuple
类似,但是更加直观
% records.erl -module(records). -export([get_user_name/1, get_user_phone/1]). -record(user, { name, phone }). get_user_name(#user{name=Name}) -> Name. get_user_phone(#user{phone=Phone}) -> Phone.
% 进入 erlang shell c(records). % 编译文件 rr(records). % 将 record 加载到 shell 中 User = #user{name=<<"Jeson">>, phone=<<"123">>}. % 定义一个 record Name = record:get_user_name(User). % Jeson,获取 User 中的名字 Phone = record:get_user_phone(User). % 123 User#user.name. % Jeson #user.name. % 2,record 本质就是一个 tagged tuple,所有 name 是第二个元素
Erlang
中位置从 1 开始计算
递归
因为 Erlang
中没有迭代语句,所以使用递归解决大部分的问题
% 场景:计算一个 List 的长度 len([]) -> 0; len([_|T]) -> 1 + len(T). % 递归计算长度
尾递归
上述递归存在一个问题,就是需要递归到最深处再回溯进行相加操作,对内存消耗较大,可以使用尾递归进行优化
len(T) -> len(T, 0). %调用尾递归函数 len([], Len) -> Len; len([_|T], Len) -> len(T, Len+1).
制作一个简单的 GIF 演示一下:
并行
参考资料:简书
相关推荐
Noneyes 2020-11-10
huavhuahua 2020-11-20
weiiron 2020-11-16
ailxxiaoli 2020-11-16
cakecc00 2020-11-15
千锋 2020-11-15
JakobHu 2020-11-14
chensen 2020-11-14
Nostalgiachild 2020-11-13
guangcheng 2020-11-13
zhangxiafll 2020-11-13
jipengx 2020-11-12
xirongxudlut 2020-11-10
solarLan 2020-11-09
pythonxuexi 2020-11-08
文山羊 2020-11-07
susmote 2020-11-07
wuShiJingZuo 2020-11-05
Pythonjeff远 2020-11-06