深入讲解Ruby中Block代码快的用法
Block
定义
some_array.each{|value|putsvalue+3}
sum=0
other_array.eachdo|value|
sum+=value
putsvalue/sum
end
- Ablockissomewhatlikethebodyofananonymousmethod
- Blockcantakeparameters
- Block只有被method调用时才会起作用,如果method中有参数,block出现在最后面
Block中的变量
如果block的本地变量的名字和block之外但是在同样scope里面的变量名字一样,那他们两个是一样的。block内变量的值会改变block外变量的值。
sum=0 [1,2,3,4].eachdo|value| sum+=value putsvalue/sum end putssum#=>30
如果block中的变量只出现在block中,那么它只是block中本地变量,无法在block之外被引用。
sum=0
[1,2,3,4].eachdo|value|
square=value*value
sum+=square
end
putssum#=>30
putssquare#undefinedlocalvariableormethod'square'formain:Object<NameError>
Parameterstoablockarealwayslocaltoablock,eveniftheyhavethesamenameaslocalsinthesurroundingscope.
value="someshape"
[1,2].each{|value|putsvalue}
putsvalue
#1
#2
#someshape
Youcandefineablock-localvariablesbyputtingthemafterssemicolonintheblock'sparameterlist
square="someshape"
sum=0
[1,2,3,4].eachdo|value;square|
square=value*value
sum+=square
end
putssum#30
putssquare#someshape
- Bymakingsquareblock-local,valuesassignedinsidetheblockwillnotaffectthevalueofthevariablewiththesamenameintheouterscope.
- BlocksforTransactions
- Youcanuseblockstodefineachunkofcodethatmustberunundersomekindoftransnationalcontrol
classFile
defself.open_and_process(*args)
f=File.open(*args)
yieldf
f.close
end
end
File.open_and_process("testfile","r")do|file|
whileline=file.gets
putsline
end
end
BlocksCanBeObjects
Youcanconvertablockintoanobject,storeitinvariables,passitaround,andtheninvokeitscodelater.
如果method的最后一个参数前面有&符号(&action),那么当此method被调用时,Ruby会找一个codeblock,这个codeblock被转换成classProc的一个对象。
classProcExample
defpass_in_block(&action)
@stored_proc=action
end
defuse_proc(parameter)
@store_proc.call(parameter)
end
end
eg=ProcExample.new
eg.pass_in_block{|param|puts"Theparameteris#{param}"}
eg.use_proc(99)
#=>Theparameteris99
defcreate_block_object(&block)
block
end
bo=create_block_object{|param|puts"Youcalledmewith#{param}"}
bo.call99#=>Youcalledmewith99
bo.call"cat"#=>Youcalledmewithcat
Rubyhavetwobuilt-inmethodsthatconvertablocktoanobject:lambdaandProc.new
bo=lambda{|param|puts"Youcalledmewith#{param}"}
bo.call99#=>Youcalledmewith99
- BlocksCanBeClosures
- Closure:VariablesinthesurroundingscopethatarereferencedinablockremainaccessibleaccessibleforthelifeofthatblockandthelifeonanyProcobjectcreatedfromthatblock.
defn_times(thing)
lambda{|n|thing*n}
end
p1=n_times(23)
p1.call(3)#=>69
p2.call(4)#=>92
defpower_proc_generator
value=1
lambda{value+=value}
end
power_proc=power_proc_generator
putspower_proc.call#2
putspower_proc.call#4
lambda表达式的另一种简写方式
lambda{|params|...}
#与下面的写法等价
->params{...}
#parmas是可选的
proc1=->arg1,arg2{puts"#{arg1}#{arg2}"}
proc1.call"hello","world"
#=>helloworld
proc2=->{"HelloWorld"}
proc2.call#=>HelloWorld
BlockParameterList
Blockscantakedefaultvalues,splatargs,keywordargsandablockparameter
proc=->a,*b,&blockdo
puts"a=#{a.inspect}"
puts"b=#{b.inspect}"
block.call
end
proc.call(1,2,3,4){puts"inblock"}
#a=1
#b=[2,3,4]
#inblock