我也不知道中文怎么翻译。还是直接看代码吧。
比如说我们有个加法容器类,定义如下:
struct Adder {
var base: Int
func applied(_ x: Int) -> Int {
return base + x
}
}
我们创建一个+3的加法器,然后计算10+3:
let add3 = Adder(base: 3)
let sum = add3.applied(10) // => 13
看起来很简单,代码也不多。但看这种情况:
let sum1 = adds.applied(adds.applied(adds.applied(10))) // => 19
嵌套几层,applied就出现几次,看着还是挺乱的。这个新特性就是用来解决这种冗余的。怎么做呢?这里引入了一个语法糖。让我们重新定义下Adder这个结构体:
struct Adder {
var base: Int
func callAsFunction(_ x: Int) -> Int {
return base + x
}
}
把原来做加法的函数名变为"callAsFunction"就可以了。然后我们就可以这样进行加法计算:
let add3 = Adder(base: 3)
let sum = add3(10) // => 13
let sum1 = add3(add3(add3(10))) // => 19
// let sum1 = adds.applied(adds.applied(adds.applied(10)))
和原来比起来是不是更加简短了些,而且套用层数越多效果越明显。
可能很多人在开发iOS应用的时候遇不到太多这种一个方法多层嵌套的场景,所以对于这种语法糖性质的新特性感受不深。这里再借用一个官方给的关于深度神经网络的例子:
struct Model {
var conv = Conv2D<Float>(filterShape: (5, 5, 3, 6))
var maxPool = MaxPool2D<Float>(poolSize: (2, 2), strides: (2, 2))
var flatten = Flatten<Float>()
var dense = Dense<Float>(inputSize: 36 * 6, outputSize: 10)
// 上面的四个变量都不用理,看这个方法
func applied(to input: Tensor<Float>) -> Tensor<Float> {
// 看这里的applied(to:)有多冗余
return dense.applied(to: flatten.applied(to: maxPool.applied(to: conv.applied(to: input))))
}
}
大家都知道,深度神经网络的特点就是有很多层,上一层的输出再作为下一层的输入,进行一个非线性变换之后输出再作为下一层的输入。于是我们看到上面的模型中返回的Tensor就是多层嵌套的结构。这时我们应用前面提到的新特性,去掉这个applied(to:),那这个嵌套会变得更加清晰可读。我们比照上面的例子,将上面Model里面的方法名用语法糖替换下:
func callAsFunction(_ input: Tensor<Float>) -> Tensor<Float> {
// 这个嵌套简单清晰多了
return dense(flatten(maxPool(conv(input))))
}
好吧,就是这么简单。
网友评论