大多数人都知道_IRB作为最后回报值的持有人的特殊含义,但这不是我在这里要求的.
相反,我问的是什么_时候用作普通旧Ruby代码中的变量名.在这里它似乎有特殊的行为,类似于"不关心变量"(àlaProlog).以下是一些说明其独特行为的有用示例:
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
Run Code Online (Sandbox Code Playgroud)
这些都直接在Ruby中运行(puts添加了s) - 不是IRB-以避免与其附加功能冲突.
这完全是我自己的实验的结果,因为我无法在任何地方找到关于此行为的任何文档(不可否认,这不是最容易搜索的事情).最后,我很好奇所有这些内部是如何工作的,所以我可以更好地理解究竟什么是特别的_.所以我要求提供文档,最好是Ruby源代码(也许是RubySpec),它们揭示了_Ruby中的行为.
注意:大部分内容都来自与@Niklas B的讨论.
mu *_*ort 52
源中有一些特殊处理可以抑制"重复参数名称"错误.错误消息只出现在shadowing_lvar_gen内部parse.y,1.9.3版本如下所示:
static ID
shadowing_lvar_gen(struct parser_params *parser, ID name)
{
if (idUScore == name) return name;
/* ... */
Run Code Online (Sandbox Code Playgroud)
并且idUScore是在定义id.c这样的:
REGISTER_SYMID(idUScore, "_");
Run Code Online (Sandbox Code Playgroud)
你会看到类似的特殊处理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]));
}
}
Run Code Online (Sandbox Code Playgroud)
您会注意到警告在for循环的第二行被禁止.
_我在1.9.3源代码中可以找到的唯一特殊处理是:禁止重复名称错误,并禁止使用未使用的变量警告.除了这两件事之外,_它只是一个普通的旧变量.我不知道有关(次要)特殊性的任何文件_.
在Ruby 2.0中,idUScore == v[i]测试输入warn_unused_var被替换为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]));
Run Code Online (Sandbox Code Playgroud)
并is_private_local_id禁止以下列开头的变量发出警告_:
if (name == idUScore) return 1;
/* ... */
return RSTRING_PTR(s)[0] == '_';
Run Code Online (Sandbox Code Playgroud)
而不仅仅是_自己.所以2.0放松了一些东西.
Mat*_*ira 23
_是有效的标识符.标识符不能只包含下划线,它们也可以是下划线.
_ = o = Object.new
_.object_id == o.object_id
# => true
Run Code Online (Sandbox Code Playgroud)
您还可以将其用作方法名称:
def o._; :_ end
o._
# => :_
Run Code Online (Sandbox Code Playgroud)
当然,它不是一个可读的名称,也不会向读者传递有关变量引用的内容或方法的作用的任何信息.
IRB,特别是,设置_为最后一个表达式的值:
$ irb
> 'asd'
# => "asd"
> _
# => "asd"
Run Code Online (Sandbox Code Playgroud)
就像它在源代码中一样,它只是设置_为最后一个值:
@workspace.evaluate self, "_ = IRB.CurrentContext.last_value"
Run Code Online (Sandbox Code Playgroud)
做了一些存储库探索.这是我发现的:
在文件的最后一行id.c,有一个调用:
REGISTER_SYMID(idUScore, "_");
Run Code Online (Sandbox Code Playgroud)
grep来源给idUScore了我两个看似相关的结果:
shadowing_lvar_gen似乎是一种机制,通过该机制,块的形式参数替换了另一个范围中存在的同名变量.似乎提出"重复参数名称" SyntaxError和"阴影外部局部变量"警告的功能.
在grep获取源代码后shadowing_lvar_gen,我在Ruby 1.9.3的更新日志中找到了以下内容:
Tue Dec 11 01:21:21 2007 Yukihiro Matsumoto
- parse.y(shadowing_lvar_gen):"_"没有重复的错误.
这很可能是这条线的起源:
if (idUScore == name) return name;
Run Code Online (Sandbox Code Playgroud)
由此可见,我推断出在某种情况下proc { |_, _| :x }.call :a, :b,一个_变量只会影响另一个变量.
这是有问题的提交.它基本上介绍了这两行:
if (!uscore) uscore = rb_intern("_");
if (uscore == name) return;
Run Code Online (Sandbox Code Playgroud)
idUScore显然,从一个甚至不存在的时候开始.
| 归档时间: |
|
| 查看次数: |
23208 次 |
| 最近记录: |