在哪里以及如何指定_(下划线)variables?
大多数人都知道IRB作为最后回报价值的持有者具有特殊的含义 ,但这不是我在这里问的。
相反,我在使用纯旧的Ruby代码作为variables名称时询问了_
。 这里似乎有特殊的行为,类似于“无关variables”( àProlog )。 以下是一些有用的例子,说明其独特的行为:
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
这些都是在Ruby中直接运行的(join了puts
),而不是IRB,以避免与其他function冲突。
这是我自己实验的结果,尽pipe我无法在任何地方find有关这种行为的任何文档(当然,这不是search最简单的事情)。 最后,我很好奇所有这些在内部工作,所以我可以更好地理解_
什么是特殊的。 所以我要求引用文档,最好是Ruby源代码(也可能是RubySpec ),它揭示了Ruby在Ruby中的行为。
注意:这大部分出现在与@Niklas B的 讨论中 。
源代码中有一些特殊的处理来抑制“重复的参数名称”错误。 该错误消息只出现在parse.y
中的shadowing_lvar_gen
, 1.9.3版本看起来像这样 :
static ID shadowing_lvar_gen(struct parser_params *parser, ID name) { if (idUScore == name) return name; /* ... */
而idUScore
在id.c
是这样定义的 :
REGISTER_SYMID(idUScore, "_");
你会在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])); } }
你会注意到在for
循环的第二行中被禁止了。
我只能在1.9.3源代码中find_
的唯一特殊处理:重复名称错误被抑制,未使用的variables警告被取消。 除了这两件事之外, _
只是一个普通的旧variables。 我不知道关于_
的(小)特殊性的任何文档。
在Ruby 2.0中, idUScore == v[i]
testing被replace为对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]));
而is_private_local_id
禁止以_
开头的variables的警告
if (name == idUScore) return 1; /* ... */ return RSTRING_PTR(s)[0] == '_';
而不仅仅是本身。 所以2.0放松了一下。
_
是一个有效的标识符。 标识符不能只包含下划线,也可以是下划线。
_ = o = Object.new _.object_id == o.object_id # => true
您也可以将其用作方法名称:
def o._; :_ end o._ # => :_
当然,这不是一个完全可读的名字,也不会向读者传递有关variables引用或方法的信息。
IRB
特别将_
设定为最后一个expression式的值:
$ irb > 'asd' # => "asd" > _ # => "asd"
就像在源代码中一样 ,它只是将_
设置为最后一个值:
@workspace.evaluate self, "_ = IRB.CurrentContext.last_value"
有一些存储库的探索。 这是我发现的:
在文件id.c
的最后一行,有这个调用:
REGISTER_SYMID(idUScore, "_");
对idUScore
的源idUScore
给了我两个看似相关的结果:
- 在
shadowing_lvar_gen
函数中 - 在
warn_unused_var
函数中
shadowing_lvar_gen
似乎是块的forms参数replace另一个范围中存在的同名variables的机制。 似乎是引起“重复的参数名称” SyntaxError
和“阴影外部局部variables”警告的函数。
在grep
shadowing_lvar_gen
的源代码之后,我在Ruby 1.9.3的更新日志中发现了以下内容:
星期二十二月十一日01:21:21松本幸弘
- parse.y(shadowing_lvar_gen):“_”没有重复的错误。
这可能是这一行的起源:
if (idUScore == name) return name;
由此我推断,在proc { |_, _| :x }.call :a, :b
proc { |_, _| :x }.call :a, :b
,其中一个_
variables只是影响另一个。
这是提交的问题 。 它基本上介绍了这两行:
if (!uscore) uscore = rb_intern("_"); if (uscore == name) return;
从idUScore
甚至不存在的时候,显然。