当前位置:  开发笔记 > 编程语言 > 正文

为什么在调用时不需要函数在Swift中的第一个参数名?

如何解决《为什么在调用时不需要函数在Swift中的第一个参数名?》经验,为你挑选了2个好方法。

我正在学习Swift,我觉得很奇怪为什么在调用函数时,第一个参数的名称不是必需的.

func say(greeting: String, toName: String) {
    print("\greeting), \(toName)!")
}

say("Goodbye", toName: "Hollywood") // <-- why is there no "greeting" required?

Crowman.. 16

正如其他人所说,这是源于Objective-C的风格问题.

要了解为什么有人想要这种风格,请考虑修改您的示例:

func say(greeting: String) {
    print("\(greeting)")
}

你会这样称呼:

say("Hello!")

当你看到你正在使用的名字时,可能会遗漏一些信息.使用一个被调用的函数say(),你可能会合理地认为这是一个让你说什么的功能.但是当你查看你的参数名称时,很明显这是一个说出问候语的功能,而不是说什么.

所以Objective-C希望你这样写:

func sayGreeting(greeting: String) {
    print("\(greeting)")
}

你会这样称呼:

sayGreeting("Hello!")

现在很清楚,你正在说一个问候.换句话说,函数名称本身更清楚地描述了您正在做的事情.出于这个原因,sayGreeting("Hello!")最好是say(greeting: "Hello!")因为函数所做的关键事情应该用它的名字来描述,而不是降级到参数名称并且具有次要的重要性.

但这个理由只适用于第一个论点.假设您要添加名称,就像您所做的那样.在像C这样的语言中,根本没有外部参数名,你可以写:

void sayGreetingToName(char * greeting, char * person) { ...

并称之为:

sayGreetingToName("Hello", "Dave");

这是可以的,但是当你有重载的函数或默认值时,它们会快速分解,你在C中都没有.如果你想写:

func sayGreetingToName(greeting: String, name: String? = nil) {
    if let name = name {
        print("\(greeting), \(name)!")
    }
    else {
        print("\(greeting)!")
    }
}

然后将其称为:

sayGreetingToName("Hello", "Dave")

看起来基本上没问题,但是:

sayGreetingToName("Hello")

看起来很荒谬,因为函数名称表示你提供了一个名字,但你不是.

所以相反,如果你写:

func sayGreeting(greeting: String, toName: String? = nil) {
    if let name = toName {
        print("\(greeting), \(name)!")
    }
    else {
        print("\(greeting)!")
    }
}

你可以用两种方式调用它:

sayGreeting("Hello")
sayGreeting("Hello", toName: "Dave")

一切看起来都很清楚.

总而言之,这种写作风格背后的想法是函数名称本身应该包含第一个参数的名称包含的任何信息,但是将它扩展到后续参数是没有意义的.所以默认情况下,第一个没有外部名称,但其余的都没有.这个函数一直都是关于一个问候语,所以这应该是函数名称中固有的(因此不能通过坚持第一个参数的外部名称来复制),但它可能会也可能不会说出来到特定名称,以便信息应该在函数名称中.

它还使您能够基本上读取函数调用,就像它是英语一样,因为名称和参数现在大致按照正确的顺序执行:

sayGreeting("Hello", toName: "Dave")

说(问候)"你好",给(名字叫"戴夫"的人)

一旦你习惯它,这是一个相当不错的风格.



1> Crowman..:

正如其他人所说,这是源于Objective-C的风格问题.

要了解为什么有人想要这种风格,请考虑修改您的示例:

func say(greeting: String) {
    print("\(greeting)")
}

你会这样称呼:

say("Hello!")

当你看到你正在使用的名字时,可能会遗漏一些信息.使用一个被调用的函数say(),你可能会合理地认为这是一个让你说什么的功能.但是当你查看你的参数名称时,很明显这是一个说出问候语的功能,而不是说什么.

所以Objective-C希望你这样写:

func sayGreeting(greeting: String) {
    print("\(greeting)")
}

你会这样称呼:

sayGreeting("Hello!")

现在很清楚,你正在说一个问候.换句话说,函数名称本身更清楚地描述了您正在做的事情.出于这个原因,sayGreeting("Hello!")最好是say(greeting: "Hello!")因为函数所做的关键事情应该用它的名字来描述,而不是降级到参数名称并且具有次要的重要性.

但这个理由只适用于第一个论点.假设您要添加名称,就像您所做的那样.在像C这样的语言中,根本没有外部参数名,你可以写:

void sayGreetingToName(char * greeting, char * person) { ...

并称之为:

sayGreetingToName("Hello", "Dave");

这是可以的,但是当你有重载的函数或默认值时,它们会快速分解,你在C中都没有.如果你想写:

func sayGreetingToName(greeting: String, name: String? = nil) {
    if let name = name {
        print("\(greeting), \(name)!")
    }
    else {
        print("\(greeting)!")
    }
}

然后将其称为:

sayGreetingToName("Hello", "Dave")

看起来基本上没问题,但是:

sayGreetingToName("Hello")

看起来很荒谬,因为函数名称表示你提供了一个名字,但你不是.

所以相反,如果你写:

func sayGreeting(greeting: String, toName: String? = nil) {
    if let name = toName {
        print("\(greeting), \(name)!")
    }
    else {
        print("\(greeting)!")
    }
}

你可以用两种方式调用它:

sayGreeting("Hello")
sayGreeting("Hello", toName: "Dave")

一切看起来都很清楚.

总而言之,这种写作风格背后的想法是函数名称本身应该包含第一个参数的名称包含的任何信息,但是将它扩展到后续参数是没有意义的.所以默认情况下,第一个没有外部名称,但其余的都没有.这个函数一直都是关于一个问候语,所以这应该是函数名称中固有的(因此不能通过坚持第一个参数的外部名称来复制),但它可能会也可能不会说出来到特定名称,以便信息应该在函数名称中.

它还使您能够基本上读取函数调用,就像它是英语一样,因为名称和参数现在大致按照正确的顺序执行:

sayGreeting("Hello", toName: "Dave")

说(问候)"你好",给(名字叫"戴夫"的人)

一旦你习惯它,这是一个相当不错的风格.



2> Marcus Rosse..:

Chris Lattner 在Swift 2中的新内容中谈到了这一点:

回到Swift 1.x时代,这种行为只适用于方法.在类,结构或枚举之外编写的函数不需要在函数调用中命名任何参数(除非您在函数定义中使用外部参数名称明确强制它).

由于Objective-C的约定,方法通常以某种方式命名,第一个参数已经是方法名称的一部分.
例如:indexOf(_:)代替index(of:)charactersAtIndex(_:)代替charactersAt(index:).
在Objective-C中,这将被写为indexOf:charactersAtIndex:.没有大括号可以将函数名与函数参数分开.因此参数基本上是函数名称的一部分.

如前所述,此行为最初仅适用于方法.这导致程序员之间的混淆,何时向第一个参数添加外部名称,何时不添加.所以最后行为被更改了,因此默认情况下第一个参数不使用内部名称作为外部名称,但所有以下参数都可以.
这导致外部和内部参数名称的使用更加一致.这就是今天Swift中存在的行为.

tl; dr行为是Objective-C的残余

推荐阅读
臭小子
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有