ÿØÿà JFIF ÿÛ „ ( %!1!%)+//.383,7(-.+
-%%-////---/-.+/--+------/------/--0+--/-/-----.-----ÿÀ ¥2" ÿÄ ÿÄ J ! 1AQ"aq2‘#BR‚¡ÁÑ3br’¢±Âð$CSƒ²á4c“%DsÓñÿÄ ÿÄ * !1AQa‘"2q3±ð#b¡ÿÚ ? ¼QxJQaÍuò¸Zö Úü8,ÐÚú
"SSn<rçù–´âE—^ªBÖ9À\†¸ÔÁTÃÛ5
ëd´³Í#Ý;Þ38œî ¶H£M:wÎ3…³…âpÔF&‚FK¸9„â4àGEõªfÿ ‘ñ(ßwpŽF|È¥ù®häðÍѶ¹‘[ÒinÙW¶ùñY˜Q{›K"išÒ[Ú8žë\F¹@-?v"ÔU”,ìöžkÿ {I‡£šÍ?e
ríV
?>
.........................................
.............................................................................
ÿØÿà JFIF ÿÛ „
(
%!1!%)+//.383,7(-.+
-%%-////---/-.+/--+------/------/--0+--/-/-----.-----ÿÀ ¥2" ÿÄ
ÿÄ J ! 1AQ"aq2‘#BR‚¡ÁÑ3br’¢±Âð$CSƒ²á4c“%DsÓñÿÄ
ÿÄ * !1AQa‘"2q3±ð#b¡ÿÚ
? ¼QxJQaÍuò¸Zö
Úü8,ÐÚú
"SSn<rçù–´âE—^ªBÖ9À\†¸ÔÁTÃÛ5
ëd´³Í#Ý;Þ38œî ¶H£M:wÎ3…³…âpÔF&‚FK¸9„â4àGEõªfÿ ‘ñ(ßwpŽF|È¥ù®häðÍѶ¹‘[ÒinÙW¶ùñY˜Q{›K"išÒ[Ú8žë\F¹@-?v"ÔU”,ìöžkÿ {I‡£šÍ?e
ríV
?>
.........................................
.............................................................................
????????????????????????????????????
????????????????????????????????????
ÿØÿà JFIF ÿÛ „ ( %!1!%)+//.383,7(-.+
-%%-////---/-.+/--+------/------/--0+--/-/-----.-----ÿÀ ¥2" ÿÄ ÿÄ J ! 1AQ"aq2‘#BR‚¡ÁÑ3br’¢±Âð$CSƒ²á4c“%DsÓñÿÄ ÿÄ * !1AQa‘"2q3±ð#b¡ÿÚ ? ¼QxJQaÍuò¸Zö Úü8,ÐÚú
"SSn<rçù–´âE—^ªBÖ9À\†¸ÔÁTÃÛ5
ëd´³Í#Ý;Þ38œî ¶H£M:wÎ3…³…âpÔF&‚FK¸9„â4àGEõªfÿ ‘ñ(ßwpŽF|È¥ù®häðÍѶ¹‘[ÒinÙW¶ùñY˜Q{›K"išÒ[Ú8žë\F¹@-?v"ÔU”,ìöžkÿ {I‡£šÍ?e
ríV
?>
.........................................
.............................................................................
ÿØÿà JFIF ÿÛ „
(
%!1!%)+//.383,7(-.+
-%%-////---/-.+/--+------/------/--0+--/-/-----.-----ÿÀ ¥2" ÿÄ
ÿÄ J ! 1AQ"aq2‘#BR‚¡ÁÑ3br’¢±Âð$CSƒ²á4c“%DsÓñÿÄ
ÿÄ * !1AQa‘"2q3±ð#b¡ÿÚ
? ¼QxJQaÍuò¸Zö
Úü8,ÐÚú
"SSn<rçù–´âE—^ªBÖ9À\†¸ÔÁTÃÛ5
ëd´³Í#Ý;Þ38œî ¶H£M:wÎ3…³…âpÔF&‚FK¸9„â4àGEõªfÿ ‘ñ(ßwpŽF|È¥ù®häðÍѶ¹‘[ÒinÙW¶ùñY˜Q{›K"išÒ[Ú8žë\F¹@-?v"ÔU”,ìöžkÿ {I‡£šÍ?e
ríV
?>
.........................................
.............................................................................
????????????????????????????????????
????????????????????????????????????
U:RDoc::NormalClass[iI" Proc:ET@I"Object;To:RDoc::Markup::Document:@parts[o;;[ro:RDoc::Markup::Paragraph;[ I"QA +Proc+ object is an encapsulation of a block of code, which can be stored ;TI"Qin a local variable, passed to a method or another Proc, and can be called. ;TI"GProc is an essential concept in Ruby and a core of its functional ;TI"programming features.;To:RDoc::Markup::BlankLine o:RDoc::Markup::Verbatim;[I"#square = Proc.new {|x| x**2 }
;TI"
;TI"square.call(3) #=> 9
;TI"# shorthands:
;TI"square.(3) #=> 9
;TI"square[3] #=> 9
;T:@format0o; ;[I"OProc objects are _closures_, meaning they remember and can use the entire ;TI"(context in which they were created.;T@o;;[I"def gen_times(factor)
;TI"Z Proc.new {|n| n*factor } # remembers the value of factor at the moment of creation
;TI" end
;TI"
;TI"times3 = gen_times(3)
;TI"times5 = gen_times(5)
;TI"
;TI"*times3.call(12) #=> 36
;TI"*times5.call(5) #=> 25
;TI"*times3.call(times5.call(4)) #=> 60
;T;0S:RDoc::Markup::Heading:
leveli: textI"
Creation;T@o; ;[I"/There are several methods to create a Proc;T@o:RDoc::Markup::List:
@type:BULLET:@items[
o:RDoc::Markup::ListItem:@label0;[o; ;[I"$Use the Proc class constructor:;T@o;;[I""proc1 = Proc.new {|x| x**2 }
;T;0o;;0;[o; ;[I";Use the Kernel#proc method as a shorthand of Proc.new:;T@o;;[I"proc2 = proc {|x| x**2 }
;T;0o;;0;[o; ;[I"LReceiving a block of code into proc argument (note the &):;T@o;;[
I"def make_proc(&block)
;TI"
block
;TI" end
;TI"
;TI"#proc3 = make_proc {|x| x**2 }
;T;0o;;0;[o; ;[I"KConstruct a proc with lambda semantics using the Kernel#lambda method ;TI"0(see below for explanations about lambdas):;T@o;;[I""lambda1 = lambda {|x| x**2 }
;T;0o;;0;[o; ;[I"^Use the {Lambda proc literal}[rdoc-ref:syntax/literals.rdoc@Lambda+Proc+Literals] syntax ;TI"4(also constructs a proc with lambda semantics):;T@o;;[I"lambda2 = ->(x) { x**2 }
;T;0S;
;i;I"$Lambda and non-lambda semantics;T@o; ;[I"MProcs are coming in two flavors: lambda and non-lambda (regular procs). ;TI"Differences are:;T@o;;;;[
o;;0;[o; ;[I"BIn lambdas, +return+ and +break+ means exit from this lambda;;To;;0;[o; ;[I"DIn non-lambda procs, +return+ means exit from embracing method ;TI"E(and will throw +LocalJumpError+ if invoked outside the method);;To;;0;[o; ;[I"XIn non-lambda procs, +break+ means exit from the method which the block given for. ;TI"K(and will throw +LocalJumpError+ if invoked after the method returns);;To;;0;[o; ;[I"NIn lambdas, arguments are treated in the same way as in methods: strict, ;TI";with +ArgumentError+ for mismatching argument number, ;TI"+and no additional argument processing;;To;;0;[o; ;[ I"GRegular procs accept arguments more generously: missing arguments ;TI"Lare filled with +nil+, single Array arguments are deconstructed if the ;TI"Hproc has multiple arguments, and there is no error raised on extra ;TI"arguments.;T@o; ;[I"Examples:;T@o;;[:I"5# +return+ in non-lambda proc, +b+, exits +m2+.
;TI"H# (The block +{ return }+ is given for +m1+ and embraced by +m2+.)
;TI"`$a = []; def m1(&b) b.call; $a << :m1 end; def m2() m1 { return }; $a << :m2 end; m2; p $a
;TI"#=> []
;TI"
;TI"4# +break+ in non-lambda proc, +b+, exits +m1+.
;TI"G# (The block +{ break }+ is given for +m1+ and embraced by +m2+.)
;TI"_$a = []; def m1(&b) b.call; $a << :m1 end; def m2() m1 { break }; $a << :m2 end; m2; p $a
;TI"#=> [:m2]
;TI"
;TI"8# +next+ in non-lambda proc, +b+, exits the block.
;TI"F# (The block +{ next }+ is given for +m1+ and embraced by +m2+.)
;TI"^$a = []; def m1(&b) b.call; $a << :m1 end; def m2() m1 { next }; $a << :m2 end; m2; p $a
;TI"#=> [:m1, :m2]
;TI"
;TI"C# Using +proc+ method changes the behavior as follows because
;TI"B# The block is given for +proc+ method and embraced by +m2+.
;TI"g$a = []; def m1(&b) b.call; $a << :m1 end; def m2() m1(&proc { return }); $a << :m2 end; m2; p $a
;TI"#=> []
;TI"f$a = []; def m1(&b) b.call; $a << :m1 end; def m2() m1(&proc { break }); $a << :m2 end; m2; p $a
;TI"0# break from proc-closure (LocalJumpError)
;TI"e$a = []; def m1(&b) b.call; $a << :m1 end; def m2() m1(&proc { next }); $a << :m2 end; m2; p $a
;TI"#=> [:m1, :m2]
;TI"
;TI"J# +return+, +break+ and +next+ in the stubby lambda exits the block.
;TI"'# (+lambda+ method behaves same.)
;TI"K# (The block is given for stubby lambda syntax and embraced by +m2+.)
;TI"e$a = []; def m1(&b) b.call; $a << :m1 end; def m2() m1(&-> { return }); $a << :m2 end; m2; p $a
;TI"#=> [:m1, :m2]
;TI"d$a = []; def m1(&b) b.call; $a << :m1 end; def m2() m1(&-> { break }); $a << :m2 end; m2; p $a
;TI"#=> [:m1, :m2]
;TI"c$a = []; def m1(&b) b.call; $a << :m1 end; def m2() m1(&-> { next }); $a << :m2 end; m2; p $a
;TI"#=> [:m1, :m2]
;TI"
;TI")p = proc {|x, y| "x=#{x}, y=#{y}" }
;TI"&p.call(1, 2) #=> "x=1, y=2"
;TI";p.call([1, 2]) #=> "x=1, y=2", array deconstructed
;TI"@p.call(1, 2, 8) #=> "x=1, y=2", extra argument discarded
;TI"Gp.call(1) #=> "x=1, y=", nil substituted instead of error
;TI"
;TI"+l = lambda {|x, y| "x=#{x}, y=#{y}" }
;TI"&l.call(1, 2) #=> "x=1, y=2"
;TI"Xl.call([1, 2]) # ArgumentError: wrong number of arguments (given 1, expected 2)
;TI"Xl.call(1, 2, 8) # ArgumentError: wrong number of arguments (given 3, expected 2)
;TI"Xl.call(1) # ArgumentError: wrong number of arguments (given 1, expected 2)
;TI"
;TI"def test_return
;TI"M -> { return 3 }.call # just returns from lambda into method body
;TI"7 proc { return 4 }.call # returns from method
;TI" return 5
;TI" end
;TI"
;TI"*test_return # => 4, return from proc
;T;0o; ;[I"NLambdas are useful as self-sufficient functions, in particular useful as ;TI"Marguments to higher-order functions, behaving exactly like Ruby methods.;T@o; ;[I"1Procs are useful for implementing iterators:;T@o;;[ I"def test
;TI"E [[1, 2], [3, 4], [5, 6]].map {|a, b| return a if a + b > 10 }
;TI"E # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
;TI" end
;T;0o; ;[ I"PInside +map+, the block of code is treated as a regular (non-lambda) proc, ;TI"Lwhich means that the internal arrays will be deconstructed to pairs of ;TI"Jarguments, and +return+ will exit from the method +test+. That would ;TI",not be possible with a stricter lambda.;T@o; ;[I"UYou can tell a lambda from a regular proc by using the #lambda? instance method.;T@o; ;[I"QLambda semantics is typically preserved during the proc lifetime, including ;TI"6&-deconstruction to a block of code:;T@o;;[ I"p = proc {|x, y| x }
;TI"l = lambda {|x, y| x }
;TI")[[1, 2], [3, 4]].map(&p) #=> [1, 3]
;TI"_[[1, 2], [3, 4]].map(&l) # ArgumentError: wrong number of arguments (given 1, expected 2)
;T;0o; ;[I"IThe only exception is dynamic method definition: even if defined by ;TI"Ppassing a non-lambda proc, methods still have normal semantics of argument ;TI"checking.;T@o;;[
I"
class C
;TI"# define_method(:e, &proc {})
;TI" end
;TI"*C.new.e(1,2) #=> ArgumentError
;TI"1C.new.method(:e).to_proc.lambda? #=> true
;T;0o; ;[I"MThis exception ensures that methods never have unusual argument passing ;TI"Kconventions, and makes it easy to have wrappers defining methods that ;TI"behave as usual.;T@o;;[
I"
class C
;TI"" def self.def2(name, &body)
;TI"$ define_method(name, &body)
;TI" end
;TI"
;TI" def2(:f) {}
;TI" end
;TI"*C.new.f(1,2) #=> ArgumentError
;T;0o; ;[I"IThe wrapper def2 receives _body_ as a non-lambda proc, ;TI"5yet defines a method which has normal semantics.;T@S;
;i;I")Conversion of other objects to procs;T@o; ;[I"KAny object that implements the +to_proc+ method can be converted into ;TI"Aa proc by the & operator, and therefore can be ;TI"consumed by iterators.;T@o;;[I"class Greeter
;TI" def initialize(greeting)
;TI" @greeting = greeting
;TI" end
;TI"
;TI" def to_proc
;TI"1 proc {|name| "#{@greeting}, #{name}!" }
;TI" end
;TI" end
;TI"
;TI"hi = Greeter.new("Hi")
;TI"hey = Greeter.new("Hey")
;TI"?["Bob", "Jane"].map(&hi) #=> ["Hi, Bob!", "Hi, Jane!"]
;TI"A["Bob", "Jane"].map(&hey) #=> ["Hey, Bob!", "Hey, Jane!"]
;T;0o; ;[I"EOf the Ruby core classes, this method is implemented by Symbol, ;TI"Method, and Hash.;T@o;;[
I"-:to_s.to_proc.call(1) #=> "1"
;TI"4[1, 2].map(&:to_s) #=> ["1", "2"]
;TI"
;TI"0method(:puts).to_proc.call(1) # prints 1
;TI"3[1, 2].each(&method(:puts)) # prints 1, 2
;TI"
;TI"/{test: 1}.to_proc.call(:test) #=> 1
;TI";%i[test many keys].map(&{test: 1}) #=> [1, nil, nil]
;T;0S;
;i;I"Orphaned Proc;T@o; ;[
I"4+return+ and +break+ in a block exit a method. ;TI"FIf a Proc object is generated from the block and the Proc object ;TI"Nsurvives until the method is returned, +return+ and +break+ cannot work. ;TI"?In such case, +return+ and +break+ raises LocalJumpError. ;TI"GA Proc object in such situation is called as orphaned Proc object.;T@o; ;[I"INote that the method to exit is different for +return+ and +break+. ;TI"RThere is a situation that orphaned for +break+ but not orphaned for +return+.;T@o;;[
I"Adef m1(&b) b.call end; def m2(); m1 { return } end; m2 # ok
;TI"@def m1(&b) b.call end; def m2(); m1 { break } end; m2 # ok
;TI"
;TI"Adef m1(&b) b end; def m2(); m1 { return }.call end; m2 # ok
;TI"Ldef m1(&b) b end; def m2(); m1 { break }.call end; m2 # LocalJumpError
;TI"
;TI"Mdef m1(&b) b end; def m2(); m1 { return } end; m2.call # LocalJumpError
;TI"Ldef m1(&b) b end; def m2(); m1 { break } end; m2.call # LocalJumpError
;T;0o; ;[I"CSince +return+ and +break+ exits the block itself in lambdas, ;TI" lambdas cannot be orphaned.;T@S;
;i;I"Anonymous block parameters;T@o; ;[I"LTo simplify writing short blocks, Ruby provides two different types of ;TI"Sanonymous parameters: +it+ (single parameter) and numbered ones: _1, ;TI"_2 and so on.;T@o;;[I"# Explicit parameter:
;TI"Q%w[test me please].each { |str| puts str.upcase } # prints TEST, ME, PLEASE
;TI"4(1..5).map { |i| i**2 } # => [1, 4, 9, 16, 25]
;TI"
;TI"# it:
;TI"J%w[test me please].each { puts it.upcase } # prints TEST, ME, PLEASE
;TI"1(1..5).map { it**2 } # => [1, 4, 9, 16, 25]
;TI"
;TI"# Numbered parameter:
;TI"J%w[test me please].each { puts _1.upcase } # prints TEST, ME, PLEASE
;TI"1(1..5).map { _1**2 } # => [1, 4, 9, 16, 25]
;T;0S;
;i;I" +it+;T@o; ;[I"Q+it+ is a name that is available inside a block when no explicit parameters ;TI"defined, as shown above.;T@o;;[I"J%w[test me please].each { puts it.upcase } # prints TEST, ME, PLEASE
;TI"1(1..5).map { it**2 } # => [1, 4, 9, 16, 25]
;T;0o; ;[I"M+it+ is a "soft keyword": it is not a reserved name, and can be used as ;TI",a name for methods and local variables:;T@o;;[ I"it = 5 # no warnings
;TI"2def it(&block) # RSpec-like API, no warnings
;TI" # ...
;TI" end
;T;0o; ;[I"K+it+ can be used as a local variable even in blocks that use it as an ;TI"Cimplicit parameter (though this style is obviously confusing):;T@o;;[I"[1, 2, 3].each {
;TI"A # takes a value of implicit parameter "it" and uses it to
;TI"4 # define a local variable with the same name
;TI" it = it**2
;TI" p it
;TI"}
;T;0o; ;[I"PIn a block with explicit parameters defined +it+ usage raises an exception:;T@o;;[ I"![1, 2, 3].each { |x| p it }
;TI"(# syntax error found (SyntaxError)
;TI"## [1, 2, 3].each { |x| p it }
;TI"[# ^~ `it` is not allowed when an ordinary parameter is defined
;T;0o; ;[I"MBut if a local name (variable or method) is available, it would be used:;T@o;;[I"it = 5
;TI"![1, 2, 3].each { |x| p it }
;TI"# Prints 5, 5, 5
;T;0o; ;[I"%Blocks using +it+ can be nested:;T@o;;[I"0%w[test me].each { it.each_char { p it } }
;TI"+# Prints "t", "e", "s", "t", "m", "e"
;T;0o; ;[I" [[:opt, nil]]
;TI"p.arity # => 1
;TI"$l.parameters # => [[:req]]
;TI"l.arity # => 1
;T;0S;
;i;I"Numbered parameters;T@o; ;[I"NNumbered parameters are another way to name block parameters implicitly. ;TI"KUnlike +it+, numbered parameters allow to refer to several parameters ;TI"in one block.;T@o;;[I"J%w[test me please].each { puts _1.upcase } # prints TEST, ME, PLEASE
;TI"H{a: 100, b: 200}.map { "#{_1} = #{_2}" } # => "a = 100", "b = 200"
;T;0o; ;[I"5Parameter names from +_1+ to +_9+ are supported:;T@o;;[I"G[10, 20, 30].zip([40, 50, 60], [70, 80, 90]).map { _1 + _2 + _3 }
;TI"# => [120, 150, 180]
;T;0o; ;[I"GThough, it is advised to resort to them wisely, probably limiting ;TI"7yourself to +_1+ and +_2+, and to one-line blocks.;T@o; ;[I"FNumbered parameters can't be used together with explicitly named ;TI"
ones:;T@o;;[I"$[10, 20, 30].map { |x| _1**2 }
;TI"3# SyntaxError (ordinary parameter is defined)
;T;0o; ;[I"9Numbered parameters can't be mixed with +it+ either:;T@o;;[I""[10, 20, 30].map { _1 + it }
;TI"R# SyntaxError: `it` is not allowed when a numbered parameter is already used
;T;0o; ;[I":To avoid conflicts, naming local variables or method ;TI"5arguments +_1+, +_2+ and so on, causes an error.;T@o;;[I" _1 = 'test'
;TI"?# ^~ _1 is reserved for numbered parameters (SyntaxError)
;T;0o; ;[I">Using implicit numbered parameters affects block's arity:;T@o;;[I"p = proc { _1 + _2 }
;TI"l = lambda { _1 + _2 }
;TI"6p.parameters # => [[:opt, :_1], [:opt, :_2]]
;TI"p.arity # => 2
;TI"6l.parameters # => [[:req, :_1], [:req, :_2]]
;TI"l.arity # => 2
;T;0o; ;[I"5Blocks with numbered parameters can't be nested:;T@o;;[ I"0%w[test me].each { _1.each_char { p _1 } }
;TI"G# numbered parameter is already used in outer block (SyntaxError)
;TI"2# %w[test me].each { _1.each_char { p _1 } }
;TI"# ^~;T;0:
@fileI"proc.c;T:0@omit_headings_from_table_of_contents_below0;0;0[ [ [ [[I"
class;T[[:public[[I"new;TI"proc.c;T[:protected[ [:private[ [I"
instance;T[[;[[I"<<;T@[I"==;T@[I"===;T@[I">>;T@[I"[];T@[I"
arity;T@[I"binding;T@[I" call;T@[I"
curry;T@[I" eql?;T@[I" hash;T@[I"inspect;T@[I"lambda?;T@[I"parameters;T@[I"ruby2_keywords;T@[I"source_location;T@[I"to_proc;T@[I" to_s;T@[I"
yield;T@[;[ [;[ [ [U:RDoc::Context::Section[i 0o;;[ ;0;0[@@cRDoc::TopLevel