《函数式编程入门:使用 Elixir》笔记 2

学习 Elixir。

一些奇特语法点

1
2
3
4
5
[1, 2] ++ [3]
# => [1, 2, 3]

"Hello" <> ", World!"
# => "Hello, World!"

值包括 false 和 nil,而真值是除了假值以外的所有值。

1
2
3
4
5
6
7
8
true and false
# => false

true && "Hello, World!"
# => "Hello, World!"

1 || "Hello, World!"
# => 1

&& 运算符是另外一个版本的 and,不同之处在于它既可用于布尔值,也可以用于普通值。当第一个表达式为真值时,它返回第二个表达式的值,否则返回第一个。 || 运算符是另外一个版本的 or,它返回第一个真值,否则返回第二个表达式的值。

闭包

当我们定义函数引用函数作用域之外的变量时,变量绑定的当前值是不可变的。与此同时,外部作用域无法看到匿名函数内部定义的变量,且匿名函数只能看到在自己的定义之前定义的变量。这就是 Elixir 闭包的工作方式:可以在不使用参数的情况下与函数共享值。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
answer = 42
make_answer = fn -> other_answer = 88 + answer end

make_answer.()
# => 130

answer = 0

make_answer.()
# => 130

在函数内部,当一个变量被定义为一个函数的参数或者一个函数体中的局部变量的时候,它就是绑定变量同时他的值不会被记住,否则,它就是自由变量

Elixir 的具名函数定义在模块里。可以使用原子或者别名来命名模块。别名是任何以答谢字母开头的单词,但是只允许使用ASCII字符。所有的别名在编译的时候会转换为带有 Elixir 作为前缀的原子,如下所示:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
String == :"Elixir.String"
# => true

Float.ceil(3.6)
# => 4.0

:"Elixir.Float".ceil(3.6)
# => 4.0

# 调用具名函数可以省略括号
IO.puts "Good to hear"
IO.puts("Good to hear")

与匿名函数一样,具名函数将返回最后一个表达式的值。

一些命名规范

模块与函数、变量的命名约定不同。模块使用大驼峰式命名法,如ShoppingCart,而模块的文件名、函数名和变量名则是使用蛇形命名法,如shopping_cart.ex。在大型程序中,应用程序模块的名称和 Elixir 模块的名称容易混淆,所以建议在自定义模块的名称前面加上特定的名称来防止命名冲突。

模块的一些用法

1
2
3
4
5
defmodule TaskList do
  import File, only: [write: 3, read: 1]
# 这里的 3 和 1 是元数,即函数接受参数的数量。必须始终带上它的名字和它的形参数量。
# 如果不使用 only 关键字的话将会导入这个模块中的所有函数,这是不好的做法。
...

将具名函数作为值使用

如果希望像使用值一样的使用具名函数,如String.upcase/1,可以将函数包装在匿名函数中。

1
2
3
4
5
upcase = fn string -> Strign.upcase(string) end

# 等价于

upcase = &String.case/1

使用&运算符可以获取对具名函数的引用,但是传递给运算符的函数必须遵循 function/arity 的格式。与此同时,使用&可以创建匿名函数。

1
2
3
4
5
6
7
8
total_cost = &(&1 * &2)

# 等价于

total_cost = & &1 * &2

total_cost.(10, 2)
# => 20

注意:不能使用这种方式创建无参数的匿名函数。同时也要谨慎使用&运算符,有时候会影响可读性。

updatedupdated2023-12-052023-12-05