zoukankan      html  css  js  c++  java
  • Erlang入门(五)——补遗

     暂时搞不到《Programming Erlang》,最近就一直在看Erlang自带的例子和Reference Manual。基础语法方面有一些过去遗漏或者没有注意的,断断续续仅记于此。

    1。Erlang的保留字有:

    after and andalso band begin bnot bor bsl bsr bxor case catch cond div end fun if let not of or orelse query receive rem try when xor

    基本都是些用于逻辑运算、位运算以及特殊表达式的符号

    2.Erlang的类型,除了在前面入门一提到的类型外,还包括:
    1)Binary,用于表示某段未知类型的内存区域
    比如:
    1> <<10,20>>. 
    <<10,20>> 
    2> <<"ABC">>.
     <<65,66,67>> 

    2)Reference,通过调用mk_ref/0产生的运行时的unique term

    3)String,字符串,Erlang中的字符串用双引号包括起来,其实也是list。编译时期,两个邻近的字符串将被连接起来,比如"string" "42" 等价于 "string42"

    4)Record,记录类型,与c语言中的struct类似,模块可以通过-record属性声明,比如:
    -module(person). 
    -export([new/2]).
    -record(person, {name, age}). 
    new(Name, Age) ->
         #person{name=Name, age=Age}. 
    1> person:new(dennis, 44). 
    {person,dennis,44} 
     在编译后其实已经被转化为tuple。可以通过Name#person.name来访问Name Record的name属性。

    3.模块的预定义属性:
    -module(Module).    声明模块名称,必须与文件名相同
    -export(Functions).   指定向外界导出的函数列表
    -import(Module,Functions).   引入函数,引入的函数可以被当作本地定义的函数使用
    -compile(Options).     设置编译选项,比如export_all
    -vsn(Vsn).         模块版本,设置了此项,可以通过beam_lib:version/1 获取此项信息
    可以通过-include和-include_lib来包含文件,两者的区别是include-lib不能通过绝对路径查找文件,而是在你当前Erlang的lib目录进行查找。

    4.try表达式,try表达式可以与catch结合使用,比如:

    try Expr
    catch
    throw:Term -> Term;
    exit:Reason -> {'EXIT',Reason}
    error:Reason -> {'EXIT',{Reason,erlang:get_stacktrace()}}
    end

    不仅如此,try还可以与after结合使用,类似java中的try..finally,用于进行清除作用,比如:
    termize_file(Name) -> {ok,F} = file:open(Name, [read,binary]), try {ok,Bin} = file:read(F, 1024*1024), binary_to_term(Bin) after file:close(F) end.

    5.列表推断(List Comprehensions),函数式语言特性之一,Erlang中的语法类似:
    [Expr || Qualifier1,...,QualifierN] Expr可以是任意的表达式,而Qualifier是generator或者filter。还是各举例子说明下。
    1> [X*2 || X <- [1,2,3]]. [2,4,6]

    2> L=[1,2,3,4,5,6,7].
    [1,2,3,4,5,6,7]
    3> [X|X<-L,X>=3].
    [3,4,5,6,7]

    再看几个比较酷的例子,来自Programming Erlang
    比如快速排序:
    -module(qsort).
    -export([qsort/1]).
    qsort([])->[];
    qsort([Pivot|T])->
      qsort([X||X<-T,X<Pivot])
       ++ [Pivot] ++
      qsort([X||X<-T,X>=Pivot]).

    搜索勾股数组:
    %勾股数组
    -module(pythag).
    -export([pythag/1]).
    pythag(N)->
        L=lists:seq(1,N),
        Square=fun(X) when is_number(X)->X*X end,
        [{A,B,C}||
            A<-L,
            B<-L,
            C<-L,
            A+B+C=<N,
            Square(A)+Square(B)=:=Square(C)].
    列表推断将大大减少你的敲击键盘的次数。
     
    6.宏,定义常量或者函数等等,语法如下:
    -define(Const, Replacement). -define(Func(Var1,...,VarN), Replacement).
    使用的时候在宏名前加个问号?,比如?Const,Replacement将插入宏出现的位置。系统预定义了一些宏:
    ?MODULE 表示当前模块名

    ?MODULE_STRING 同上,但是以字符串形式
    ?FILE 当前模块的文件名
    ?LINE 调用的当前代码行数
    ?MACHINE 机器名

    Erlang的宏与C语言的宏很相似,同样有宏指示符,包括:
    -undef(Macro).
    取消宏定义
    -ifdef(Macro).
    当宏Macro有定义的时候,执行以下代码
    -ifndef(Macro).
    同上,反之
    -else.
    接在ifdef或者ifndef之后,表示不满足前者条件时执行以下代码
    -endif.
    if终止符
    假设宏-define(Square(X),X*X).用于计算平方,那么??X将返回X表达式的字符串形式,类似C语言中#arg

    一个简单的宏例子:
    -module(macros_demo).
    -ifdef(debug).
    -define(LOG(X), io:format("{~p,~p}: ~p~n", [?MODULE,?LINE,X])).
    -else.
    -define(LOG(X), true).
    -endif.
    -define(Square(X),X*X).
    -compile(export_all).
    test()->
        A=3,
        ?LOG(A),
        B=?Square(A),
        io:format("square(~w) is ~w~n",[A,B]).
    当编译时不开启debug选项的时候:
    17> c(macros_demo).
    {ok,macros_demo}
    18> macros_demo:test().
    square(3) is 9

    当编译时开启debug之后:

    19> c(macros_demo,{d,debug}).
    {ok,macros_demo}
    20> macros_demo:test().
    {macros_demo,11}: 3
    square(3) is 9
    ok

    可以看到LOG的输出了,行数、模块名以及参数
    7、Process Dictionary,每个进程都有自己的process dictionary,用于存储这个进程内的全局变量,可以通过下列
    BIFs操作:
    put(Key, Value)
    get(Key)
    get()
    get_keys(Value)
    erase(Key)
    erase()

    8、关于分布式编程,需要补充的几点
    1)节点之间的连接默认是transitive,也就是当节点A连接了节点B,节点B连接了节点C,那么节点A也与节点C互相连接
    可以通过启动节点时指定参数-connect_all false来取消默认行为

    2)隐藏节点,某些情况下,你希望连接一个节点而不去连接其他节点,你可以通过在节点启动时指定-hidden选项
    来启动一个hidden node。在此情况下,通过nodes()查看所有连接的节点将不会出现隐藏的节点,想看到隐藏的节点
    可以通过nodes(hidden)或者nodes(connected)来查看。

    完整的erl选项如下:
    -connect_all false 上面已经解释。
    -hidden 启动一个hidden node
    -name Name 启动一个系统成为节点,使用long name.
    -setcookie Cookie Erlang:set_cookie(node(), Cookie).相同,设置magic cookie
    -sname Name 启动一个Erlang系统作为节点,使用short name 

    注意,short name启动的节点是无法与long name节点通信的。

    9.一个小细节,在Erlang中小于等于是用=<表示,而不是一般语言中的<=语法,我犯过错误的地方,同样,不等于都是用/号,而不是
    !,比如/=、=/=。

    10.and or 和andalso orelse的区别

    and和or会计算两边的表达式,而andalso和orelse的求值采用短路机制,比如exp1 andalso exp2,当exp1返回false之后,就不会去求值
    exp2,而是直接返回false,而exp1 and exp2会对exp1和exp2都进行求值,or与orelse也类似。
     
    今天在erlang-china下到了《Programming Erlang》,准备打印一份看看,进入OTP的学习。  
  • 相关阅读:
    5种Python使用定时调度任务的方式
    基于Tensorflow + Opencv 实现CNN自定义图像分类
    CANN 5.0硬核技术抢先看
    大力出奇迹,揭秘昇腾CANN的AI超能力
    MSQL:超强的多任务表示学习方法
    Shell:Lite OS在线调试工具知多少
    带你掌握Vue过滤器filters及时间戳转换
    Selenium系列(六) 详细解读强制等待、隐式等待、显式等待的区别和源码解读
    Linux常用命令 top命令详解(重点)
    Selenium系列(一) 详细解读8种元素定位方式
  • 原文地址:https://www.cnblogs.com/xuan52rock/p/4597943.html
Copyright © 2011-2022 走看看