深入讲解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