2009-11-25 121 views
8

我正在学习Ruby。我的背景是C++/Java/C#。总的来说,我喜欢这种语言,但是我为什么有很多不同的方式来完成同一个事情,每个都有自己稍微不同的语义,有点困惑。例如,为什么Ruby中有这么多不同的方法来做同样的事情?

以字符串创建为例。我可以使用'','“,q%,Q%或%来创建字符串。有些形式支持插值。其他形式允许我指定字符串分隔符。

为什么有五种方法来创建字符串文字?为什么我会使用非插值字符串? %语法对引用文字有什么优势?

我知道Ruby中的redundency必须有价值,但我未经训练的眼睛并没有清楚地看到它。请赐教。

回答

15

为什么我会使用非插值字符串?

当然你不想插值。例如,也许您输出一些文件有关的字符串插值:

'Use #{x} to interpolate the value of x.' 
=> "Use #{x} to interpolate the value of x." 

请问%语法有什么优势引述文字?

它可以让你写串更自然,不带引号,或当你不想逃避很多东西,类似于C#的字符串文字前缀@

%{The % syntax make strings look more "natural".} 
=> "The % syntax makes strings look more \"natural\"." 

%{<basket size="50">} 
=> "<basket size=\"50\">" 

还有许多其他%-notations:

%w{apple banana #{1}cucumber} # [w]hitespace-separated array, no interpolation 
=> ["apple", "banana", "\#{1}cucumber"] 

%W{apple banana #{1}cucumber} # [W]hitespace-separated array with interpolation 
=> ["apple", "banana", "1cucumber"] 

# [r]egular expression (finds all unary primes) 
%r{^1?$|^(11+?)\1+$} 
=> /^1?$|^(11+?)\1+$/ 

(1..30).to_a.select{ |i| ("1" * i) !~ %r{^1?$|^(11+?)\1+$} } 
=> [2, 3, 5, 7, 11, 13, 17, 19, 23, 29] 

%x{ruby --version} # [s]hell command 
=> "ruby 1.9.1p129 (2009-05-12 revision 23412) [x86_64-linux]\n" 

还有%s(用于符号)和其他一些人。

为什么有五种方法来创建字符串文字?

这不是非常不寻常的。例如,考虑C#,它有几种不同的方式来生成字符串:new String(); ""; @""; StringBuilder.ToString()等等。

+1

“自然”是非常主观的。 “非常不寻常”不是创建语言功能的动机。 – skrat 2012-02-07 16:46:10

+1

“自然”具有很高的主观性,但“更少且更容易输入字符来表示完全相同的东西”不是,而且是创建语言功能的一个很好的动机。 – 2012-02-07 18:34:19

1

很多ruby的语法都是从perl派生的,就像使用q来将几个单词引入一个字符串中一样。这可能是造成这么大变化的主要原因。

3

我不是Ruby专家,但你有没有听说过“syntactic sugar”这个词?基本上一些编程语言提供不同的语法来完成相同的任务。由于他以前的编程/语法经验,有些人可以找到比其他人更容易的方法。

+0

确实。显然,Ruby在更多场合使用别名/同义词。例如,数组中元素的数量可以用'count','length'或'size'来检索。用于数组的相同属性的不同单词,但是通过它,您可以为您的代码选择最合适的单词:是否需要您正在收集的_number_项,数组的_length_或当前的_size_结构。从本质上讲,它们都是一样的,但选择正确的单词可能会使代码更易于阅读,这是该语言的一个很好的属性。 – 2016-10-10 18:59:10

2

在大多数情况下,您最终会使用普通的字符串分隔符。单引号和双引号的主要区别是双引号允许插入变量。当你因为他们是内部字符串的一部分不能使用引号

puts 'this is a string' 
# => this is a string 
puts "this is a string" 
# => this is a string 
v = "string" 
puts 'this is a #{v}' 
# => this is a #{v} 
puts "this is a #{v}" 
# => this is a string 

%q%Q是有用的。 例如,你可能最终写

html = %Q{this is a <img src="#{img_path}" class="style" /> image tag} 

在这种情况下,除非你想逃避内部属性分隔符,你不能使用双引号作为分隔符。另外,您不能使用单引号,因为img_path变量不会被插值。

0

如果您的字符串包含大量特殊字符(如反斜杠,#{}等),并且您不希望全部转义,则可以使用非插值字符串。

如果您的字符串包含大量需要转义的引号,那么您将使用不同的分隔符。

如果你的字符串有很多行会使正常的字符串语法看起来不灵活,那么你会使用heredocs。

0

Ruby借鉴了很多语言的构造和思想。两个最明显的影响是Smalltalk和Perl。

根据您对Smalltalk或Perl的安慰,您可以选择不同的构造来做同样的事情。

1

另一个原因是对非插值字符串性能略有提升。使用''vs'“意味着Ruby不必考虑字符串内部的内容。所以你会看到人们使用单引号作为数组键或符号,因为它们更快。对于什么是值得的,我将包括一个小基准。

require 'benchmark' 

Benchmark.bmbm(10) do |x| 
    x.report("single-quote") do 
    for z in 0..1000000 
     zf = 'hello' 
    end 
    end 

    x.report("double-quote") do 
    for z in 0..1000000 
     zf = "hello" 
    end 
    end 

    x.report("symbol") do 
    for z in 0..1000000 
     zf = :hello 
    end 
    end 
end 

产量:

Rehearsal ------------------------------------------------ 
single-quote 0.610000 0.000000 0.610000 ( 0.620387) 
double-quote 0.630000 0.000000 0.630000 ( 0.627018) 
symbol   0.270000 0.000000 0.270000 ( 0.309873) 
--------------------------------------- total: 1.580000sec 
0

除了约翰的回答线: 快速黑客,我最后往往是从我的Ruby脚本中运行的Perl或者sed的一个班轮使用grep语法。能够使用%[ ]类型语法意味着我可以简单地从终端复制粘贴我的正则表达式

0

最初的问题是为什么Ruby中有很多稍微不同的方法来做事。

有时候,不同的东西是明智的:引用是一种很好的情况,其中不同的行为需要不同的语法 - 非/插值,交替引用字符等 - 和历史因素导致像%x()vs``这样的同义词,在Perl中。

同义词问题 - [] .size [] .length [] .count - 感觉像是在语言对于IDE来说过于随机的世界中有帮助的尝试:猴子修补和奇怪的严格但动态的打字组合使运行时错误成为编码中不可避免和令人沮丧的部分,所以人们试图通过提供同义词来减少问题。不幸的是,他们最终弄乱了习惯于不同方法的程序员做不同的事情。

的“如此相似但不完全”的问题,例如...

$ ruby -le 'e=[]; e << (*[:A, :B])' 
-e:1: syntax error, unexpected ')', expecting :: or '[' or '.' 
$ ruby -le 'e=[]; e << *[:A, :B]' 
-e:1: syntax error, unexpected * 
$ ruby -le 'e=[]; e.push(*[:A, :B])' 
$ 

...真的只能被看作是一个缺陷。每种语言都有它们,但它们通常比这更神秘。

然后在Rubocop编码标准中存在一个普通的任意'使用失败而不是加注,除非你只是重新抛出一个异常'废话。

Ruby中有一些不错的东西,但真的 - 我宁愿编写一些更好的东西。

相关问题