1
class SongList
2
def [](key)
3
return @songs[key] if key.kind_of?(Integer)
4
return @songs.find { |aSong| aSong.name == key }
5
end
6
end
class SongList2
def [](key)3
return @songs[key] if key.kind_of?(Integer)4
return @songs.find { |aSong| aSong.name == key }5
end6
end在第四行中,有find这样一个方法,可以按照指定条件对songs进行遍历,最终返回一个符合条件的个体。
下面就来看看这个方法到底是怎么实现的,
1
class Array
2
def find
3
for i in 0
size
4
value = self[i]
5
return value if yield(value)
6
end
7
return nil
8
end
9
end
10
发现是在Array这个类中,增加了一个method,在method中嵌入了一个遍历操作。
class Array 2
def find 3
for i in 0
size 4
value = self[i] 5
return value if yield(value) 6
end 7
return nil 8
end 9
end 10

如果只是这样的话,那么ruby和其他语言也就没有什么差别了,我们注意到第5行中有yield
这么一个东东。其实他起到了一个代理的作用,实现了实际操作部分和遍历的分离。
再看看下面这个例子,来了解一下yield的功能。
1
def threeTimes
2
yield
3
yield
4
yield
5
end
6
threeTimes { puts "Hello" }
7
8
def threeTimes2
yield3
yield4
yield5
end6
threeTimes { puts "Hello" }7

8

这里定义了名叫threeTimes的blocks, blocks中会重复3次外部的操作,当row 6的代码执行后,会得到后面的结果:
Hello
Hello
Hello

可以看到blocks为我们提供了如此灵活的手段,其实他语言中需要通过代理或接口或函数指针来实现。
其实.net 3.x以后的版本也提供了类似的功能,一个叫LINQ(Language Integrated Query )的东东。
可以使用类似SQL的方式过滤集合
LINQ Query:
string[] names = { "Geoff", "Jessica", "Mike", "Megan",
"Priscilla", "Jack", "Alma" };
IEnumerable<string> expr = from s in names
where s.Length == 5
orderby s
select s.ToUpper();
foreach (string item in expr)
Console.WriteLine(item);
上面的用法是不是很简洁方便?
用ruby来实现的话,将会是这样:
1
names = [ "Geoff", "Jessica", "Mike", "Megan", "Priscilla",
2
"Jack", "Alma" ]
3
4
expr = names.select {
5
|n| n.length == 5
6
}.sort.collect { |n| n.upcase }
7
8
expr.each {|n| puts n }
names = [ "Geoff", "Jessica", "Mike", "Megan", "Priscilla",2
"Jack", "Alma" ]3
4
expr = names.select {5
|n| n.length == 56
}.sort.collect { |n| n.upcase }7

8
expr.each {|n| puts n }正因为blocks如此方便,在阅读ruby程序的时候,可以看到被广泛的使用着。


浙公网安备 33010602011771号