Hello Erlang!

本系列文章是《Programming Erlang》的学习笔记

Erlang是什么

Erlang是由Ericsson开发的一种面向并发环境的函数式编程语言,
Erlang的并发性是语言虚拟机支持的,不依赖于OS。

Getting Stared

Erlang是面向并发环境的编程语言,一个Erlang程序是由多个并行的进程构成的。进程执行模块中定义的函数。一个erl文件包含一个模块,编译后的erl文件就可以在shell中直接执行了。

-module(hello).
-export([start/0]).

% Hello erlang
start() ->
    io:format("Hello Erlang!~n").

进入Erlang Shell(erl),就可以运行这个模块了

使用c(hello).编译hello模块使用hello:start().调用start函数,即可看见运行结果

$ erl
1> c(hello).
{ok, hello}
2> hello:start().
Hello Erlang~
ok
3> halt().
$

这是一个最简单的Erlang模块,我们可以通过这个模块学习一下Erlang的基本语法。

  • 不难发现,所以Erlang语句都以.结尾,一个Erlang语句以.+空白结束,空白可以是换行符,空格,tab,等等
  • -module(hello).声明了一个名为hello的模块
  • -export([start/0]).是这个模块的导出函数列表,声明了可以在模块外部调用的函数列表,start/0表示start函数有0个参数
  • start() -> io:format("Hello Erlang!~n").是start函数的定义,io是erlang系统提供的模块,format是io模块导出的一个函数。因此,Erlang中调用函数的基本模式即为:(params).

Getting little sophisticated

Hello Erlang模块阐述了一个最基本的Erlang模块,和所有Hello World!程序一样,这并没有什么卵用。我们需要一个更复杂的程序来展示Erlang的基本编程模式。

%file_server.erl
-module(file_server).
-export([start/1, loop/1]).

start(Dir) ->
    spawn(file_server, loop, [Dir]).

loop(Dir) ->
    receive
        {Client, list_dir} ->
            Client ! {self(), file:list_dir(Dir)};
        {Client, {get_file, File}} ->
            Full = filename:join(Dir, File),
            Client ! {self(), file:read_file(Full)};
        {Client, {put_file, File, Content}} ->
            Full = filename:join(Dir, File),
            Client ! {self(), file:write_file(Full, Content)}
    end,
    loop(Dir).
  • 原子和变量,Erlang中变量以大写字母开头,小写字母开头的名称被称为原子,原子不是变量,而是符号常量,file_server程序中,list_dir,get_file,put_file都是原子而不是变量,模块名也是原子

  • spawn函数用于启动一个进程,并返回一个进程标识符。基本模式为spawn(, , [params])

  • self()获取当前进程的pid,erlang进程间通信依赖于pid

  • !用于向另一个进程发送消息,Erlang对现实的建模是通过这种轻量的进程间通信实现的,进程间交互使用消息。语法为 !

  • 接收消息,仅仅有发送消息是不够的,还需要接收消息的语法来完成基于消息的进程间通信,接受消息的语法如下。

    receive
        {From ,Message} ->
            Handle the message
    

From记录了消息的来源,Message是消息本身,后续是消息的处理逻辑

  • 多种消息的模式匹配,file_server的代码中可以看见,receive部分有多种模式,不同消息会进入到不同的处理代码中,于是这儿的模式是这样的。

    receive
        Parttern1 ->
            Actions1;
        Parttern2 ->
            Actions2
    %模式之间以;分隔,最后一种模式后面不能写;
    
  • 循环,Erlang是一种函数是编程语言,这意味着其逻辑结构是由一系列的函数演算构成的,和其他函数式语言类似,Erlang没有专门的循环语法,因此循环是通过递归实现的。file_server的代码中可以看见loop函数最后递归调用了自己。递归代码总会有递归栈占用过大的问题,编写成尾递归可以借由编译器的尾递归优化解决这一问题。

上述内容已经涵盖了erlang的基本知识,可以继续写出下面的file_client模块

%file_client.erl
-module(file_client).
-export([ls/1, get_file/2, put_file/3]).

ls(Server) ->
    Server ! {self(), list_dir},
    receive
        {Server, FileList} ->
            FileList
    end.

get_file(Server, File) ->
    Server ! {self(), {get_file, File}},
    receive
        {Server, Content} ->
            Content
    end.

put_file(Server, File, Content) ->
    Server ! {self(), put_file, File, Content}},
    receive
        {Server, Result} ->
            Result
    end.

file_client.el中没有引入新的内容,在shell中运行即可看见运行结果

$ erl
1> c(file_server).
{ok, file_server}
2> c(file_client).
{ok, file_client}
3> FS = file_server:start(".").
<0.45.0> 这是FS这个进程的pid
4> file_client:ls(FS).
{ok,["file_client.beam","file_client.erl",
     "file_server.beam","file_server.erl","hello.erl"]}
5> file_client:get_file(FS, "hello.erl").
{ok,<<"-module(hello).\n-export([start/0]).\n\nstart() ->\n    io:format(\"Hello World!~n\").\n">>}
6> file_client:put_file(FS, "haha", "hehe").
ok
7> file_client:ls(FS).
{ok,["afile_client.beam","afile_client.erl",
     "afile_server.beam","afile_server.erl","haha","hello.erl"]}
8> file_client:get_file(FS, "haha").
{ok,<<"hehe">>}

上述的file_server,file_client,涵盖了Erlang的基本语法,模式。下一篇文章会讲述Erlang语言在编写传统顺序程序时的用法。

你可能感兴趣的:(Hello Erlang!)