ÿØÿà JFIF    ÿÛ „  ( %!1!%)+//.383,7(-.+  -%%-////---/-.+/--+------/------/--0+--/-/-----.-----ÿÀ  ¥2" ÿÄ     ÿÄ J    ! 1AQ"aq2‘#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ÿ ‘ñ(ßw­pŽ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"aq2‘#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ÿ ‘ñ(ßw­pŽ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"aq2‘#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ÿ ‘ñ(ßw­pŽ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"aq2‘#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ÿ ‘ñ(ßw­pŽF|È¥ù®häðÍѶ¹‘[ÒinÙW¶ùñY˜Q{›K"išÒ[Ú8žë\F¹@-?v"ÔU”,ìöžkÿ {I‡£šÍ?e ríV ?> ......................................... ............................................................................. ???????????????????????????????????? ???????????????????????????????????? U:RDoc::TopLevel[ iI"$syntax/control_expressions.rdoc:ETcRDoc::Parser::Simpleo:RDoc::Markup::Document: @parts[S:RDoc::Markup::Heading: leveli: textI"Control Expressions;To:RDoc::Markup::BlankLineo:RDoc::Markup::Paragraph;[I"URuby has a variety of ways to control execution. All the expressions described ;TI"here return a value.;T@ o; ;[I"TFor the tests in these control expressions, +nil+ and +false+ are false-values ;TI"Tand +true+ and any other object are true-values. In this document "true" will ;TI";mean "true-value" and "false" will mean "false-value".;T@ S; ; i; I"+if+ Expression;T@ o; ;[I"RThe simplest +if+ expression has two parts, a "test" expression and a "then" ;TI"Oexpression. If the "test" expression evaluates to a true then the "then" ;TI"expression is evaluated.;T@ o; ;[I"#Here is a simple if statement:;T@ o:RDoc::Markup::Verbatim;[I"if true then ;TI"0 puts "the test resulted in a true-value" ;TI" end ;T: @format0o; ;[I"9This will print "the test resulted in a true-value".;T@ o; ;[I"The +then+ is optional:;T@ o;;[I" if true ;TI"0 puts "the test resulted in a true-value" ;TI" end ;T;0o; ;[I"TThis document will omit the optional +then+ for all expressions as that is the ;TI"most common usage of +if+.;T@ o; ;[I"SYou may also add an +else+ expression. If the test does not evaluate to true ;TI",the +else+ expression will be executed:;T@ o;;[ I"if false ;TI"0 puts "the test resulted in a true-value" ;TI" else ;TI"1 puts "the test resulted in a false-value" ;TI" end ;T;0o; ;[I":This will print "the test resulted in a false-value".;T@ o; ;[I"NYou may add an arbitrary number of extra tests to an if expression using ;TI"N+elsif+. An +elsif+ executes when all tests above the +elsif+ are false.;T@ o;;[I" a = 1 ;TI" ;TI"if a == 0 ;TI" puts "a is zero" ;TI"elsif a == 1 ;TI" puts "a is one" ;TI" else ;TI"$ puts "a is some other value" ;TI" end ;T;0o; ;[I"RThis will print "a is one" as 1 is not equal to 0. ;TI"ISince +else+ is only executed when there are no matching conditions.;T@ o; ;[I"SOnce a condition matches, either the +if+ condition or any +elsif+ condition, ;TI"Lthe +if+ expression is complete and no further tests will be performed.;T@ o; ;[I"DLike an +if+, an +elsif+ condition may be followed by a +then+.;T@ o; ;[I"0In this example only "a is one" is printed:;T@ o;;[I" a = 1 ;TI" ;TI"if a == 0 ;TI" puts "a is zero" ;TI"elsif a == 1 ;TI" puts "a is one" ;TI"elsif a >= 1 ;TI"0 puts "a is greater than or equal to one" ;TI" else ;TI"$ puts "a is some other value" ;TI" end ;T;0o; ;[I"SThe tests for +if+ and +elsif+ may have side-effects. The most common use of ;TI";side-effect is to cache a value into a local variable:;T@ o;;[I"if a = object.some_value ;TI" # do something to a ;TI" end ;T;0o; ;[I"NThe result value of an +if+ expression is the last value executed in the ;TI"expression.;T@ S; ; i; I"Ternary if;T@ o; ;[I"KYou may also write a if-then-else expression using ? and ;TI"&:. This ternary if:;T@ o;;[I":input_type = gets =~ /hello/i ? "greeting" : "other" ;T;0o; ;[I")Is the same as this +if+ expression:;T@ o;;[ I"input_type = ;TI" if gets =~ /hello/i ;TI" "greeting" ;TI" else ;TI" "other" ;TI" end ;T;0o; ;[ I"SWhile the ternary if is much shorter to write than the more verbose form, for ;TI"Oreadability it is recommended that the ternary if is only used for simple ;TI"Nconditionals. Also, avoid using multiple ternary conditions in the same ;TI")expression as this can be confusing.;T@ S; ; i; I"+unless+ Expression;T@ o; ;[I"SThe +unless+ expression is the opposite of the +if+ expression. If the value ;TI"1is false, the "then" expression is executed:;T@ o;;[I"unless true ;TI") puts "the value is a false-value" ;TI" end ;T;0o; ;[I"6This prints nothing as true is not a false-value.;T@ o; ;[I"AYou may use an optional +then+ with +unless+ just like +if+.;T@ o; ;[I"a = ;TI"0.zero?.;T@ o; ;[I"QSince the test is true it executes the "then" expression, p a. ;TI"QSince the +a+ in the body was recorded as a method which does not exist the ;TI"NameError is raised.;T@ o; ;[I"#The same is true for +unless+.;T@ S; ; i; I"+case+ Expression;T@ o; ;[I"3The +case+ expression can be used in two ways.;T@ o; ;[ I"QThe most common way is to compare an object against multiple patterns. The ;TI"[patterns are matched using the === method which is aliased to == on ;TI"OObject. Other classes must override it to give meaningful behavior. See ;TI",Module#=== and Regexp#=== for examples.;T@ o; ;[I"NHere is an example of using +case+ to compare a String against a pattern:;T@ o;;[ I"case "12345" ;TI"when /^1/ ;TI") puts "the string starts with one" ;TI" else ;TI"7 puts "I don't know what the string starts with" ;TI" end ;T;0o; ;[ I"PHere the string "12345" is compared with /^1/ by ;TI"Pcalling /^1/ === "12345" which returns +true+. Like the +if+ ;TI"Uexpression, the first +when+ that matches is executed and all other matches are ;TI" ignored.;T@ o; ;[I"5If no matches are found, the +else+ is executed.;T@ o; ;[I"OThe +else+ and +then+ are optional, this +case+ expression gives the same ;TI"result as the one above:;T@ o;;[ I"case "12345" ;TI"when /^1/ ;TI") puts "the string starts with one" ;TI" end ;T;0o; ;[I":You may place multiple conditions on the same +when+:;T@ o;;[ I"case "2" ;TI"when /^1/, "2" ;TI"3 puts "the string starts with one or is '2'" ;TI" end ;T;0o; ;[I"NRuby will try each condition in turn, so first /^1/ === "2" ;TI"Sreturns +false+, then "2" === "2" returns +true+, so "the string ;TI"+starts with one or is '2'" is printed.;T@ o; ;[I"RYou may use +then+ after the +when+ condition. This is most frequently used ;TI"6to place the body of the +when+ on a single line.;T@ o;;[ I" case a ;TI"+when 1, 2 then puts "a is one or two" ;TI"&when 3 then puts "a is three" ;TI"2else puts "I don't know what a is" ;TI" end ;T;0o; ;[I"MThe other way to use a +case+ expression is like an if-elsif expression:;T@ o;;[I" a = 2 ;TI" ;TI" case ;TI"when a == 1, a == 2 ;TI" puts "a is one or two" ;TI"when a == 3 ;TI" puts "a is three" ;TI" else ;TI"% puts "I don't know what a is" ;TI" end ;T;0o; ;[I"/Again, the +then+ and +else+ are optional.;T@ o; ;[I"OThe result value of a +case+ expression is the last value executed in the ;TI"expression.;T@ o; ;[I"ESince Ruby 2.7, +case+ expressions also provide a more powerful ;TI"3pattern matching feature via the +in+ keyword:;T@ o;;[ I"case {a: 1, b: 2, c: 3} ;TI"in a: Integer => m ;TI" "matched: #{m}" ;TI" else ;TI" "not matched" ;TI" end ;TI"# => "matched: 1" ;T;0o; ;[I"1The pattern matching syntax is described on ;TI";{its own page}[rdoc-ref:syntax/pattern_matching.rdoc].;T@ S; ; i; I"+while+ Loop;T@ o; ;[I"9The +while+ loop executes while a condition is true:;T@ o;;[ I" a = 0 ;TI" ;TI"while a < 10 do ;TI" p a ;TI" a += 1 ;TI" end ;TI" ;TI" p a ;T;0o; ;[I"TPrints the numbers 0 through 10. The condition a < 10 is checked ;TI"Obefore the loop is entered, then the body executes, then the condition is ;TI"Pchecked again. When the condition results in false the loop is terminated.;T@ o; ;[I"QThe +do+ keyword is optional. The following loop is equivalent to the loop ;TI" above:;T@ o;;[ I"while a < 10 ;TI" p a ;TI" a += 1 ;TI" end ;T;0o; ;[I"NThe result of a +while+ loop is +nil+ unless +break+ is used to supply a ;TI" value.;T@ S; ; i; I"+until+ Loop;T@ o; ;[I":The +until+ loop executes while a condition is false:;T@ o;;[ I" a = 0 ;TI" ;TI"until a > 10 do ;TI" p a ;TI" a += 1 ;TI" end ;TI" ;TI" p a ;T;0o; ;[I"TThis prints the numbers 0 through 11. Like a while loop the condition a ;TI"O> 10 is checked when entering the loop and each time the loop body ;TI"Lexecutes. If the condition is false the loop will continue to execute.;T@ o; ;[I"/Like a +while+ loop, the +do+ is optional.;T@ o; ;[I"QLike a +while+ loop, the result of an +until+ loop is nil unless +break+ is ;TI" used.;T@ S; ; i; I"+for+ Loop;T@ o; ;[I"LThe +for+ loop consists of +for+ followed by a variable to contain the ;TI"Titeration argument followed by +in+ and the value to iterate over using #each. ;TI"The +do+ is optional:;T@ o;;[I"for value in [1, 2, 3] do ;TI" puts value ;TI" end ;T;0o; ;[I"Prints 1, 2 and 3.;T@ o; ;[I"4Like +while+ and +until+, the +do+ is optional.;T@ o; ;[I"RThe +for+ loop is similar to using #each, but does not create a new variable ;TI" scope.;T@ o; ;[I"SThe result value of a +for+ loop is the value iterated over unless +break+ is ;TI" used.;T@ o; ;[I";The +for+ loop is rarely used in modern ruby programs.;T@ S; ; i; I"!Modifier +while+ and +until+;T@ o; ;[I"JLike +if+ and +unless+, +while+ and +until+ can be used as modifiers:;T@ o;;[ I" a = 0 ;TI" ;TI"a += 1 while a < 10 ;TI" ;TI"p a # prints 10 ;T;0o; ;[I" +until+ used as a modifier:;T@ o;;[ I" a = 0 ;TI" ;TI"a += 1 until a > 10 ;TI" ;TI"p a # prints 11 ;T;0o; ;[I"TYou can use +begin+ and +end+ to create a +while+ loop that runs the body once ;TI"before the condition:;T@ o;;[ I" a = 0 ;TI" ;TI" begin ;TI" a += 1 ;TI"end while a < 10 ;TI" ;TI"p a # prints 10 ;T;0o; ;[I"NIf you don't use +rescue+ or +ensure+, Ruby optimizes away any exception ;TI"handling overhead.;T@ S; ; i; I"+break+ Statement;T@ o; ;[I"uUse +break+ to leave a block early. This will stop iterating over the items in +values+ if one of them is even:;T@ o;;[ I"values.each do |value| ;TI" break if value.even? ;TI" ;TI" # ... ;TI" end ;T;0o; ;[I">You can also terminate from a +while+ loop using +break+:;T@ o;;[I" a = 0 ;TI" ;TI"while true do ;TI" p a ;TI" a += 1 ;TI" ;TI" break if a < 10 ;TI" end ;TI" ;TI" p a ;T;0o; ;[I"%This prints the numbers 0 and 1.;T@ o; ;[I"N+break+ accepts a value that supplies the result of the expression it is ;TI""breaking" out of:;T@ o;;[ I"(result = [1, 2, 3].each do |value| ;TI"& break value * 2 if value.even? ;TI" end ;TI" ;TI"p result # prints 4 ;T;0S; ; i; I"+next+ Statement;T@ o; ;[I":Use +next+ to skip the rest of the current iteration:;T@ o;;[ I"'result = [1, 2, 3].map do |value| ;TI" next if value.even? ;TI" ;TI" value * 2 ;TI" end ;TI" ;TI"#p result # prints [2, nil, 6] ;T;0o; ;[I"N+next+ accepts an argument that can be used as the result of the current ;TI"block iteration:;T@ o;;[ I"'result = [1, 2, 3].map do |value| ;TI"! next value if value.even? ;TI" ;TI" value * 2 ;TI" end ;TI" ;TI"!p result # prints [2, 2, 6] ;T;0S; ; i; I"+redo+ Statement;T@ o; ;[I".Use +redo+ to redo the current iteration:;T@ o;;[I"result = [] ;TI" ;TI"!while result.length < 10 do ;TI" result << result.length ;TI" ;TI"! redo if result.last.even? ;TI" ;TI"# result << result.length + 1 ;TI" end ;TI" ;TI"p result ;T;0o; ;[I"3This prints [0, 1, 3, 3, 5, 5, 7, 7, 9, 9, 11];T@ o; ;[ I"PIn Ruby 1.8, you could also use +retry+ where you used +redo+. This is no ;TI"Rlonger true, now you will receive a SyntaxError when you use +retry+ outside ;TI"Mof a +rescue+ block. See {Exceptions}[rdoc-ref:syntax/exceptions.rdoc] ;TI"!for proper usage of +retry+.;T@ S; ; i; I"Modifier Statements;T@ o; ;[ I"LRuby's grammar differentiates between statements and expressions. All ;TI"Lexpressions are statements (an expression is a type of statement), but ;TI"Knot all statements are expressions. Some parts of the grammar accept ;TI"Kexpressions and not other types of statements, which causes code that ;TI",looks similar to be parsed differently.;T@ o; ;[ I"OFor example, when not used as a modifier, +if+, +else+, +while+, +until+, ;TI"Gand +begin+ are expressions (and also statements). However, when ;TI"Eused as a modifier, +if+, +else+, +while+, +until+ and +rescue+ ;TI"(are statements but not expressions.;T@ o;;[I";if true; 1 end # expression (and therefore statement) ;TI"11 if true # statement (not expression) ;T;0o; ;[I"MStatements that are not expressions cannot be used in contexts where an ;TI"6expression is expected, such as method arguments.;T@ o;;[I",puts( 1 if true ) #=> SyntaxError ;T;0o; ;[I"EYou can wrap a statement in parentheses to create an expression.;T@ o;;[I""puts((1 if true)) #=> 1 ;T;0o; ;[I"MIf you put a space between the method name and opening parenthesis, you ;TI")do not need two sets of parentheses.;T@ o;;[I"Nputs (1 if true) #=> 1, because of optional parentheses for method ;T;0o; ;[I"EThis is because this is parsed similar to a method call without ;TI"Pparentheses. It is equivalent to the following code, without the creation ;TI"of a local variable:;T@ o;;[I"x = (1 if true) ;TI" p x ;T;0o; ;[I"MIn a modifier statement, the left-hand side must be a statement and the ;TI"+right-hand side must be an expression.;T@ o; ;[ I"NSo in a if b rescue c, because b rescue c is a ;TI"Nstatement that is not an expression, and therefore is not allowed as the ;TI"Mright-hand side of the +if+ modifier statement, the code is necessarily ;TI".parsed as (a if b) rescue c.;T@ o; ;[I"@This interacts with operator precedence in such a way that:;T@ o;;[I"stmt if v = expr rescue x ;TI"stmt if v = expr unless x ;T;0o; ;[I"are parsed as:;T@ o;;[I"!stmt if v = (expr rescue x) ;TI"!(stmt if v = expr) unless x ;T;0o; ;[I"RThis is because modifier +rescue+ has higher precedence than =, ;TI"@and modifier +if+ has lower precedence than =.;T@ S; ; i; I"Flip-Flop;T@ o; ;[I"MThe flip-flop is a slightly special conditional expression. One of its ;TI"Ktypical uses is processing text from ruby one-line programs used with ;TI"2ruby -n or ruby -p.;T@ o; ;[ I"HThe form of the flip-flop is an expression that indicates when the ;TI"Sflip-flop turns on, .. (or ...), then an expression ;TI"Tthat indicates when the flip-flop will turn off. While the flip-flop is on it ;TI"?will continue to evaluate to +true+, and +false+ when off.;T@ o; ;[I"Here is an example:;T@ o;;[ I"selected = [] ;TI" ;TI"0.upto 10 do |value| ;TI"/ selected << value if value==2..value==8 ;TI" end ;TI" ;TI"/p selected # prints [2, 3, 4, 5, 6, 7, 8] ;T;0o; ;[I"SIn the above example, the `on' condition is n==2. The flip-flop ;TI"Ois initially `off' (false) for 0 and 1, but becomes `on' (true) for 2 and ;TI"Rremains `on' through 8. After 8 it turns off and remains `off' for 9 and 10.;T@ o; ;[I"MThe flip-flop must be used inside a conditional such as !, ;TI"R? :, +not+, +if+, +while+, +unless+, +until+ etc. including the ;TI"modifier forms.;T@ o; ;[I"OWhen you use an inclusive range (..), the `off' condition is ;TI"/evaluated when the `on' condition changes:;T@ o;;[ I"selected = [] ;TI" ;TI"0.upto 5 do |value| ;TI"/ selected << value if value==2..value==2 ;TI" end ;TI" ;TI"p selected # prints [2] ;T;0o; ;[I"SHere, both sides of the flip-flop are evaluated so the flip-flop turns on and ;TI"Koff only when +value+ equals 2. Since the flip-flop turned on in the ;TI"iteration it returns true.;T@ o; ;[I"PWhen you use an exclusive range (...), the `off' condition is ;TI"*evaluated on the following iteration:;T@ o;;[ I"selected = [] ;TI" ;TI"0.upto 5 do |value| ;TI"0 selected << value if value==2...value==2 ;TI" end ;TI" ;TI"&p selected # prints [2, 3, 4, 5] ;T;0o; ;[I"UHere, the flip-flop turns on when +value+ equals 2, but doesn't turn off on the ;TI"Nsame iteration. The `off' condition isn't evaluated until the following ;TI"3iteration and +value+ will never be two again.;T@ S; ; i; I"throw/catch;T@ o; ;[ I"T+throw+ and +catch+ are used to implement non-local control flow in Ruby. They ;TI"Qoperate similarly to exceptions, allowing control to pass directly from the ;TI"Nplace where +throw+ is called to the place where the matching +catch+ is ;TI"Scalled. The main difference between +throw+/+catch+ and the use of exceptions ;TI"Ois that +throw+/+catch+ are designed for expected non-local control flow, ;TI"Qwhile exceptions are designed for exceptional control flow situations, such ;TI"#as handling unexpected errors.;T@ o; ;[ I"OWhen using +throw+, you provide 1-2 arguments. The first argument is the ;TI"Svalue for the matching +catch+. The second argument is optional (defaults to ;TI"O+nil+), and will be the value that +catch+ returns if there is a matching ;TI"P+throw+ inside the +catch+ block. If no matching +throw+ method is called ;TI"Pinside a +catch+ block, the +catch+ method returns the return value of the ;TI"block passed to it.;T@ o;;[I"def a(n) ;TI" throw :d, :a if n == 0 ;TI" b(n) ;TI" end ;TI" ;TI"def b(n) ;TI" throw :d, :b if n == 1 ;TI" c(n) ;TI" end ;TI" ;TI"def c(n) ;TI" throw :d if n == 2 ;TI" end ;TI" ;TI"4.times.map do |i| ;TI" catch(:d) do ;TI" a(i) ;TI" :default ;TI" end ;TI" end ;TI""# => [:a, :b, nil, :default] ;T;0o; ;[ I"LIf the first argument you pass to +throw+ is not handled by a matching ;TI"O+catch+, an UncaughtThrowError exception will be raised. This is because ;TI"O+throw+/+catch+ should only be used for expected control flow changes, so ;TI" :e ;TI"end;T;0: @file@:0@omit_headings_from_table_of_contents_below0