зеркало из https://github.com/github/ruby.git
Describe lambda-ness of Proc more.
This commit is contained in:
Родитель
dda2c860d9
Коммит
357f295a0e
69
proc.c
69
proc.c
|
@ -172,8 +172,10 @@ proc_clone(VALUE self)
|
|||
* call-seq:
|
||||
* prc.lambda? -> true or false
|
||||
*
|
||||
* Returns +true+ for a Proc object for which argument handling is rigid.
|
||||
* Such procs are typically generated by +lambda+.
|
||||
* Returns +true+ if a Proc object is lambda.
|
||||
* +false+ if non-lambda.
|
||||
*
|
||||
* The lambda-ness affects argument handling and the behavior of +return+ and +break+.
|
||||
*
|
||||
* A Proc object generated by +proc+ ignores extra arguments.
|
||||
*
|
||||
|
@ -3370,9 +3372,11 @@ rb_method_compose_to_right(VALUE self, VALUE g)
|
|||
* Procs are coming in two flavors: lambda and non-lambda (regular procs).
|
||||
* Differences are:
|
||||
*
|
||||
* * In lambdas, +return+ means exit from this lambda;
|
||||
* * In regular procs, +return+ means exit from embracing method
|
||||
* * In lambdas, +return+ and +break+ means exit from this lambda;
|
||||
* * In non-lambda procs, +return+ means exit from embracing method
|
||||
* (and will throw +LocalJumpError+ if invoked outside the method);
|
||||
* * In non-lambda procs, +break+ means exit from the method which the block given for.
|
||||
* (and will throw +LocalJumpError+ if invoked after the method returns);
|
||||
* * In lambdas, arguments are treated in the same way as in methods: strict,
|
||||
* with +ArgumentError+ for mismatching argument number,
|
||||
* and no additional argument processing;
|
||||
|
@ -3383,6 +3387,40 @@ rb_method_compose_to_right(VALUE self, VALUE g)
|
|||
*
|
||||
* Examples:
|
||||
*
|
||||
* # +return+ in non-lambda proc, +b+, exits +m2+.
|
||||
* # (The block +{ return }+ is given for +m1+ and embraced by +m2+.)
|
||||
* $a = []; def m1(&b) b.call; $a << :m1 end; def m2() m1 { return }; $a << :m2 end; m2; p $a
|
||||
* #=> []
|
||||
*
|
||||
* # +break+ in non-lambda proc, +b+, exits +m1+.
|
||||
* # (The block +{ break }+ is given for +m1+ and embraced by +m2+.)
|
||||
* $a = []; def m1(&b) b.call; $a << :m1 end; def m2() m1 { break }; $a << :m2 end; m2; p $a
|
||||
* #=> [:m2]
|
||||
*
|
||||
* # +next+ in non-lambda proc, +b+, exits the block.
|
||||
* # (The block +{ next }+ is given for +m1+ and embraced by +m2+.)
|
||||
* $a = []; def m1(&b) b.call; $a << :m1 end; def m2() m1 { next }; $a << :m2 end; m2; p $a
|
||||
* #=> [:m1, :m2]
|
||||
*
|
||||
* # Using +proc+ method changes the behavior as follows because
|
||||
* # The block is given for +proc+ method and embraced by +m2+.
|
||||
* $a = []; def m1(&b) b.call; $a << :m1 end; def m2() m1(&proc { return }); $a << :m2 end; m2; p $a
|
||||
* #=> []
|
||||
* $a = []; def m1(&b) b.call; $a << :m1 end; def m2() m1(&proc { break }); $a << :m2 end; m2; p $a
|
||||
* # break from proc-closure (LocalJumpError)
|
||||
* $a = []; def m1(&b) b.call; $a << :m1 end; def m2() m1(&proc { next }); $a << :m2 end; m2; p $a
|
||||
* #=> [:m1, :m2]
|
||||
*
|
||||
* # +return+, +break+ and +next+ in the subby lambda exits the block.
|
||||
* # (+lambda+ method behaves same.)
|
||||
* # (The block is given for stubby lambda syntax and embraced by +m2+.)
|
||||
* $a = []; def m1(&b) b.call; $a << :m1 end; def m2() m1(&-> { return }); $a << :m2 end; m2; p $a
|
||||
* #=> [:m1, :m2]
|
||||
* $a = []; def m1(&b) b.call; $a << :m1 end; def m2() m1(&-> { break }); $a << :m2 end; m2; p $a
|
||||
* #=> [:m1, :m2]
|
||||
* $a = []; def m1(&b) b.call; $a << :m1 end; def m2() m1(&-> { next }); $a << :m2 end; m2; p $a
|
||||
* #=> [:m1, :m2]
|
||||
*
|
||||
* p = proc {|x, y| "x=#{x}, y=#{y}" }
|
||||
* p.call(1, 2) #=> "x=1, y=2"
|
||||
* p.call([1, 2]) #=> "x=1, y=2", array deconstructed
|
||||
|
@ -3487,6 +3525,29 @@ rb_method_compose_to_right(VALUE self, VALUE g)
|
|||
* {test: 1}.to_proc.call(:test) #=> 1
|
||||
* %i[test many keys].map(&{test: 1}) #=> [1, nil, nil]
|
||||
*
|
||||
* == Orphaned Proc
|
||||
*
|
||||
* +return+ and +break+ in a block exit a method.
|
||||
* If a Proc object is generated from the block and the Proc object
|
||||
* survives until the method is returned, +return+ and +break+ cannot work.
|
||||
* In such case, +return+ and +break+ raises LocalJumpError.
|
||||
* A Proc object in such situation is called as orphaned Proc object.
|
||||
*
|
||||
* Note that the method to exit is different for +return+ and +break+.
|
||||
* There is a situation that orphaned for +break+ but not orphaned for +return+.
|
||||
*
|
||||
* def m1(&b) b.call end; def m2(); m1 { return } end; m2 # ok
|
||||
* def m1(&b) b.call end; def m2(); m1 { break } end; m2 # ok
|
||||
*
|
||||
* def m1(&b) b end; def m2(); m1 { return }.call end; m2 # ok
|
||||
* def m1(&b) b end; def m2(); m1 { break }.call end; m2 # LocalJumpError
|
||||
*
|
||||
* def m1(&b) b end; def m2(); m1 { return } end; m2.call # LocalJumpError
|
||||
* def m1(&b) b end; def m2(); m1 { break } end; m2.call # LocalJumpError
|
||||
*
|
||||
* Since +return+ and +break+ exists the block itself in lambdas,
|
||||
* lambdas cannot be orphaned.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче