Swift 5 更新
在 Swift 5(尚未正式发布,但您可以获取 master snapshot)中,由于 #19062,此不一致已得到修复。您的代码现在输出以下内容:
functionLiteralTest.weirdo() // returns "weirdo()"
functionLiteralTest.weirdo(parameter: 1) // returns "weirdo(parameter:)"
functionLiteralTest.weirdo(1) // returns "weirdo(_:)"
functionLiteralTest.weirdo(1, 2) // returns "weirdo(_:_:)"
前 Swift 5
我同意这完全是令人费解的行为,但它确实似乎是故意的。
函数字面量在 SILGen 的过程中被“填充”;这是通过SILGenApply.cpp 中的SILGenFunction::emitLiteral 函数完成的。
然后调用getMagicFunctionString 获取函数字面量:
static StringRef
getMagicFunctionString(SILGenFunction &SGF) {
assert(SGF.MagicFunctionName
&& "asking for #function but we don't have a function name?!");
if (SGF.MagicFunctionString.empty()) {
llvm::raw_string_ostream os(SGF.MagicFunctionString);
SGF.MagicFunctionName.printPretty(os);
}
return SGF.MagicFunctionString;
}
如果尚未生成,则创建一个新流以输出到MagicFunctionString,并使用此流在MagicFunctionName 上调用DeclName::printPretty:
llvm::raw_ostream &DeclName::printPretty(llvm::raw_ostream &os) const {
return print(os, /*skipEmptyArgumentNames=*/true);
}
(MagicFunctionName被赋值为when the function is emitted;和is given the value ofgetFullName(),其中is just the Name的声明)
然后调用DeclName::print,它的第二个参数采用布尔参数来确定是否跳过列出的参数名称,如果它们都是空的:
llvm::raw_ostream &DeclName::print(llvm::raw_ostream &os,
bool skipEmptyArgumentNames) const {
// Print the base name.
os << getBaseName();
// If this is a simple name, we're done.
if (isSimpleName())
return os;
if (skipEmptyArgumentNames) {
// If there is more than one argument yet none of them have names,
// we're done.
if (getArgumentNames().size() > 0) {
bool anyNonEmptyNames = false;
for (auto c : getArgumentNames()) {
if (!c.empty()) {
anyNonEmptyNames = true;
break;
}
}
if (!anyNonEmptyNames)
return os;
}
}
// Print the argument names.
os << "(";
for (auto c : getArgumentNames()) {
os << c << ':';
}
os << ")";
return os;
}
您可以看到,由于 if 条件 if (getArgumentNames().size() > 0),没有参数的函数将跳过对所有空参数名称的检查,导致它们被发出 括号,例如 weirdo() .但是带有一个或多个参数的函数,所有参数名称都为空,会在没有括号的情况下发出,例如weirdo。
因此,鉴于 DeclName::printPretty 专门为 skipEmptyArgumentNames 参数传递了 true,看来 Swift 团队确实特别希望 #function 有这种行为。
此外,如果我们看一下blame,我们可以看到DeclName::printPretty被添加到this commit中,并带有提交消息:
通过删除没有关键字参数的漂亮打印 DeclNames
带括号的位。
不打印“f(_:_:)”,只打印“f”。
话虽如此,我仍然会file a bug report 处理它,因为它对于函数字面量来说似乎并不那么直观。