zoukankan      html  css  js  c++  java
  • 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 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">>
    • TupleList 最大的区别在于定长不定长(个人理解)

    运算符

    逻辑运算符
    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,可以使用 andalsoorels

    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 演示一下:

    并行

    参考资料:简书

  • 相关阅读:
    补发《超级迷宫》站立会议九
    补发《超级迷宫》站立会议八
    补发《超级迷宫》站立会议七
    补发《超级迷宫》站立会议六
    一周开发项目
    所学的内容
    开发项目和所用时间 感想
    自我介绍
    大容量数据转移操作命令——BULK INSERT(类似于BCP)
    字符编码与文件处理
  • 原文地址:https://www.cnblogs.com/qq188380780/p/13462540.html
Copyright © 2011-2022 走看看