Swift-style-guide: 函数与方法

创建于 2015-07-06  ·  26评论  ·  资料来源: raywenderlich/swift-style-guide

该指南应明确说明在编写时如何正确使用函数和方法。 看了一下 Apple 的 Swift Programming Language 文档,例如:

方法是与类、结构或枚举相关联的函数。 这适用于实例和类型方法。 另一方面,函数是在全局范围内声明的,不属于任何类型。

就足够了。

最有用的评论

这样的事情怎么样:

方法与自由函数

方法是与类型相关联的函数,并且由于它们的自动完成可发现性而被首选。 自由函数不太常见,但在操作与特定类型或实例没有密切关联时有意义。

首选

let sorted = items.mergeSort()  // easily discoverable
rocket.launch()  // a mutating method

不喜欢

let sorted = mergeSort(items)
launch(&rocket)

自由函数异常

let tuples = zip(a, b)  // feels natural as a free function (symmetry)
let value = max(x,y,z)  // another free function that feels natural

所有26条评论

我还看到了被称为“自由函数”的函数。 我假设“免费”的意思是“不与任何对象相关联”。

在 Swift 中,函数具有比类型和全局更多的范围选项。

我只是假设Objective-C中的正常方法现在被称为functiona中的Swift 。 我在论坛、博客、教程等方面阅读过的所有材料都将它们简称为functions ,即使它们属于一个类或一个枚举。

@mitchellporter Apple 自己的文档清楚地说明了什么时候应该将某些东西称为函数或方法,如上面的引用所示。

raywenderlich.com 上的教程也遵循 Apple 的指南,这就是为什么它应该被纳入风格指南。

Objective-C 中也有函数和方法; 不是一切都是方法。 😉

@micpringle有道理,但我发誓我读过很多材料,即使它属于一个类,他们也只是简单地将其称为function 。 我猜我不是唯一一个总是使用function ,看看这是否会发生变化会很有趣。

方法中的“函数”是“嵌套方法”吗?
闭包或其他非函数中的函数是什么?

struct Struct {
   let closure = {
      func whoAmI() {}
   }

   var any: Any? {
      func jeanValjean() {}
      return nil
   }
}

我认为这些将被归类为匿名函数 (IMO),因为从技术上讲它们不“属于”任何东西,并且它们只存在于该特定范围内,无法从外部访问。

我不认为“匿名函数”是这里的正确名称——通常指的是闭包。

我将它们称为“嵌套函数”:“函数”,因为它们是函数,而不是附加到命名类型或实例的方法。 并且“嵌套”是因为……它们是嵌套的! 也许是“作用域函数”,但这似乎不太清楚。

抱歉,我没有意识到闭包也被称为匿名函数。 :]

嵌套函数对我来说听起来不错。 我同意 scoped 听起来不太对。

我认为任何东西中的“嵌套函数”,无论是否是一种方法,在可预见的未来似乎都足够清楚了。

虽然我确实认为具有名称的嵌套函数使它们成为“匿名”,但我不清楚究竟什么是“匿名”,但是,当涉及到闭包时,尤其是存储的、不可变的,它们非常像函数。 我倾向于相信存储的函数确实是匿名的,但是捕获它的闭包,可能还有一些状态,就是它的名字。 这就是 C# 的教学方式,其中 lambda 语法是构造它所谓的委托的简写。
https://msdn.microsoft.com/en-us/library/system.delegate (v=vs.110).aspx

func nonymous() {
   func nonymous() {}
}

let anonymouses: [() -> ()] = [].map
{$0} // This "transform" is also anonymous.

let unlcearToMeWhetherNonymous = {}

这是一个微妙的观点,甚至可能在你深入了解 Swift 的内部并且一切都相同时甚至是没有实际意义的,但是用func声明某些东西肯定会给这个东西一个名字。 相比之下,闭包只是一些没有名称的代码块。 当然,您可以将其分配给变量或常量,但这只是存储指向该事物的指针。

同样,这是一种人为的差异。 你可以像 lisp 一样说func只是给闭包命名的语法糖。

这样的事情怎么样:

方法与自由函数

方法是与类型相关联的函数,并且由于它们的自动完成可发现性而被首选。 自由函数不太常见,但在操作与特定类型或实例没有密切关联时有意义。

首选

let sorted = items.mergeSort()  // easily discoverable
rocket.launch()  // a mutating method

不喜欢

let sorted = mergeSort(items)
launch(&rocket)

自由函数异常

let tuples = zip(a, b)  // feels natural as a free function (symmetry)
let value = max(x,y,z)  // another free function that feels natural

关于,

自由函数异常

let tuples = zip(a, b)  // feels natural as a free function (symmetry)
let value = max(x,y,z)  // another free function that feels natural

“感觉自然”是相当模糊和主观的。

我们能澄清一下我们在这里的意思吗?

此外, zipmax也会受到您在 PR 中提出的// hard to discover问题的困扰。

恕我直言,我认为zip是一个尴尬的例子。 我遇到的问题:

  • 它实际上_在做什么_? 结合ab ? 以某种方式压缩ab ? 还有什么? 没有更多的背景,很难知道。

代替

自由函数不太常见,但在操作与特定类型或实例没有密切关联时有意义。

这个怎么样?

未附加到类或类型的自由函数应谨慎使用。 如果可能,最好使用方法而不是自由函数。 这有助于提高可读性和可发现性。

当自由函数不与任何特定类型或实例相关联时,它们是最合适的。

我重新打开这个问题以寻求对Free Function Exceptions进一步讨论。

嗯,这是一个标准的库函数。 它在 R、Python、C#、C++ 等语言中具有优先权。(通过 boost)。

嗯,这是一个标准的库函数。

真的吗? 我没有在 iOS 中使用过它... * 尴尬 *

我会检查一下......如果它在iOS上被广泛理解/使用,也许我在这里的担忧是错误的......

我喜欢你的措辞建议......我不愿意放弃 zip 示例。 (PS:RW Swift 团队有一个比 iOS 更大(或更小)的章程。)

RW Swift 团队的章程比 iOS 大(或小)。

👍没错。 ;]

在回顾了 zip 的作用之后,我

在这里对我的 Swift 新手体验表示歉意。 😉

不用担心。 感谢您一如既往的帮助。 顺便说一句,我只是注意到你没有在学分中提到。 我也会解决这个问题。

我不确定免费功能是否是最好的解决方案。 如果使用它们,我认为它们应该添加其他地方没有解决的功能。

最大限度

let max = Swift.max(0, 1, 2)
let maxElement = [0, 1, 2].maxElement()!

maxElement应该是一个属性,而不是一个方法,但是我还是觉得free函数是多余的。 如果这些不能编译成相同的东西,那么我认为应该改进编译器,但即使不是,我认为性能也无关紧要; 我不认为人们会使用包含许多元素的 max 函数。

压缩
在 C# 中,zip 实现为等效于 Swift 协议扩展方法。 我不认为这更好,但它是如何以不同方式处理zip的示例。

在 Swift 中, zipZip2Sequence初始值设定项相同。 有一种方法来表示可变数量的输入序列的压缩序列会很好,但在此之前,我认为直接使用初始化程序很好。

zip([1...3], ["a"..."c"])
Zip2Sequence([1...3], ["a"..."c"])

运营商
我用 Swift 编写的绝大多数免费函数都是运算符。 我已经看到 Chris Lattner 和 Joe Groff 建议运算符将能够在类型中定义,就像 C#,在未来,所以运算符也可以遵循选择的任何约定,然后用于其他函数。 他们目前作为自由功能的实现可能不应该被用作指导方针。

运营商
我用 Swift 编写的绝大多数免费函数都是运算符。 我已经看到 Chris Lattner 和 Joe Groff 建议将来可以在类型中定义运算符,à la C#...

是的,这很可能是 Swift 未来的发展方向。 正如你所提到的,这是 Chris Lattner 最近提出的提案

这对于像Equatable这样的协议来说尤其特殊,根据我们的扩展指南,基本上_要求_您创建一个空扩展。 这充其量是尴尬的。 😞

我绝对同意应该将运算符用作理想自由函数的示例。

感谢@Jessy- 的评论!

一些注意事项:

我认为maxElement()被声明为一种方法,因为它不是 O(1),这可能会让某些用户感到惊讶。 如果您实现的属性不是 O(1),则需要清楚地记录下来。 (在 RW 教程中,我们有幸将所有代码公开,因此我们不必担心或将其作为风格指南强制执行。)

另一方面,某些形式的max<T: Comparable>是 O(1) 并且具有专门利用硬件的潜力。 (我猜这就是为什么除了可变参数版本之外还有两个参数版本的原因,尽管我还没有确认。)

无论如何,我认为我们都同意应该谨慎使用免费功能,但我会反对_从不_。 使用的示例来自标准库。 我还没有看到任何从标准库中删除zip函数的建议。 是否对@JRG-Developer 改写的细节或当前合并的拉取请求以这种改写为模数有异议?

如果您认为还有什么需要进一步讨论,请随时重新打开。 (合并到更新分支。)

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

sima-11 picture sima-11  ·  5评论

samkim102 picture samkim102  ·  4评论

rwenderlich picture rwenderlich  ·  29评论

WingYn picture WingYn  ·  15评论

hollance picture hollance  ·  28评论