[英]Difference between puts a and puts “#{a}”
I thought that doing puts #{a}
would result in the same output as puts a
, but found this not to be the case. 我认为执行
puts #{a}
会得到与puts a
相同的输出,但事实并非如此。 Consider: 考虑:
irb(main):001:0> a = [1,2]
=> [1, 2]
irb(main):002:0> puts a
1
2
=> nil
irb(main):003:0> puts "#{a}"
12
=> nil
irb(main):004:0>
In the above example it doesn't matter much, but it may matter when I want to print multiple variables on one line, such as (psudocode): 在上面的示例中,这没什么大不了的,但是当我想在一行上打印多个变量时可能会很重要,例如(psudocode):
puts "There are #{a.size} items in the whitelist: #{a}"
Why is the output different here? 为什么这里的输出不同? Do they actually do different things, or have different semantics?
他们实际上是在做不同的事情,还是具有不同的语义?
That's because "#{a}"
calls the #to_s
method on the expression. 这是因为
"#{a}"
在表达式上调用了#to_s
方法。
So: 所以:
puts a # equivalent to, well, puts a
puts "#{a}" # equivalent to the next line
puts a.to_s
Update: 更新:
To elaborate, puts
eventually calls #to_s
but it adds logic in front of the actual output, including special handling for arrays. 详细地说,
puts
最终调用#to_s
但是它在实际输出之前添加了逻辑,包括对数组的特殊处理。 It just happens that Array#to_s
doesn't use the same algorithm. 碰巧
Array#to_s
没有使用相同的算法。 (See puts
docs here.) Here is exactly what it does... (请参阅此处的
puts
文档。)这正是它的作用...
rb_io_puts(int argc, VALUE *argv, VALUE out)
{
int i;
VALUE line;
/* if no argument given, print newline. */
if (argc == 0) {
rb_io_write(out, rb_default_rs);
return Qnil;
}
for (i=0; i<argc; i++) {
if (TYPE(argv[i]) == T_STRING) {
line = argv[i];
goto string;
}
line = rb_check_array_type(argv[i]);
if (!NIL_P(line)) {
rb_exec_recursive(io_puts_ary, line, out);
continue;
}
line = rb_obj_as_string(argv[i]);
string:
rb_io_write(out, line);
if (RSTRING_LEN(line) == 0 ||
!str_end_with_asciichar(line, '\n')) {
rb_io_write(out, rb_default_rs);
}
}
return Qnil;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.