_(下划线)变量在哪里以及如何指定? [英] Where and how is the _ (underscore) variable specified?

查看:31
本文介绍了_(下划线)变量在哪里以及如何指定?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大多数人都知道 _ 在 IRB 中作为最后一个返回值的持有者的特殊含义,但这不是我在这里要问的.>

相反,我询问的是 _ 在普通旧 Ruby 代码中用作变量名时的情况.这里它似乎有特殊的行为,类似于无关变量"(à la 序言).以下是一些说明其独特行为的有用示例:

lambda { |x, x|42 } # SyntaxError: 重复的参数名称拉姆达 { |_, _|42 }.call(4, 2) # =>42拉姆达 { |_, _|42 }.call(_, _) # NameError: 未定义的局部变量或方法`_'拉姆达 { |_|_ + 1 }.call(42) # =>43拉姆达 { |_, _|_ }.call(4, 2) # 1.8.7: =>2# 1.9.3: =>4_ = 42_ * 100 # =>4200_, _ = 4, 2;_ # =>2

这些都直接在 Ruby 中运行(添加了 putss)——而不是 IRB——以避免与其附加功能发生冲突.

不过,这都是我自己实验的结果,因为我在任何地方都找不到关于此行为的任何文档(诚然,这不是最容易搜索的东西).最后,我很好奇所有这些是如何在内部工作的,这样我才能更好地理解 _ 的特别之处.所以我要求参考文档,最好是 Ruby 源代码(也许还有 RubySpec),它揭示了如何_ 在 Ruby 中表现.

注意:大部分内容来自本次讨论@Niklas B.

解决方案

在源代码中有一些特殊处理来抑制重复参数名称"错误.错误消息仅出现在 parse.y 内的 shadowing_lvar_gen 中,1.9.3 版本看起来像这样:

静态IDshadowing_lvar_gen(struct parser_params *parser, ID name){if (idUScore == name) 返回名称;/* ... */

idUScoreid.c 像这样:

REGISTER_SYMID(idUScore, "_");

您将在 warn_unused_var:

静态无效warn_unused_var(struct parser_params *parser, struct local_vars *local){/* ... */for (i = 0; i 

您会注意到警告在 for 循环的第二行被抑制.

我在 1.9.3 源代码中可以找到的对 _ 的唯一特殊处理是:重复名称错误被抑制,未使用的变量警告被抑制.除了这两件事,_ 只是一个普通的旧变量.我不知道关于 _ 的(次要)特殊性的任何文档.

在 Ruby 2.0 中,warn_unused_var 被替换为对 is_private_local_id 的调用:

if (is_private_local_id(v[i])) continue;rb_warn4S(ruby_sourcefile, (int)u[i], "已分配但未使用的变量 - %s", rb_id2name(v[i]));

is_private_local_id 抑制以 _ 开头的变量的警告:

if (name == idUScore) return 1;/* ... */返回 RSTRING_PTR(s)[0] == '_';

而不仅仅是 _ 本身.所以 2.0 稍微放松了一些.

Most are aware of _’s special meaning in IRB as a holder for last return value, but that is not what I'm asking about here.

Instead, I’m asking about _ when used as a variable name in plain-old-Ruby-code. Here it appears to have special behavior, akin to a "don't care variable" (à la Prolog). Here are some useful examples illustrating its unique behavior:

lambda { |x, x| 42 }            # SyntaxError: duplicated argument name
lambda { |_, _| 42 }.call(4, 2) # => 42
lambda { |_, _| 42 }.call(_, _) # NameError: undefined local variable or method `_'
lambda { |_| _ + 1 }.call(42)   # => 43
lambda { |_, _| _ }.call(4, 2)  # 1.8.7: => 2
                                # 1.9.3: => 4
_ = 42
_ * 100         # => 4200
_, _ = 4, 2; _  # => 2

These were all run in Ruby directly (with putss added in)—not IRB—to avoid conflicting with its additional functionality.

This is all a result of my own experimentation though, as I cannot find any documentation on this behavior anywhere (admittedly it's not the easiest thing to search for). Ultimately, I'm curious how all of this works internally so I can better understand exactly what is special about _. So I’m asking for references to documentation, and, preferably, the Ruby source code (and perhaps RubySpec) that reveal how _ behaves in Ruby.

Note: most of this arose out of this discussion with @Niklas B.

解决方案

There is some special handling in the source to suppress the "duplicate argument name" error. The error message only appears in shadowing_lvar_gen inside parse.y, the 1.9.3 version looks like this:

static ID
shadowing_lvar_gen(struct parser_params *parser, ID name)
{
    if (idUScore == name) return name;
    /* ... */

and idUScore is defined in id.c like this:

REGISTER_SYMID(idUScore, "_");

You'll see similar special handling in warn_unused_var:

static void
warn_unused_var(struct parser_params *parser, struct local_vars *local)
{
    /* ... */
    for (i = 0; i < cnt; ++i) {
        if (!v[i] || (u[i] & LVAR_USED)) continue;
        if (idUScore == v[i]) continue;
        rb_compile_warn(ruby_sourcefile, (int)u[i], "assigned but unused variable - %s", rb_id2name(v[i]));
    }
}

You'll notice that the warning is suppressed on the second line of the for loop.

The only special handling of _ that I could find in the 1.9.3 source is above: the duplicate name error is suppressed and the unused variable warning is suppressed. Other than those two things, _ is just a plain old variable like any other. I don't know of any documentation about the (minor) specialness of _.

In Ruby 2.0, the idUScore == v[i] test in warn_unused_var is replaced with a call to is_private_local_id:

if (is_private_local_id(v[i])) continue;
rb_warn4S(ruby_sourcefile, (int)u[i], "assigned but unused variable - %s", rb_id2name(v[i]));

and is_private_local_id suppresses warnings for variables that begin with _:

if (name == idUScore) return 1;
/* ... */
return RSTRING_PTR(s)[0] == '_';

rather than just _ itself. So 2.0 loosens things up a bit.

这篇关于_(下划线)变量在哪里以及如何指定?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆