.NET和Java也提出了类似的问题,但Ruby没有。那么, Ruby中你最喜欢的功能是什么?
您可能也对hidden features of Ruby感兴趣。
请具体说明并在每个答案中发布一个功能。解释或代码示例会很好。
答案 0 :(得分:12)
块非常好:
my_array.each { |element| print element }
#...
File.open("foo.txt") do |file|
# do stuff with file
end
答案 1 :(得分:7)
这是一个非常小的,几乎无关紧要的功能,但我真的很喜欢这个结构:
var ||= "default"
如果尚未设置var
,则会将"default"
设置为默认值(var
),如果已设置var
,则保留当前值new_val = old_val || "default"
。我喜欢紧凑的语法。
同样,我可以这样做:
||
也设置默认值。
一般来说,我喜欢所有Ruby表达式都返回一个值,因此我可以使用像{{1}}这样的运算符来编写简短的紧凑语句。
答案 2 :(得分:3)
我喜欢能够调用没有括号的函数,并且函数返回最后一次计算的表达式。
前者节省了大量不必要的括号,使代码更容易阅读。
后者有时会变得非常混乱,但它对于单行(尤其是逻辑)函数来说非常棒。
答案 3 :(得分:3)
可枚举!关于为什么它很棒的一些例子。
a = ['foo', 'bar', 'baz']
a.delete_if {|i| i =~ /^f/ }
# vs
new = []
a.each do |i|
if i !~ /^f/
new << i
end
end
a.select {|i| i =~ /^f/ }
# vs
new = []
a.each do |i|
if i =~ /^f/
new << i
end
end
a.detect {|i| i =~ /^f/ }
# vs
a.each do |i|
if i =~ /^f/
return i
end
end
能够通过'select','detect','delete_if'等直接说出你想要实现的东西,而不是循环并手动完成所有事情,这是非常好的。 Enumerable使得在阅读代码时更容易输入和更容易理解。
答案 4 :(得分:2)
这些类是对象,new是类中的方法:
c = Array
a = c.new()
我喜欢案件的运作方式。它在每个case值上调用===并返回一个值:
if(0 <= age && age <= 10){
x = "kid"
}else if(10 <= age && age <= 80)
x = "person"
}else if(80 <= age && age <= 99)
x = "old"
}else{
x = "???"
}
=>
x = case age
when 0..10: "kid"
when 10..80: "person"
when 80..99: "old"
default: "???"
end
这是有效的,因为范围(0..10)有一个===方法来检查某些东西是否在范围内:(5..10)=== 6 ==&gt;真正。正则表达式也支持===,所以你可以这样做:
case str
when /regex1/: ...
when /regex2/: ...
...
end
您甚至可以为自己的对象编写===方法。
答案 5 :(得分:2)
另一个不错的功能:确保。它就像最后一样,但在Ruby中有一个简洁的语法。你有这样的东西时可以使用它:
def foo(x)
return_value = bar(x)
dosomething(x)
return return_value
end
=>
def foo(x)
bar(x)
ensure
dosomething(x)
end
答案 6 :(得分:2)
开放课程是我最喜欢的一个。例如,这个:
# try.rb
class TryObjectMock
public_instance_methods.reject { |x| x =~ /^__/ }.each { |x| undef_method(x) }
def method_missing(symbol, *args)
end
end
class Object
def try
self.nil? ? TryObjectMock.new : self
end
end
使处理nil
能够对象的代码更清晰:
irb(main):001:0> require 'try'
irb(main):002:0> puts "5".try.to_i
5
irb(main):003:0> puts nil.try.to_i
nil
irb(main):004:0> puts [1, 2].try.find { |x| x == 2 }.try + 3
5
irb(main):005:0> puts [1, 2].try.find { |x| x == 3 }.try + 3
nil
irb(main):006:0> puts nil.try.find { |x| x == 3 }.try + 3
nil
irb(main):007:0>
它避免了很多if-else
s:
irb(main):007:0> a = [1, 2]
irb(main):008:0> puts(if a
irb(main):009:2> if b = a.find { |x| x == 2 }
irb(main):010:3> b + 3
irb(main):011:3> end
irb(main):012:2> end)
5
irb(main):013:0> c = "5"
irb(main):014:0> puts(c ? c.to_i : nil)
5
这个技巧通过为对象空间中的每个类定义方法try
来实现。当它被调用时,当对象为nil
时,它返回一个特殊对象(nil
是NilClass
的实例,它是Object
的子类!)或对象本身否则。对于调用的每个方法(通过空nil
实现),该特殊对象只返回method_missing
。请注意,它也适用于运算符,因为它们是左侧对象的方法。
答案 7 :(得分:2)
非布尔值的布尔运算符。
&&
和||
两者都返回最后一个表达式的值。通过短路,这些可以创造出方便的捷径。为了短路检测的目的,它们将任何非零或假的值视为真。
示例:
a = b || c
仅当b为nil或false时才将c的值赋给a。
a = b && c
将c的值指定为只有b不是nil或false,否则指定b。
此行为说明了已提及的||=
。
然而,&&=
运算符却没有得到同样的爱。
string &&= string + "suffix"
相当于
if string
string = string + "suffix"
end
如果变量未定义,那么破坏性操作非常方便。
答案 8 :(得分:2)
我不可能只选择一个,但第一个想到的是splat:*
基本上它可以让你把数组转换成参数列表,反之亦然,让你做这样的事情:
odds = [1, 3, 7]
evens = [2, 4, 6]
case 4
when *odds then "odd!"
when *evens then "even!"
end
# => "even!"
arr = [ :a, 1, :b, :2 ]
Hash[*arr] # => { :a => 1, :b => 2 }
a, b, c = *(1..3)
puts a # => 1
puts b # => 2
puts c # => 3
a = 1, *[2, 3] # => [1, 2, 3]
# And of course...
def f(*args)
puts args
end
f 1, 2, 3 # => [1, 2, 3]
答案 9 :(得分:1)
问号/感叹号命名惯例
方法调用后通常不需要parens
封
的rubygems
好的,我想这是一些最爱:)
答案 10 :(得分:1)
我最喜欢的功能(最近处理Soap4R之后)可能是可用的内省。这两种方法特别有用:
public_methods - 返回对象上所有方法的列表。当您试图找出可以对某些事情做些什么时,从调试器或irb中获得超级有用。 (紧随其后
instance_variables - 返回对象上所有实例变量的列表。
答案 11 :(得分:1)
instance_eval和class_eval:)
答案 12 :(得分:1)
if
语句也是表达式,因此块的最后一行返回一个值。允许使用以下代码:
my_var = if some_var.is_true?
if some_other_var > 8
1
else
23
end
else
5
end
此处,my_var
最终会得到值1,23或5,具体取决于条件的评估方式。