如果一个变异函数设置它自己等于另一个函数,这意味着什么
What does it mean if a mutating function setting it's self equals to another function
我正在浏览 Apple 的 Arkit 项目示例。我一直在努力理解代码,因为我还在学习。我看到一个函数将其自身设置为另一个函数,有人可以解释一下这些函数到底在做什么吗?请在 detail.In 中简要说明 "mutating func normalize()" 将其自身设置为 self.normalized 的代码,这是为什么。这段代码在做什么。我们能不能简单地调用 "func normalized()" 好像我们正在重新创建相同的函数。
mutating func normalize() {
self = self.normalized()
}
func normalized() -> SCNVector3 {
if self.length() == 0 {
return self
}
return self / self.length()
}
func length() -> CGFloat {
return sqrt(self.x * self.x + self.y * self.y)
}
我假设此片段位于 struct
而不是 class。
self.normalized()
复制 self
并将副本的组件除以其长度,然后 returns 复制。 self
不受影响。
self.normalize()
获取 self
的规范化版本,然后用副本替换 self
。所以原地改变。
在幕后,每个成员函数都将 self
作为隐式参数传递。即对于编译器来说,声明看起来像这样:
func normalised(self: SCNVector3) -> SCNVector3
将 mutating
放在函数定义的前面会使隐藏参数 inout
func normalise(self: inout SCNVector3)
所以,如果你有
var a = SCNVector3(3, 4, 0)
let b = SCNVector3(4, 3, 0)
let c = b.normalized()
a.normalize()
在该代码之后,c
将是 (0.8, 0.6, 0)
,而 a
将是 (0.6, 0.8, 0)
。 b
将保持不变。
请注意,a
必须用 var
声明,因为它已被 normalise()
原地更改
编辑
汗在评论中提问:
What i am not able to understand is why do we have to create a func again we can use "func normalized"
重点是为什么我们不能做这样的事情:
var a = SCNVector3(3, 4, 0)
a = a.normalized()
根本没有normalise()
功能?
以上将与 a.normalize()
产生完全相同的效果,在我看来[1],是更好的风格,更 "functional"。
我认为 a.normalize()
存在只是因为它在 Swift 中很常见,以提供两种形式的功能。例如,对于集合,你有 union()
和 formUnion()
:第一个 returns 一个集合与另一个集合的并集,第二个用它自己和另一个集合的并集替换一个集合。在某些情况下,函数的就地版本可能更有效,但我认为,使用此 normalize
函数并非如此。
您选择使用哪种是您的喜好。
[1]其实更好的风格是
let a = SCNVector3(3, 4, 0).normalized()
Swift 中的值类型可以是可变的和不可变的。因此,当您创建 struct( 或任何其他值类型) 并将其分配给变量 (var) 时,它是可变的,您可以在其上调用 normalize() 。这意味着 struct 不会被复制到另一个内存中,并且会在适当的位置更新(就像引用类型一样)。但是当你将它分配给常量 (let) 时——它不能被改变,所以更新这个结构中的值的唯一方法是像 normalized() 方法一样创建一个具有更新值的新值。关于你的问题——normalize() 只是重用逻辑来规范化 normalized() 中的向量。所以这是完全好的解决方案。分配给 self 只允许在可变方法中使用。它基本上是用新的重写结构的值。
我正在浏览 Apple 的 Arkit 项目示例。我一直在努力理解代码,因为我还在学习。我看到一个函数将其自身设置为另一个函数,有人可以解释一下这些函数到底在做什么吗?请在 detail.In 中简要说明 "mutating func normalize()" 将其自身设置为 self.normalized 的代码,这是为什么。这段代码在做什么。我们能不能简单地调用 "func normalized()" 好像我们正在重新创建相同的函数。
mutating func normalize() {
self = self.normalized()
}
func normalized() -> SCNVector3 {
if self.length() == 0 {
return self
}
return self / self.length()
}
func length() -> CGFloat {
return sqrt(self.x * self.x + self.y * self.y)
}
我假设此片段位于 struct
而不是 class。
self.normalized()
复制 self
并将副本的组件除以其长度,然后 returns 复制。 self
不受影响。
self.normalize()
获取 self
的规范化版本,然后用副本替换 self
。所以原地改变。
在幕后,每个成员函数都将 self
作为隐式参数传递。即对于编译器来说,声明看起来像这样:
func normalised(self: SCNVector3) -> SCNVector3
将 mutating
放在函数定义的前面会使隐藏参数 inout
func normalise(self: inout SCNVector3)
所以,如果你有
var a = SCNVector3(3, 4, 0)
let b = SCNVector3(4, 3, 0)
let c = b.normalized()
a.normalize()
在该代码之后,c
将是 (0.8, 0.6, 0)
,而 a
将是 (0.6, 0.8, 0)
。 b
将保持不变。
请注意,a
必须用 var
声明,因为它已被 normalise()
编辑
汗在评论中提问:
What i am not able to understand is why do we have to create a func again we can use "func normalized"
重点是为什么我们不能做这样的事情:
var a = SCNVector3(3, 4, 0)
a = a.normalized()
根本没有normalise()
功能?
以上将与 a.normalize()
产生完全相同的效果,在我看来[1],是更好的风格,更 "functional"。
我认为 a.normalize()
存在只是因为它在 Swift 中很常见,以提供两种形式的功能。例如,对于集合,你有 union()
和 formUnion()
:第一个 returns 一个集合与另一个集合的并集,第二个用它自己和另一个集合的并集替换一个集合。在某些情况下,函数的就地版本可能更有效,但我认为,使用此 normalize
函数并非如此。
您选择使用哪种是您的喜好。
[1]其实更好的风格是
let a = SCNVector3(3, 4, 0).normalized()
Swift 中的值类型可以是可变的和不可变的。因此,当您创建 struct( 或任何其他值类型) 并将其分配给变量 (var) 时,它是可变的,您可以在其上调用 normalize() 。这意味着 struct 不会被复制到另一个内存中,并且会在适当的位置更新(就像引用类型一样)。但是当你将它分配给常量 (let) 时——它不能被改变,所以更新这个结构中的值的唯一方法是像 normalized() 方法一样创建一个具有更新值的新值。关于你的问题——normalize() 只是重用逻辑来规范化 normalized() 中的向量。所以这是完全好的解决方案。分配给 self 只允许在可变方法中使用。它基本上是用新的重写结构的值。