Learn You Some Erlang For Great Good笔记

语句

  • 动态,强类型,函数式范型,并发范型,actor并发模型
  • 卫语句:“;”和","和orelse,analso还是有区别的,前者即使前面的结果没匹配上,依然后执行后面的语句,而后者就不会了。

模块

函数的集合。

  • 模块: 函数和属性(预定义模块属性+自定义模块属性)。
    • 模块的设计要避免环形依赖。
    • 属性module必须放在最前面.
    • 属性import 破坏代码的可读性,强烈建议不适用这种属性。通常只有lists模块的函数会被引入,因为他用的比较频繁。
    • 学会使用属性 -ifdef(MACRO).,-else.和-endif 有条件的定义其他的属性。
    • 定义宏,包括“函数”宏.
    • 通过 Mod:module_info()可以查看所有的元数据。

模块

函数的集合。

  • 模块: 函数和属性(预定义模块属性+自定义模块属性)。
    • 模块的设计要避免环形依赖。
    • 属性module必须放在最前面.
    • 属性import 破坏代码的可读性,强烈建议不适用这种属性。通常只有lists模块的函数会被引入,因为他用的比较频繁。
    • 学会使用属性 -ifdef(MACRO).,-else.和-endif 有条件的定义其他的属性。
    • 定义宏,包括“函数”宏.
    • 通过 Mod:module_info()可以查看所有的元数据。

函数

函数,参数,返回结果。

  • 函数的模式匹配:善用模式匹配,可以避免多层if else,case 的使用,让代码更优美。使用模式匹配的函数 是先匹配参数,再给参数赋值;而if else,case的使用是先赋值,再比较。
  • 模式匹配搭配卫语句使用:卫语句不能使用自定义的函数。
  • true 在 if end 语句中的使用.

类型

erlang 是动态强类型语言。

  • erlang 是动态类型语言,所有错误都在运行时被捕获,在编译代码时,对于可能导致失败的问题,编译器并不总是会给出警告。 但是erlang的动态类型系统不是程序可靠性和安全性的障碍。这得益于它的容错性;同时,动态类型也是实现热更新最简单的办法。
  • 如果你是一个静态类型拥护者,erlang 提供了Dialyzer可以进行静态类型分析,及早发现错误。
  • erlang 是强类型语言,不允许像弱类型语言会在不同的数据项之间隐式的类型装换。但是为了适应类型装换的需要,erlang专门 提供了一些 类型检测类型装换 的BIF函数。
  • erlang 不提供 type_of(X) -> Type 这样的函数是因为:erlang 只针对正确的情况编程,你的程序只需要处理那些你知道肯定会 发生以及所期望的情况,对于除此以外的其他情况,都应该尽快排除异常。

递归 - 更优雅的循环

函数式变成通常没有类似for,while这样的循环结构,但提供了递归来实现循环。

  • 递归的两点:停止条件;调用自己。
  • 递归的问题:每次执行的结果都会保存到内存中,如果列表长度很长,那么就要把一大堆数据放到内存中,这很好内存,为了 解决这个问题,可以使用尾递归实现(增加一个累加器,将每次计算的结果放在累加器中)。
  • 尾递归:两个参数不同的函数;增加累加器参数,每次执行之后更新累加器;将剩余的数继续调用自身函数。
  • 尾递归有时候需要翻转列表才能和原列表顺序匹配。

高阶函数

在数学和计算机中,高阶函数是至少满足下列一个条件的函数:接收一个或多个函数作为输入;输出一个函数。

  • 高阶函数:所有函数是语言都有一个特性:把自定义的函数作为参数传递给另外一个函数,这个函数会被绑定到一个变量上, 就像使用变量一样使用这个函数。如果一个函数的参数时这样传递过来的那么这就是一个高阶函数。
  • 高阶函数的参数:函数表示成参数(Module:Function/Arity,告诉虚拟机具体执行哪个函数并把这个函数绑定到一个变量上)。
  • 函数的作用域和闭包:是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环 境也不例外。也就是,当匿名函数,作用域的概念和可以携带变量的能力结合在一起时,就产生了闭包。

错误和异常

erlang 处理错误的机制和并发是有关联的。

  • 关于异常
    • 错误有:编译期错误(语法错误);逻辑错误;运行时错误(会导致程序崩溃)。这里主要讨论运行时错误。
    • erlang 三种异常:出错(error),退出(exit),抛出(throw)。
    • error (调用erlang:error/1时触发) 会结束当前进程的执行。所以不想让进程崩溃的异常不要使用这种方式;可以自定义错误。
    • exit (erlang:exit/1 内部退出, erlang:exit/2 外部退出): 进程退出之后会发送一条消息给接收者。
    • exit: 接收exit消息的进程如果没有traping exits,那么接收进程也会退出;如果traping exits,退出信号会转化为{'EXIT', From, Reason}送到进程邮箱中。
    • error 和 exit:捕获error异常会得到最后几次函数调用的栈跟踪和参数列表, 而exit/1不会返回调用栈,因为如果调用栈很深 就意味着退出进程把这个消息复制给所有监听进程就要复制很多消息,这不现实。
    • throw: 当期待程序员处理所发生的异常的时候,可以抛出异常throw。相比error和exit,throw没有"让进程崩溃"的意思。
    • 通常在深度递归中内部返回throw,由顶层catch异常后处理该异常。
  • 处理异常
    • 三种异常都可以通过 try ... catch ... 处理。默认 catch 得到 Type:Exception 消息,如果没有 Type, 默认就有 throw 的信息。
    • try of catch 中被保护部分不能做尾递归。

Comments

comments powered by Disqus