在Ruby中,array * string是什么意思?

问题描述:

我一直在寻找通过一些Rails的源代码和跨在Ruby中,array * string是什么意思?

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

什么是*“”做出来?这是乘以一个空字符串...?你为什么要这样做。

这是一种奇怪的语法。这是等价的:

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

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

所以在这种情况下,加入的@target所有条目合并为一个字符串,与项目之间没有任何东西。

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

+0

咦?!关于infix操作符的语法没有什么“奇怪的”(除非你是一个Lisp或Forth*分子)。 *这个星球上的每一种编程语言都有一个'*'infix操作符。 – 2010-02-10 11:35:38

+5

@Jörg:这不是中间的怪异部分,它是一个数组乘以一个字符串的事实...? – 2010-02-10 11:38:38

+0

我同意这种语义是令人困惑和奇怪的,但是彼得和克劳森抱怨的不是语义,而是语法*,我对此一点都不屑一顾。 – 2010-02-10 12:45:43

它做同样的事情:

["foo","bar","baz"].join 

http://ruby-doc.org/core/classes/Array.html#M002210

每Z.E.D.的建议,如果你想蛊惑人心,使你的代码更容易出错,你会使用它。

+2

我可能用不同的话来说。它与[] .join的结果相同,但使用join()方法更明显且更常用。我已经看到了一些建议,我们不会在数组中使用'*'运算符,因为很少有人使用它,这会让人感到困惑。比较[1,2] *','与[1,2] * 2的输出为例,说明为什么它不能与我们的大脑相配合。 – 2010-02-10 01:04:21

+0

你是否认为它没有做同样的事情? RDoc说“相当于”。可读性与实现正交。 – klochner 2010-02-10 01:08:26

真的很神秘的代码。

检查源代码后,我意识到,@target实际上是一个Array比如,我知道你可以做这样的东西

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

我不知道在哪里Array#*定义(也许在ActiveSupport)但我可以告诉你的是,这是行为,当它被用String

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

乘以所以我可以推断出它concatanating阵列中的所有元素,而不任何分隔符。

两点意见:

  1. 拥有一个!结束方法名称意味着它是一个变异操作,这个例子似乎不是。

  2. 正如其他人所说,它确实是神秘的。我会去@ target.to_s或@ target.join

+1

此外,这种类型的ruby代码让我感到难过,因为ruby很容易阅读,而且地道的美,这样的语法给了我Perl的闪回。 – user253455 2010-02-10 05:30:31

+0

你是这个问题上第二个抱怨中缀操作符语法的人。我不太明白。除了Lisp和Forth之外,这个星球上几乎所有*编程语言都有一个'*'infix操作符。中缀操作员没有什么“奇怪”或“难过”。 – 2010-02-10 11:40:14

+0

当然,但这个例子让人不得不简单地思考一下代码行。创建一个空字符串来连接一个数组是一个有点模糊的使用*。我绝对没有反对运营商。 – user253455 2010-02-10 19:17:45

Array#*String说法是相当于Array#join

我看到有人想用*加入字符串数组的唯一原因是他们想避开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,并检查每一个正在完成一个线程,而不是一个数组。事实上,你可以选择让Array#join抛出异常。