我发现 Swift 3.1 中 #function 文字返回的 String 很奇怪。这里:
class FunctionLiteralTest {
func weirdo() -> String {
return #function
}
func weirdo(parameter: Int) -> String {
return #function
}
func weirdo(_ parameter: Int) -> String {
return #function
}
func weirdo(_ parameter: Int, _ anotherParameter: Int) -> String {
return #function
}
}
let functionLiteralTest = FunctionLiteralTest()
functionLiteralTest.weirdo() // returns "weirdo()"
functionLiteralTest.weirdo(parameter: 1) // returns "weirdo(parameter:)"
functionLiteralTest.weirdo(1) // returns "weirdo"
functionLiteralTest.weirdo(1, 2) // returns "weirdo"
当所有参数都未标记时,括号将被完全跳过。如果 #function 也为没有任何参数的函数返回不带括号的函数名,我会非常理解。
这是合理的行为还是错误?
最佳答案
在 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(_:_:)"
我同意这是完全令人费解的行为,但它似乎是故意的。
函数文字在 SILGen 的过程中得到“填充”;这是通过 SILGenFunction::emitLiteral 完成的在 SILGenApply.cpp 中发挥作用.
然后调用 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,并调用 DeclName::printPretty在 MagicFunctionName 上使用此流:
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 of getFullName(),即声明的 is just the Name)
然后调用 DeclName::print ,作为它的第二个参数,它采用 bool 参数来确定是否跳过列出参数名称,如果它们都是空的:
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,我们可以看到在 this commit 中添加了 DeclName::printPretty ,带有提交消息:
Pretty-print DeclNames with no keyword arguments by dropping the parenthsized bit.
Instead of printing "
f(_:_:)", just print "f".
话虽如此,我还是会file a bug report超过它,因为对于函数文字来说它似乎并不那么直观。
关于swift - Swift 3.1 中#function 文字的奇怪值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45086137/
我有一大串格式化数据(例如JSON),我想使用Psychinruby同时保留格式转储到YAML。基本上,我希望JSON使用literalstyle出现在YAML中:---json:|{"page":1,"results":["item","another"],"total_pages":0}但是,当我使用YAML.dump时,它不使用文字样式。我得到这样的东西:---json:!"{\n\"page\":1,\n\"results\":[\n\"item\",\"another\"\n],\n\"total_pages\":0\n}\n"我如何告诉Psych以想要的样式转储标量?解
对于作为String#tr参数的单引号字符串文字中反斜杠的转义状态,我觉得有些神秘。你能解释一下下面三个例子之间的对比吗?我特别不明白第二个。为了避免复杂化,我在这里使用了'd',在双引号中转义时不会改变含义("\d"="d")。'\\'.tr('\\','x')#=>"x"'\\'.tr('\\d','x')#=>"\\"'\\'.tr('\\\d','x')#=>"x" 最佳答案 在tr中转义tr的第一个参数非常类似于正则表达式中的括号字符分组。您可以在表达式的开头使用^来否定匹配(替换任何不匹配的内容)并使用例如a-f来匹配一
我正在使用Rails3.1并在一个论坛上工作。我有一个名为Topic的模型,每个模型都有许多Post。当用户创建新主题时,他们也应该创建第一个Post。但是,我不确定如何以相同的形式执行此操作。这是我的代码:classTopic:destroyaccepts_nested_attributes_for:postsvalidates_presence_of:titleendclassPost...但这似乎不起作用。有什么想法吗?谢谢! 最佳答案 @Pablo的回答似乎有你需要的一切。但更具体地说...首先改变你View中的这一行对此#
使用rspec-rails3.0+,测试设置分为spec_helper和rails_helper我注意到生成的spec_helper不需要'rspec/rails'。这会导致zeus崩溃:spec_helper.rb:5:in`':undefinedmethod`configure'forRSpec:Module(NoMethodError)对thisissue最常见的回应是需要'rspec/rails'。但这是否会破坏仅使用spec_helper拆分rails规范和PORO规范的全部目的?或者这无关紧要,因为Zeus无论如何都会预加载Rails?我应该在我的spec_helper中做
有没有人用ruby解决这个问题:假设我们有:a=8.1999999我们想将它四舍五入为2位小数,即8.20,然后乘以1,000,000得到8,200,000我们是这样做的;(a.round(2)*1000000).to_i但是我们得到的是8199999,为什么?奇怪的是,如果我们乘以1000、100000或10000000而不是1000000,我们会得到正确的结果。有人知道为什么吗?我们正在使用ruby1.9.2并尝试使用1.9.3。谢谢! 最佳答案 每当你在计算中得到时髦的数字时使用bigdecimalrequire'bi
这段代码似乎创建了一个范围从a到z的数组,但我不明白*的作用。有人可以解释一下吗?[*"a".."z"] 最佳答案 它叫做splatoperator.SplattinganLvalueAmaximumofonelvaluemaybesplattedinwhichcaseitisassignedanArrayconsistingoftheremainingrvaluesthatlackcorrespondinglvalues.Iftherightmostlvalueissplattedthenitconsumesallrvaluesw
defreverse(ary)result=[]forresult[0,0]inaryendresultendassert_equal["baz","bar","foo"],reverse(["foo","bar","baz"])这行得通,我想了解原因。有什么解释吗? 最佳答案 如果我使用each而不是for/in重写它,它看起来像这样:defreverse(ary)result=[]#forresult[0,0]inaryary.eachdo|item|result[0,0]=itemendresultendforainb基本上就
当我写下面的代码时:x=[1,2,3]x我得到这个输出:[1,2,3,[...]][1,2,3,[...]][1,2,3,[...]]我不应该只得到[1,2,3,[1,2,3]]吗?解释是什么? 最佳答案 这没什么奇怪的。数组的第四个元素就是数组本身,所以当你求第四个元素时,你得到的是数组,当你求第四个元素的第四个元素时,你得到的是数组,当你求第四个元素时,你得到的是数组。第四个元素的第四个元素的第四个元素的元素......你得到了数组。就这么简单。唯一有点不寻常的是Array#to_s检测到这样的递归,而不是进入无限循环,而是返回
我以为它已经安装了,但在我的gemfile中有gem"jquery-rails"但是在我的asset/javascripts文件夹中accounts.js.coffeeapplication.js都被注释掉了这是我的虚拟railsapplication但是在源代码中没有jQuery并且删除链接不起作用......任何想法都丢失了 最佳答案 看看thisRailscast.您可能需要检查application.js文件并确保它包含以下语句。//=requirejquery//=requirejquery_ujs
以下测试中的第3个失败:specify{(0.6*2).shouldeql(1.2)}specify{(0.3*3).shouldeql(0.3*3)}specify{(0.3*3).shouldeql(0.9)}#thisonefails这是为什么呢?这是浮点问题还是ruby或rspec问题? 最佳答案 从rspec-2.1开始specify{(0.6*2).shouldbe_within(0.01).of(1.2)}在那之前:specify{(0.6*2).shouldbe_close(1.2,0.01)}