本文是函数式Ruby编程的学习笔记。
1.Ruby中的迭代方法(如each, map)需要与Block配合使用,那么如何获得Block呢?
- 直接使用{}或do ... end
- 将Proc或Method对象转化为Block. &proc_name/&:method_name/&method(:method_name) => block
获得Proc或Method对象的几种方式:
注意:对于无参方法f,可以直接用&:f将其转化为block,但对于有参方法f(如上图),需要将其显示地转化为Method对象,&method(:f) .
2. &:method_name 与 &method(:method_name)的区别
1 class A 2 def f 3 self 4 end 5 end 6 7 as = Array.new(3) {A.new} 8 9 as.map(&:f) #(a) 10 as.map(&A.new.method(:f)) #(b)
(a) as.map(&:f) 相当于 as.map {|a| a.f} ,也就是对于as中的每个对象调用方法f,所以第9行会得到as中每个对象的地址。
(b) as.map(&A.new.method(:f)) 相当于 as.map { f(a) } ,则是将as中的每个对象作为参数传给方法f,而方法f是无参的,所以第10行会报 wrong number of arguments (given 1, expected 0) (ArgumentError) 错误。
3.irb中的访问控制
在irb中输入以下代码
1 class A 2 def f 3 self 4 end 5 end 6 7 as = Array.new(3) {A.new} 8 9 def f1 10 1 11 end 12 13 as.map(&:f1) #(a)
按照2中的总结 as.map(&:f1) 相当于 as.map {|a| a.f1} ,但是对象a并没有方法f1,第13行应该会报错,但在irb中第13行却返回 [1, 1, 1] ,怎么回事呢?如果你将以上代码复制到一个文件中再执行,就会报 private method `f1' called for #<A:0x00000002913b18> (NoMethodError) 错误,提示f1是私有方法,as中的对象并没有方法f1,将f1设置为public方法后(public方法可以被任何对象调用),第13行同样会返回 [1, 1, 1]。综上,irb中第13行返回 [1, 1, 1]应该是对方法的访问控制没有实现好。