函数体是代码块
代码块do...end是一种表达式的组织方式。
# ./times.exs下
defmodule Times dodef doule(n) don * 2end end
函数调用与模式匹配
代码如下:
# ./factorial.exs 计算阶层 defmodule Factorial dodef of(0), do: 1 #终止条件要写在上面,否则永远都不会被执行到def of(n), do: n * of(n - 1) end
哨兵子句
代码如下:
defmodule Guard dodef what_is(x) when is_number(x) doIO.puts "#{x} is a number"enddef what_is(x) when is_list(x) doIO.puts "#{x} is a list"enddef what_is(x) when is_atom(x) doIO.puts "#{x} is an atom"end end
它们由一个或多个when关键字紧接在函数定义后的断言。当执行时,先执行基于参数的匹配,然后评估所有的when断言。
哨兵子句不支持||和&&
默认参数
定义函数名时,可以用param \\ value 的语句给任意参数指定默认值。
# ./default_param.exs defmodule Example dodef func(p1, p2 \\ 2, p3 \\ 3, p4) doIO.inspect [p1, p2, p3, p4]end endExample.func("a", "b") #=> ["a", 2, 3, "b"] Example.func("a", "b", "c") #=> ["a", "b", 3, "c"] 从从左到右匹配 Example.func("a", "b", "c", "d")
有可能会出现以下错误:
def func(p1, p2 \\ 2, p3 \\ 3, p4)def func(p1, p2) #传入两个参数时,第二个函数永远无法被调用,报错def func(p1, p2 \\ 123) #传入两个参数时,也是如此
def func(p1, p2)
可以添加一个包含默认参数,且只有函数头部分没有函数体的函数,而其余的使用普通函数,那些默认值就会被应用到对此函数的所有调用上
#省略部分内容
def func(p1, p2 \\ 123)def func(p1, p2) when ...def func(p1, p2) ...
|>管道运算符
|>将左边表达式的结果,将其作为第一个参数传递给右边的函数调用
people = DB.find_customers orders = Orders.for_customers(people) tax = sales_tax(orders, 2013) filing = prepare_filing(tax) #可以写为 filing = DB.find_customers|> Orders.for_customers|> sales_tax(2013)|> prepare_filingval |> f( a, b ) 等价于 f( val, a, b)
模块
模块为定义的内容提供了命名空间。它可以用来封装命名函数,还可以封装宏、结构体、协议和其他模块
模块指令
其作用域以指令出现处作为起点,直到当前模块结束
import,将模块内的函数或宏引入到当前作用域。比如,如果从List模块导入flatten函数,可以直接调用它而无需指定其模块名。完整语法为:import Module [, only: | except ]
defmodule Example dodef func1 do #将import写到这里 fun2也能正常使用List.flatten [1, [2, 3], 4]enddef fun2 doimport List, only: [flatten: 1]flatten [5, [6, 7], 8]end end
alias,为模块创建别名。目的为减少输入
defmodule Example dodef func doalias Mix.Task.Doctest, as: Doctestdoc = Doctest.setupdoc.run(Doctest.defaults)end end
require,reqiire指令确保在代码使用宏之前,加载定义这些宏的模块。
模块属性
每个Elixir模块都有与之关联的元数据。元数据的每一项称之为模块的属性,并且有自己的名字。在模块内部我们可以在其名称前加@访问这些属性,可以同此语法为属性赋值:@name value,在函数内部不能设置属性
defmodule Example do@author "Lr"def get_author od@authorend end
若多次为属性赋值,在命名函数内部访问该属性,其值为定义函数时属性的当前值。
模块名Elixir
在内部,模块名仅仅是原子类型。比如,当我们写IO时,Elixir内部将其转化为原子类型Elixir.IO
is_atom IO #true to_string IO #"Elixir.IO" "Elixir.IO" === IO #true"Elixir.IO".puts 123 #123 :ok