您的位置:首页 > 编程语言 > Ruby

Alex学Ruby[详解 block和Proc对象 2]

2008-06-24 00:44 615 查看
Ruby Block Part Two
本部分内容是基于Ruby 1. 8. 7, 以后的系列都是1.8.7下测试。

例子1 :
def return_using_procnew
a_proc = Proc.new { return "Hi" }
a_proc.call
"Last line in the method"
end

=> “ Hi”

def return_using_lambda
a_proc = lambda { return "Hi" }
a_proc.call
"Last line in the method"
end
=> "Last line in the method"
以上例子可以看出lambda和Proc.new的区别, 用lambda的时候return会被劫持, 而Proc.new则不会。

例子2:
def foo(proc_one,proc_two)
proc_two.call
proc_one.call
end

foo(lambda {p "Proc 1"}, lambda {p "Proc 2"}) => "Proc 2" "Proc 1"

def foo(proc_one,proc_two)
proc_one.call
proc_two.call
end

foo(lambda {p "Proc 1"}, lambda {p "Proc 2"}) => "Proc 1" "Proc 2"

例子3:

def foo(&my_block)
my_block.call
end

foo { puts "Hi" }
=> Hi

foo (lambda{ puts "Hi" })
=> ArgumentError: wrong number of arguments (1 for 0)

def foo(a,&my_block)
a.call
end

foo (lambda{ puts "Hi" })
=> Hi

def foo(&my_block)
my_block.call
end

foo { puts "Hi" }
=> Hi
例子4:

1.times do
x = 5
closure = Proc.new {puts "In clsure value of x is #{x}
end

closure.call
=> In clsure value of x is 5

x = 1

puts x
=> 1

closure.call
=> In clsure value of x is 5

由此看出,闭包引用的变量是call这个proc对象时产生的变量,在外部修改其值是没用的。

例子5:
class GreetingGenerator
def initialize(greeting)
@my_block = lambda {|name| puts "#{greeting}, #{name}"}
end
def greet(name)
@my_block.call name
end
end
frenchGreeting = GreetingGenerator.new “Bonjour”
englishGreeting = GreetingGenerator.new “Hello”
frenchGreeting.greet “TinTin”
=> Bonjour, TinTin
englishGreeting.greet “Bunny”
=> Hello, Bunny
这你能看出来什么 ?
例子6:
def repeat(n)
n.times {yield} if block_given?
end
repeat(2) {puts "Hi"}

def repeat2(n, &block)
n.times {block.call} if block
end
repeat2(2) {puts "Hi2"}

def repeat3(n,&block)
n.times {yield} if block
end
repeat3(2){ puts "Hi3" }
这三种写法的目的是一样的。
例子7:
print "(t)imes or (p)lus"

times = gets

print "number:"
number = Integer(gets)
if times =~ /^t/
calc = lambda {|n| n*number }
else
calc = lambda {|n| n + number}
end

p((1..10).collect(&calc).join(", "))
这个例子也是闭包的概念。
例子8:
words = %w(Daffy, Bugs, Alvin)
upcase_words = words.map( &:upcase )

p upcase_words
例子的map(&:upcase)相当于map{ |x| x.upcase }
这个是如何实现的? 其实Symbol类内部实现了一个to_proc方法:
class Symbol
def to_proc
lambda { |x,*args| x.send(self, *args) }
end
end
map方法只接受代码块,通过使用&可传递proc,来代替显示的使用代码块。而这个时候&被应用于不是proc的对象,而传进来的本身是个符号对象(:&upcase),所以解释器自然而然的就会调用符号类的to_proc方法来得到一个proc。to_proc方法里的self引用的是对其调用了to_proc的符号。本文出自 “悟道集” 博客,请务必保留此出处http://blackanger.blog.51cto.com/140924/83701
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: