草庐IT

swift - Swift 3.1 中#function 文字的奇怪值

coder 2023-09-05 原文

我发现 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 更新

在 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 的过程中得到“填充”;这是通过 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::printPrettyMagicFunctionName 上使用此流:

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/

有关swift - Swift 3.1 中#function 文字的奇怪值的更多相关文章

  1. ruby - 如何使用文字标量样式在 YAML 中转储字符串? - 2

    我有一大串格式化数据(例如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以想要的样式转储标量?解

  2. ruby - 字符串文字中的转义状态作为 `String#tr` 的参数 - 2

    对于作为String#tr参数的单引号字符串文字中反斜杠的转义状态,我觉得有些神秘。你能解释一下下面三个例子之间的对比吗?我特别不明白第二个。为了避免复杂化,我在这里使用了'd',在双引号中转义时不会改变含义("\d"="d")。'\\'.tr('\\','x')#=>"x"'\\'.tr('\\d','x')#=>"\\"'\\'.tr('\\\d','x')#=>"x" 最佳答案 在tr中转义tr的第一个参数非常类似于正则表达式中的括号字符分组。您可以在表达式的开头使用^来否定匹配(替换任何不匹配的内容)并使用例如a-f来匹配一

  3. ruby-on-rails - Rails 3.1 中具有相同形式的多个模型? - 2

    我正在使用Rails3.1并在一个论坛上工作。我有一个名为Topic的模型,每个模型都有许多Post。当用户创建新主题时,他们也应该创建第一个Post。但是,我不确定如何以相同的形式执行此操作。这是我的代码:classTopic:destroyaccepts_nested_attributes_for:postsvalidates_presence_of:titleendclassPost...但这似乎不起作用。有什么想法吗?谢谢! 最佳答案 @Pablo的回答似乎有你需要的一切。但更具体地说...首先改变你View中的这一行对此#

  4. ruby-on-rails - 带有 Zeus 的 RSpec 3.1,我应该在 spec_helper 中要求 'rspec/rails' 吗? - 2

    使用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中做

  5. ruby-on-rails - 浮点乘法的 Ruby 奇怪问题 - 2

    有没有人用ruby​​解决这个问题:假设我们有:a=8.1999999我们想将它四舍五入为2位小数,即8.20,然后乘以1,000,000得到8,200,000我们是这样做的;(a.round(2)*1000000).to_i但是我们得到的是8199999,为什么?奇怪的是,如果我们乘以1000、100000或10000000而不是1000000,我们会得到正确的结果。有人知道为什么吗?我们正在使用ruby​​1.9.2并尝试使用1.9.3。谢谢! 最佳答案 每当你在计算中得到时髦的数字时使用bigdecimalrequire'bi

  6. ruby - 字符串文字前面的 * 在 ruby​​ 中有什么作用? - 2

    这段代码似乎创建了一个范围从a到z的数组,但我不明白*的作用。有人可以解释一下吗?[*"a".."z"] 最佳答案 它叫做splatoperator.SplattinganLvalueAmaximumofonelvaluemaybesplattedinwhichcaseitisassignedanArrayconsistingoftheremainingrvaluesthatlackcorrespondinglvalues.Iftherightmostlvalueissplattedthenitconsumesallrvaluesw

  7. ruby - 奇怪的 ruby​​ for 循环行为(为什么这样做有效) - 2

    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基本上就

  8. ruby-on-rails - ruby数组奇怪的东西(无限数组) - 2

    当我写下面的代码时:x=[1,2,3]x我得到这个输出:[1,2,3,[...]][1,2,3,[...]][1,2,3,[...]]我不应该只得到[1,2,3,[1,2,3]]吗?解释是什么? 最佳答案 这没什么奇怪的。数组的第四个元素就是数组本身,所以当你求第四个元素时,你得到的是数组,当你求第四个元素的第四个元素时,你得到的是数组,当你求第四个元素时,你得到的是数组。第四个元素的第四个元素的第四个元素的元素......你得到了数组。就这么简单。唯一有点不寻常的是Array#to_s检测到这样的递归,而不是进入无限循环,而是返回

  9. jquery - 如何在 rails 3.1 上安装 jQuery - 2

    我以为它已经安装了,但在我的gemfile中有gem"jquery-rails"但是在我的asset/javascripts文件夹中accounts.js.coffeeapplication.js都被注释掉了这是我的虚拟railsapplication但是在源代码中没有jQuery并且删除链接不起作用......任何想法都丢失了 最佳答案 看看thisRailscast.您可能需要检查application.js文件并确保它包含以下语句。//=requirejquery//=requirejquery_ujs

  10. ruby - 比较 rspec 中的 float 时的奇怪行为 - 2

    以下测试中的第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)}

随机推荐