在Ruby中,数组*字符串是什么意思?

15

我在查看一些 Rails 源代码时发现

# File vendor/rails/activesupport/lib/active_support/vendor/builder-2.1.2/builder/css.rb, line 129
129:     def target!
130:       @target * ''
131:     end

*表示乘法,''表示空字符串。在这种情况下,乘以空字符串不会产生任何效果,因为任何数乘以0都等于0。可能是在某些特定的应用场景下使用,但需要看上下文来确定。

6个回答

15

这是一种奇怪的语法。以下两者等价:

>> [1, 2, 3] * 'joiner'
=> "1joiner2joiner3"

>> [1, 2, 3].join 'joiner'
=> "1joiner2joiner3"

在这种情况下,它将@target的所有条目连接成一个字符串,并在条目之间不加任何内容。

注意:如果您执行类似于[1, 2, 3] * 3的操作(使用int而不是str),则会得到三个连接的数组副本。


6

2
我可能会用不同的措辞。它的结果与 [].join 相同,但使用 join() 方法更明显且更常用。我看过几个建议,我们不要使用数组的 '*' 运算符,因为使用它的人太少了,这会让人感到困惑。比较 [1,2] * ',' 和 [1,2] * 2 的输出,就可以看出为什么它不能很好地配合我们的大脑。 - the Tin Man
你是在争论它不做同样的事情吗?RDoc说“等同于”。可读性与实现无关。 - klochner

4

确实是非常晦涩的代码。

检查源代码后,我意识到@target实际上是一个Array实例,你可以像这样做一些事情。

[5] * 5 # => [5,5,5,5,5]

我不知道 Array#* 是在哪里定义的(也许是在 ActiveSupport 中),但我可以告诉你的是,当它与一个 String 相乘时的行为如下:

[1,2,3] * 'comma' # => "1comma2comma3"
[1,2,3] * '' # => '123'

因此,我可以推断它在不使用任何分隔符的情况下连接数组的所有元素。


2
使用字符串参数的Array#*等同于{{Array#join}}。

1

两点评论:

  1. 在方法名称结尾加上!意味着这是一个改变操作,但这个例子似乎不是。

  2. 正如其他人所说,这确实有些晦涩难懂。我会选择@target.to_s或@target.join。


1
此外,这种 Ruby 代码让我感到沮丧,因为 Ruby 很容易阅读和惯用美观,而这样的语法让我想起了 Perl。 - user253455
你是第二个抱怨中缀运算符语法的人。我不太明白。除了Lisp和Forth之外,地球上几乎每一种编程语言都有一种*中缀运算符。中缀运算符没有什么“奇怪”或“悲哀”的。 - Jörg W Mittag
当然,但这个例子让人们必须稍微思考一下才能理解这行代码。创建一个空字符串以连接一个数组是使用 * 的一个有些晦涩的方法。我绝对不反对这个操作符。 - user253455

0

我唯一能想到的使用 * 连接字符串数组的原因是为了避免使用单词 join,因为这个单词也用于线程。

使用以下代码:

strings = ["John", "Smith"]
threads = [Thread.new{puts "hai"}, Thread.new{ puts "world!"}]
strings.join(" ") # Legit
threads.each {|thread| thread.join} # Legit

你可能会犯错

threads.join # Not legit, but won't raise an error

如果你用strings.*替换strings.join,那么你的代码中就会少一些join。现在你可以使用grep查找它们,并检查每个join是否是针对线程而不是数组进行的。事实上,你可以选择让Array#join抛出异常。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接