makefile
使用变量
变量基础
makefile中的变量在声明时需要设置初始值,使用时需要在变量名前加"$" ,可以通过使用括号()或大括号{}包围变量名
示例:
代码语言:text复制test = c
pro.o: pro.$(test)
cc -c pro.$(test)
变量展开
不同于编程语言中变量的概念,Makefile中的变量更类似于c/c 中宏的概念,本质上是将变量的值替换到使用变量的地方
变量的嵌套
- Makefile支持将变量的值赋给变量
但为了防止变量的递归定义,可以使用":="操作符,使用":="操作符的变量, 将其他变量赋值给该变量时只能使用前面已经声明的变量。而"="操作符支持在使用变量进行赋值时,可以使用在该赋值语句之后声明的变量
- 也可在使用变量时进行嵌套操作
示例:
代码语言:text复制# 将变量赋值给变量 使用=操作符
# 可以使用在该语句之前或之后定义的变量
test_1 = $(test_3)
test_3 = $(test_4)
test_4 = c
# 将变量赋值给变量 使用:=操作符
# 仅能使用在该语句之前声明的变量
test_1 = c
test_3 := $(test_1)
# 使用嵌套变量
aaa = c
test = $($(aaa))
追加变量值
可以使用" ="操作符为变量追加值
如果变量未被定义,则" ="自动转变为"=",若变量已被定义,则会继承前次操作的赋值符
示例:
代码语言:text复制# 变量未被定义,自动转换为"="
test = a
# 变量test未声明过,因此 等价于 test = a
# 前次操作使用"="赋值,继承"="
test = k
test = $(a)
a = cc
# 变量test已声明过,因此,等价于 test = $(test) $(a) 可以使用之后声明的变量
# 前次操作使用":="赋值,继承":="
a = k
b = c
test := $(a)
test = $(b)
# 变量test已声明过,因此等价于 test := $(test) $(b) 只能使用之前声明的变量
override指令
可以重新设置make命令行设置的变量值,在define指令前,同样可以使用override指令
语法如下:
代码语言:text复制override <variable>; = <value>;
override <variable>; := <value>;
override <variable>; = <value>;
多行变量
可以通过define关键字设置变量,此时可以有换行,与命令包类似,值得注意的是,define中的命令要以[tab]开头,才能被识别为命令
示例:
代码语言:text复制# 其中命令未以[tab]开头,所以不会被识别命令
define two-lines
echo foo
echo $(bar)
endef
环境变量
make运行时可以获取到系统环境变量,也可以在make命令行中指定变量的值,或在Makefile中定义该变量,覆盖系统环境变量的值。
当make嵌套调用时,上层定义的变量会以环境变量的形式传递到下层make中。
(默认情况下,只有命令行中的变量会被传递,但Makefile中以export关键字声明的变量可以传递给下层make)
目标变量
可以为某个目标设置局部变量,称为目标变量
目标变量可以和全局变量重名,作用范围为当前规则及其连带规则中,不会影响规则链之外的全局变量的值
语法如下:
代码语言:text复制<target ...> : <variable-assignment>;
<target ...> : override <variable-assignment>;
模式变量
为匹配某一模式的目标定义目标变量
语法如下:
代码语言:text复制<pattern ...>; : <variable-assignment>;
<pattern ...>; : override <variable-assignment>;
示例:
代码语言:text复制%.o : CFLAGS = -0
rust
迭代器
惰性的迭代器
rust中的迭代器是惰性的,即在调用迭代器之前,不会有任何作用。
for循环与迭代器
for循环的底层隐式地使用了迭代器
迭代器的作用
任何语言中迭代器的作用都是类似的:
- 实现数据与抽象的分离
- 提供统一、可靠的遍历数据序列(sequence)的方式
- 无法对迭代器进行插入删除操作,限制使用者对数据的操作权限
Iterator trait 与 next方法
所有的迭代器都实现了定义于标准库的Iterator trait
定义如下:
代码语言:scss复制pub trait Iterator {
tyoe Item;
fn next(&mut self) -> Option<Self::Item>
//忽略了各种方法的默认实现
}
next方法是Iterator trait实现者必须实现的唯一方法,next方法一次返回迭代器中的一项,封装在Some中,而迭代器结束时,将返回None
消费适配器与迭代适配器
消费适配器
消费适配器即在Iterator trait 定义中调用了迭代器next方法的方法,如标准库实现的sum方法等
迭代适配器
- 迭代适配器即Iterator trait定义中能够对迭代器进行类型转换,返回另一个类型的迭代器的方法,如map方法等
- 大部分迭代器适配器都能够接受闭包作为参数,且该闭包能够捕获周围环境
迭代器与性能
与使用封装好了的容器而非底层数组的原因类似,迭代器能够提供更高层级的抽象,且性能与底层实现几乎一致:零开销或零成本抽象