一个去中心化的语言,其他语言是以模块作为功能划分,而其则选择以不同进程的程序来交流。可以说这个语言天生就是为了去中心化并发而存在的。
这里要注意并发和并行的区别,并发就是说通过合理资源调配让多个程序一起工作,而并行指的是多个cpu核心同时跑不同的程序或者说不同的电脑跑不同程序。有时候并发并不是指并行,因为通过内部模拟操作系统的轮替,编程语言是能在一核上模拟出并行的感觉,但是本质上还是需要那么多时间,只是让人感觉他们一起在工作而已。
-module(main).声明包
-export([helloWorld/0]).表明这个erl文件中会提供这么个类给外部调用
helloWorld() ->
io:format("Hello World!~n").一个方法,打印一个你好世界
可以看出来在erlang中每句都需要句号结尾,此外什么方法要提供出去,需要去好好思考
此外单行注释的话是%
创建一个指定方法的并发进程,并返回进程标识符
Key = spawn(man,init,["tang",18]).
当需要进行进程通信时候,使用
Key ! {self(),"hello,How are you?"}
这句是发送一个消息给对面,同时用self()获得自己的标识符,一起传给对面以便对方知道我是谁
receive
{From,Message} ->
io:format(Message).
end
其中From是发来消息者,而Message就是具体内容
要注意的是Erlang的变量在声明时候就已经绑死了值,所以是不能改变里面值的,这点有点像传统语言的常量。此外等号的作用也不是赋值语句,你可以理解为匹配符,只是为了让左右相等而存在。
变量和原子的区别在于,但凡大写开头都是变量,而小写则表示原子,即其本身。
此外可以这么理解erlang变量,在一道数学题中,我们会用x去替代未知数,从头到尾x都会代表同个值。而erlang的变量也是这么个情况。
写好erl文件之后,打开shell,执行c(filename)来编译文件,编译完毕就可以直接用模块名(文件名):方法名来调用你声明公开的方法了。
也可以执行erlc来编译文件,然后用erl -noshell 包名 方法名 -s init stop
这会启动erlang会话,并因为最后的init:stop()结束会话
https://blog.csdn.net/witton/article/details/107980676讲的很详细
值得注意的是,先用控制台创建项目,然后用vscode打开,就不用跨目录编译。然后配置文件中的
"arguments": "-s hello_app"
必须要加,因为erlang是靠这句知道要执行什么包的,准备完善就可以在vscode快乐编译了,缺点是智能提示依旧很弱智。
当使用rebar3来编译项目时候,会生成一个_build文件夹,里面的ebin文件夹里面的东西就是所希望的了。如果希望执行程序则需要到根目录,执行application:start(appname)
你可以放心的在尾部直接调用方法本身,这并不会出现命令语言的递归危险,erlang会自动优化,你这样操作跟写死循环是没用任何区别的,记得是函数最后一行。不需要担心死循环的问题,erlang的函数就应该是死循环的。
receive
{client,list_dir} ->
...
{client,{get_file,File}} ->
...
end
当你希望出现多种选择判断的时候,可以直接这么写,erlang会把合适的答案填入合适的方法块中,而不需要大量的if语句
当你需要进行返回值操作时候,直接把返回值写在程序中即可,默认会直接返回给父方法。又因为我们是用erlShell调用的,在获得返回值时候会直接打印出来。这时候可以用变量去接住他,则之后就可以直接拿来使用
全称是init:stop(),在使用时候可以直接写q()
erlang的整数运算可以计算非常庞大的数据,此外跟正常数学运算是一样的
此外变量的作用域仅局限在使用它的函数内,他所在的代码块等级中。其他地方的同名变量并不会互相影响。此外变量只能赋值一次意味着你不会出现空指针或者垃圾赋值的情况,你发现某个变量有问题只需要去定义的地方看就可以了,而传统命令语言需要翻阅全部代码寻找可能修改了值的地方。
Erlang的浮点也有精度问题,因为底层是c的实现方式。任何整数相除都会被转换为浮点型,如果不希望转换则应该使用div和rem
5 div 3 1
5 rem 3 2
4 div 2 2
Erlang中的原子和其他语言的枚举类似,是一种不需要声明的字符参数,通常是小写字符开头的字符串,假如希望用大写开头则应该使用单引号括起来,这样就可以使用一些原本不能使用的字符。值得注意的是erlang也是单双引号敏感型,双引号一般只用来表示字符串。
你可以把元组理解为c中的结构体,或者java中的类
区别在于元组是匿名声明,这意味着当你需要声明元组时候要记得接住它
Tang = {"Tang",15}.
但是有时候你会不知道这个元组是干嘛的,所以会习惯在第一个空位填上原子作为标签,再通过嵌套元组的方式来表明每个属性值的作用
Tang = {Man,{Name,"Tang"},{Age,15}}.
当然你也能这样
Name = {Name,"Tang"},
Age = {Age,15},
Tang = {Man,Name,Age}.
erlang的基础是模式匹配,即左边值要和右边相等一一对应,所以可以用模式匹配从元组中取值,如
{X,Y} = Tang.
这样我们就把值取到X和Y中了,当出现多层元组嵌套时候,我们应该这样写
{_,{_,X},{_,Y}} = Tang
使用占位符我们可以舍弃自己不要的东西
通过使用列表,可以创建一个类似list
Key = [11,"haha",{2,LE}]
然后可以扩增
Key1 = [44,FA | Key]
要注意的是使用|拼接时候,后面的元素必须是列表,不然会导致报错
同理当需要提取元素时候可以这么做
[X|Y] = Key1
这时候X就是列表第一个元素,而后面的其他元素都会归给Y
字符串的本质就是一个数字列表,所以理论上假如你使用合理的列表赋值可以直接拿来当字符串用。比如:
Tang = [65,66,67,68,69,70]
这个字符串等价于"ABCDEF"
使用$符号可以获得指定字符的整数,此外当需要使用特殊Unicode字符,需要使用"a\x{221e}b"这样的转义字符来表示。当你尝试打印时候会显示列表因为\x{221e}不是一个有效的Latin1编码
此时应该使用格式化打印
io:format("~ts~n",[x]). %打印出a∞b
而当只希望打印出列表而不是字符串时候用
io:format("~w~n",Tang).