我正在学习Ruby。我的背景是C ++ / Java / C#。总的来说,我喜欢这种语言,但我对为什么有这么多不同的方法来完成同样的事情感到有些困惑,每种方法都有自己略有不同的语义。
例如,创建字符串。我可以使用'',“,q%,Q%或只是%来创建字符串。某些形式支持插值。其他形式允许我指定字符串分隔符。
为什么有五种方法可以创建字符串文字?为什么我会使用非插值字符串? %语法比引用文字有什么优势?
我知道Ruby中的redundency一定有价值,但是我未经训练的眼睛并没有清楚地看到它。请赐教。
答案 0 :(得分: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\">"
还有许多其他%注释:
%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 :(得分:3)
我不是Ruby专家,但你有没有听说过“语法糖”这个词?基本上,一些编程语言提供不同的语法来完成相同的任务。由于他之前的编程/语法经验,有些人可以找到比其他人更容易的方法。
答案 2 :(得分: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
变量不会被插值。
答案 3 :(得分:1)
许多ruby的语法都是从perl派生的,比如使用q
将几个单词引用到字符串中。这可能是种类繁多的主要原因。
答案 4 :(得分: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
答案 5 :(得分:0)
如果您的字符串包含许多特殊字符(如反斜杠,#{}
等),您将使用非插值字符串,并且您不想逃避所有字符串。
如果你的字符串包含很多你必须要逃脱的引号,你会使用不同的分隔符。
如果你的字符串有很多行会使正常的字符串语法看起来不实用,你就会使用heredocs。
答案 6 :(得分:0)
Ruby借用了许多语言的构造和想法。两个最明显的影响是Smalltalk和Perl。
根据您对Smalltalk或Perl的舒适度,您可能会选择不同的结构来做同样的事情。
答案 7 :(得分:0)
按照约翰的回答:
在快速黑客攻击中,我经常在我的ruby脚本中使用grep语法运行perl或sed one-liner。能够使用%[ ]
类型语法意味着我可以简单地从终端复制粘贴我的正则表达式
答案 8 :(得分: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中有一些不错的东西,但实际上 - 我更愿意在更好的基础上编写代码。