diff options
author | usa <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2017-12-14 15:09:35 +0000 |
---|---|---|
committer | usa <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2017-12-14 15:09:35 +0000 |
commit | 1a74fa4b04da04bd2bb33103dd3cf431438df38e (patch) | |
tree | f4a1d6c2961339e0c1d653c0f8427a53315080f0 /ruby_2_2/doc/syntax | |
parent | a5b755e50e2d9aabf28ba24bf58644ca22b01a4f (diff) |
add tag v2_2_9
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/tags/v2_2_9@61257 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ruby_2_2/doc/syntax')
-rw-r--r-- | ruby_2_2/doc/syntax/assignment.rdoc | 455 | ||||
-rw-r--r-- | ruby_2_2/doc/syntax/calling_methods.rdoc | 349 | ||||
-rw-r--r-- | ruby_2_2/doc/syntax/control_expressions.rdoc | 500 | ||||
-rw-r--r-- | ruby_2_2/doc/syntax/exceptions.rdoc | 96 | ||||
-rw-r--r-- | ruby_2_2/doc/syntax/literals.rdoc | 347 | ||||
-rw-r--r-- | ruby_2_2/doc/syntax/methods.rdoc | 456 | ||||
-rw-r--r-- | ruby_2_2/doc/syntax/miscellaneous.rdoc | 107 | ||||
-rw-r--r-- | ruby_2_2/doc/syntax/modules_and_classes.rdoc | 345 | ||||
-rw-r--r-- | ruby_2_2/doc/syntax/precedence.rdoc | 60 | ||||
-rw-r--r-- | ruby_2_2/doc/syntax/refinements.rdoc | 261 |
10 files changed, 2976 insertions, 0 deletions
diff --git a/ruby_2_2/doc/syntax/assignment.rdoc b/ruby_2_2/doc/syntax/assignment.rdoc new file mode 100644 index 0000000000..adfe6485a4 --- /dev/null +++ b/ruby_2_2/doc/syntax/assignment.rdoc @@ -0,0 +1,455 @@ += Assignment + +In Ruby assignment uses the <code>=</code> (equals sign) character. This +example assigns the number five to the local variable +v+: + + v = 5 + +Assignment creates a local variable if the variable was not previously +referenced. + +== Local Variable Names + +A local variable name must start with a lowercase US-ASCII letter or a +character with the eight bit set. Typically local variables are US-ASCII +compatible since the keys to type them exist on all keyboards. + +(Ruby programs must be written in a US-ASCII-compatible character set. In +such character sets if the eight bit is set it indicates an extended +character. Ruby allows local variables to contain such characters.) + +A local variable name may contain letters, numbers, an <code>_</code> +(underscore or low line) or a character with the eighth bit set. + +== Local Variable Scope + +Once a local variable name has been assigned-to all uses of the name for the +rest of the scope are considered local variables. + +Here is an example: + + 1.times do + a = 1 + puts "local variables in the block: #{local_variables.join ", "}" + end + + puts "no local variables outside the block" if local_variables.empty? + +This prints: + + local variables in the block: a + no local variables outside the block + +Since the block creates a new scope, any local variables created inside it do +not leak to the surrounding scope. + +Variables defined in an outer scope appear inner scope: + + a = 0 + + 1.times do + puts "local variables: #{local_variables.join ", "}" + end + +This prints: + + local variables: a + +You may isolate variables in a block from the outer scope by listing them +following a <code>;</code> in the block's arguments. See the documentation +for block local variables in the {calling +methods}[rdoc-ref:syntax/calling_methods.rdoc] documentation for an example. + +See also Kernel#local_variables, but note that a +for+ loop does not create a +new scope like a block does. + +== Local Variables and Methods + +In Ruby local variable names and method names are nearly identical. If you +have not assigned to one of these ambiguous names ruby will assume you wish to +call a method. Once you have assigned to the name ruby will assume you wish +to reference a local variable. + +The local variable is created when the parser encounters the assignment, not +when the assignment occurs: + + a = 0 if false # does not assign to a + + p local_variables # prints [:a] + + p a # prints nil + +The similarity between method and local variable names can lead to confusing +code, for example: + + def big_calculation + 42 # pretend this takes a long time + end + + big_calculation = big_calculation() + +Now any reference to +big_calculation+ is considered a local variable and will +be cached. To call the method, use <code>self.big_calculation</code>. + +You can force a method call by using empty argument parentheses as shown above +or by using an explicit receiver like <code>self.</code>. Using an explicit +receiver may raise a NameError if the method's visibility is not public. + +Another commonly confusing case is when using a modifier +if+: + + p a if a = 0.zero? + +Rather than printing "true" you receive a NameError, "undefined local variable +or method `a'". Since ruby parses the bare +a+ left of the +if+ first and has +not yet seen an assignment to +a+ it assumes you wish to call a method. Ruby +then sees the assignment to +a+ and will assume you are referencing a local +method. + +The confusion comes from the out-of-order execution of the expression. First +the local variable is assigned-to then you attempt to call a nonexistent +method. + +== Instance Variables + +Instance variables are shared across all methods for the same object. + +An instance variable must start with a <code>@</code> ("at" sign or +commercial at). Otherwise instance variable names follow the rules as local +variable names. Since the instance variable starts with an <code>@</code> the +second character may be an upper-case letter. + +Here is an example of instance variable usage: + + class C + def initialize(value) + @instance_variable = value + end + + def value + @instance_variable + end + end + + object1 = C.new "some value" + object2 = C.new "other value" + + p object1.value # prints "some value" + p object2.value # prints "other value" + +An uninitialized instance variable has a value of +nil+. If you run Ruby with +warnings enabled you will get a warning when accessing an uninitialized +instance variable. + +The +value+ method has access to the value set by the +initialize+ method, but +only for the same object. + +== Class Variables + +Class variables are shared between a class, its subclasses and its instances. + +A class variable must start with a <code>@@</code> (two "at" signs). The rest +of the name follows the same rules as instance variables. + +Here is an example: + + class A + @@class_variable = 0 + + def value + @@class_variable + end + + def update + @@class_variable = @@class_variable + 1 + end + end + + class B < A + def update + @@class_variable = @@class_variable + 2 + end + end + + a = A.new + b = B.new + + puts "A value: #{a.value}" + puts "B value: #{b.value}" + +This prints: + + A value: 0 + B value: 0 + +Continuing with the same example, we can update using objects from either +class and the value is shared: + + puts "update A" + a.update + + puts "A value: #{a.value}" + puts "B value: #{b.value}" + + puts "update B" + b.update + + puts "A value: #{a.value}" + puts "B value: #{b.value}" + + puts "update A" + a.update + + puts "A value: #{a.value}" + puts "B value: #{b.value}" + +This prints: + + update A + A value: 1 + B value: 1 + update B + A value: 3 + B value: 3 + update A + A value: 4 + B value: 4 + +Accessing an uninitialized class variable will raise a NameError exception. + +Note that classes have instance variables because classes are objects, so +try not to confuse class and instance variables. + +== Global Variables + +Global variables are accessible everywhere. + +Global variables start with a <code>$</code> (dollar sign). The rest of the +name follows the same rules as instance variables. + +Here is an example: + + $global = 0 + + class C + puts "in a class: #{$global}" + + def my_method + puts "in a method: #{$global}" + + $global = $global + 1 + $other_global = 3 + end + end + + C.new.my_method + + puts "at top-level, $global: #{$global}, $other_global: #{$other_global}" + +This prints: + + in a class: 0 + in a method: 0 + at top-level, $global: 1, $other_global: 3 + +An uninitialized global variable has a value of +nil+. + +Ruby has some special globals that behave differently depending on context +such as the regular expression match variables or that have a side-effect when +assigned to. See the {global variables documentation}[rdoc-ref:globals.rdoc] +for details. + +== Assignment Methods + +You can define methods that will behave like assignment, for example: + + class C + def value=(value) + @value = value + end + end + + c = C.new + c.value = 42 + +Using assignment methods allows your programs to look nicer. When assigning +to an instance variable most people use Module#attr_accessor: + + class C + attr_accessor :value + end + +When using method assignment you must always have a receiver. If you do not +have a receiver Ruby assumes you are assigning to a local variable: + + class C + attr_accessor :value + + def my_method + value = 42 + + puts "local_variables: #{local_variables.join ", "}" + puts "@value: #{@value.inspect}" + end + end + + C.new.my_method + +This prints: + + local_variables: value + @value: nil + +To use the assignment method you must set the receiver: + + class C + attr_accessor :value + + def my_method + self.value = 42 + + puts "local_variables: #{local_variables.join ", "}" + puts "@value: #{@value.inspect}" + end + end + + C.new.my_method + +This prints: + + local_variables: + @value: 42 + +== Abbreviated Assignment + +You can mix several of the operators and assignment. To add 1 to an object +you can write: + + a = 1 + + a += 2 + + p a # prints 3 + +This is equivalent to: + + a = 1 + + a = a + 2 + + p a # prints 3 + +You can use the following operators this way: <code>+</code>, <code>-</code>, +<code>*</code>, <code>/</code>, <code>%</code>, <code>**</code>, +<code>&</code>, <code>|</code>, <code>^</code>, <code><<</code>, +<code>>></code> + +There are also <code>||=</code> and <code>&&=</code>. The former makes an +assignment if the value was +nil+ or +false+ while the latter makes an +assignment if the value was not +nil+ or +false+. + +Here is an example: + + a ||= 0 + a &&= 1 + + p a # prints 1 + +Note that these two operators behave more like <code>a || a = 0</code> than +<code>a = a || 0</code>. + +== Implicit Array Assignment + +You can implicitly create an array by listing multiple values when assigning: + + a = 1, 2, 3 + + p a # prints [1, 2, 3] + +This implicitly creates an Array. + +You can use <code>*</code> or the "splat" operator or unpack an Array when +assigning. This is similar to multiple assignment: + + a = *[1, 2, 3] + + p a # prints [1, 2, 3] + +You can splat anywhere in the right-hand side of the assignment: + + a = 1, *[2, 3] + + p a # prints [1, 2, 3] + +== Multiple Assignment + +You can assign multiple values on the right-hand side to multiple variables: + + a, b = 1, 2 + + p a: a, b: b # prints {:a=>1, :b=>2} + +In the following sections any place "variable" is used an assignment method, +instance, class or global will also work: + + def value=(value) + p assigned: value + end + + self.value, $global = 1, 2 # prints {:assigned=>1} + + p $global # prints 2 + +You can use multiple assignment to swap two values in-place: + + old_value = 1 + + new_value, old_value = old_value, 2 + + p new_value: new_value, old_value: old_value + # prints {:new_value=>1, :old_value=>2} + +If you have more values on the right hand side of the assignment than variables +on the left hand side the extra values are ignored: + + a, b = 1, 2, 3 + + p a: a, b: b # prints {:a=>1, :b=>2} + +You can use <code>*</code> to gather extra values on the right-hand side of +the assignment. + + a, *b = 1, 2, 3 + + p a: a, b: b # prints {:a=>1, :b=>[2, 3]} + +The <code>*</code> can appear anywhere on the left-hand side: + + *a, b = 1, 2, 3 + + p a: a, b: b # prints {:a=>[1, 2], :b=>3} + +But you may only use one <code>*</code> in an assignment. + +== Array Decomposition + +Like Array decomposition in {method arguments}[rdoc-ref:syntax/methods.rdoc] +you can decompose an Array during assignment using parenthesis: + + (a, b) = [1, 2] + + p a: a, b: b # prints {:a=>1, :b=>2} + +You can decompose an Array as part of a larger multiple assignment: + + a, (b, c) = 1, [2, 3] + + p a: a, b: b, c: c # prints {:a=>1, :b=>2, :c=>3} + +Since each decomposition is considered its own multiple assignment you can use +<code>*</code> to gather arguments in the decomposition: + + a, (b, *c), *d = 1, [2, 3, 4], 5, 6 + + p a: a, b: b, c: c, d: d + # prints {:a=>1, :b=>2, :c=>[3, 4], :d=>[5, 6]} + diff --git a/ruby_2_2/doc/syntax/calling_methods.rdoc b/ruby_2_2/doc/syntax/calling_methods.rdoc new file mode 100644 index 0000000000..79c0de59dc --- /dev/null +++ b/ruby_2_2/doc/syntax/calling_methods.rdoc @@ -0,0 +1,349 @@ += Calling Methods + +Calling a method sends a message to an object so it can perform some work. + +In ruby you send a message to an object like this: + + my_method() + +Note that the parenthesis are optional: + + my_method + +Except when there is difference between using and omitting parentheses, this +document uses parenthesis when arguments are present to avoid confusion. + +This section only covers calling methods. See also the {syntax documentation +on defining methods}[rdoc-ref:syntax/methods.rdoc]. + +== Receiver + ++self+ is the default receiver. If you don't specify any receiver +self+ will +be used. To specify a receiver use <code>.</code>: + + my_object.my_method + +This sends the +my_method+ message to +my_object+. Any object can be a +receiver but depending on the method's visibility sending a message may raise a +NoMethodError. + +You may also use <code>::</code> to designate a receiver, but this is rarely +used due to the potential for confusion with <code>::</code> for namespaces. + +== Arguments + +There are three types of arguments when sending a message, the positional +arguments, keyword (or named) arguments and the block argument. Each message +sent may use one, two or all types of arguments, but the arguments must be +supplied in this order. + +All arguments in ruby are passed by reference and are not lazily evaluated. + +Each argument is separated by a <code>,</code>: + + my_method(1, '2', :three) + +Arguments may be an expression, a hash argument: + + 'key' => value + +or a keyword argument: + + key: value + +Hash and keyword arguments must be contiguous and must appear after all +positional arguments, but may be mixed: + + my_method('a' => 1, b: 2, 'c' => 3) + +=== Positional Arguments + +The positional arguments for the message follow the method name: + + my_method(argument1, argument2) + +In many cases parenthesis are not necessary when sending a message: + + my_method argument1, argument2 + +However, parenthesis are necessary to avoid ambiguity. This will raise a +SyntaxError because ruby does not know which method argument3 should be sent +to: + + method_one argument1, method_two argument2, argument3 + +If the method definition has a <code>*argument</code> extra positional +arguments will be assigned to +argument+ in the method as an Array. + +If the method definition doesn't include keyword arguments the keyword or +hash-type arguments are assigned as a single hash to the last argument: + + def my_method(options) + p options + end + + my_method('a' => 1, b: 2) # prints: {'a'=>1, :b=>2} + +If too many positional arguments are given an ArgumentError is raised. + +=== Default Positional Arguments + +When the method defines default arguments you do not need to supply all the +arguments to the method. Ruby will fill in the missing arguments in-order. + +First we'll cover the simple case where the default arguments appear on the +right. Consider this method: + + def my_method(a, b, c = 3, d = 4) + p [a, b, c, d] + end + +Here +c+ and +d+ have default values which ruby will apply for you. If you +send only two arguments to this method: + + my_method(1, 2) + +You will see ruby print <code>[1, 2, 3, 4]</code>. + +If you send three arguments: + + my_method(1, 2, 5) + +You will see ruby print <code>[1, 2, 5, 4]</code> + +Ruby fills in the missing arguments from left to right. + +Ruby allows default values to appear in the middle of positional arguments. +Consider this more complicated method: + + def my_method(a, b = 2, c = 3, d) + p [a, b, c, d] + end + +Here +b+ and +c+ have default values. If you send only two arguments to this +method: + + my_method(1, 4) + +You will see ruby print <code>[1, 2, 3, 4]</code>. + +If you send three arguments: + + my_method(1, 5, 6) + +You will see ruby print <code>[1, 5, 3, 6]</code>. + +Describing this in words gets complicated and confusing. I'll describe it +in variables and values instead. + +First <code>1</code> is assigned to +a+, then <code>6</code> is assigned to ++d+. This leaves only the arguments with default values. Since +<code>5</code> has not been assigned to a value yet, it is given to +b+ and ++c+ uses its default value of <code>3</code>. + +=== Keyword Arguments + +Keyword arguments follow any positional arguments and are separated by commas +like positional arguments: + + my_method(positional1, keyword1: value1, keyword2: value2) + +Any keyword arguments not given will use the default value from the method +definition. If a keyword argument is given that the method did not list an +ArgumentError will be raised. + +=== Block Argument + +The block argument sends a closure from the calling scope to the method. + +The block argument is always last when sending a message to a method. A block +is sent to a method using <code>do ... end</code> or <code>{ ... }</code>: + + my_method do + # ... + end + +or: + + my_method { + # ... + } + +<code>do end</code> has lower precedence than <code>{ }</code> so: + + method_1 method_2 { + # ... + } + +Sends the block to +method_2+ while: + + method_1 method_2 do + # ... + end + +Sends the block to +method_1+. Note that in the first case if parentheses are +used the block is sent to +method_1+. + +A block will accept arguments from the method it was sent to. Arguments are +defined similar to the way a method defines arguments. The block's arguments +go in <code>| ... |</code> following the opening <code>do</code> or +<code>{</code>: + + my_method do |argument1, argument2| + # ... + end + +==== Block Local Arguments + +You may also declare block-local arguments to a block using <code>;</code> in +the block arguments list. Assigning to a block-local argument will not +override local arguments outside the block in the caller's scope: + + def my_method + yield self + end + + place = "world" + + my_method do |obj; place| + place = "block" + puts "hello #{obj} this is #{place}" + end + + puts "place is: #{place}" + +This prints: + + hello main this is block + place is world + +So the +place+ variable in the block is not the same +place+ variable as +outside the block. Removing <code>; place</code> from the block arguments +gives this result: + + hello main this is block + place is block + +=== Array to Arguments Conversion + +Given the following method: + + def my_method(argument1, argument2, argument3) + end + +You can turn an Array into an argument list with <code>*</code> (or splat) +operator: + + arguments = [1, 2, 3] + my_method(*arguments) + +or: + + arguments = [2, 3] + my_method(1, *arguments) + +Both are equivalent to: + + my_method(1, 2, 3) + +If the method accepts keyword arguments the splat operator will convert a hash +at the end of the array into keyword arguments: + + def my_method(a, b, c: 3) + end + + arguments = [1, 2, { c: 4 }] + my_method(*arguments) + +You may also use the <code>**</code> (described next) to convert a Hash into +keyword arguments. + +If the number of objects in the Array do not match the number of arguments for +the method an ArgumentError will be raised. + +If the splat operator comes first in the call, parentheses must be used to +avoid a warning. + +=== Hash to Keyword Arguments Conversion + +Given the following method: + + def my_method(first: 1, second: 2, third: 3) + end + +You can turn a Hash into keyword arguments with the <code>**</code> operator: + + arguments = { first: 3, second: 4, third: 5 } + my_method(**arguments) + +or: + + arguments = { first: 3, second: 4 } + my_method(third: 5, **arguments) + +Both are equivalent to: + + my_method(first: 3, second: 4, third: 5) + +If the method definition uses <code>**</code> to gather arbitrary keyword +arguments they will not be gathered by <code>*</code>: + + def my_method(*a, **kw) + p arguments: a, keywords: kw + end + + my_method(1, 2, '3' => 4, five: 6) + +Prints: + + {:arguments=>[1, 2], :keywords=>{"3"=>4, :five=>6}} + +Unlike the splat operator described above the <code>**</code> operator has no +commonly recognized name. + +=== Proc to Block Conversion + +Given a method that use a block: + + def my_method + yield self + end + +You can convert a proc or lambda to a block argument with the <code>&</code> +operator: + + argument = proc { |a| puts "#{a.inspect} was yielded" } + + my_method(&argument) + +If the splat operator comes first in the call, parenthesis must be used to +avoid a warning. + +Unlike the splat operator described above the <code>&</code> operator has no +commonly recognized name. + +== Method Lookup + +When you send a message Ruby looks up the method that matches the name of the +message for the receiver. Methods are stored in classes and modules so method +lookup walks these, not the objects themselves. + +Here is the order of method lookup for the receiver's class or module +R+: + +* The prepended modules of +R+ in reverse order +* For a matching method in +R+ +* The included modules of +R+ in reverse order + +If +R+ is a class with a superclass, this is repeated with +R+'s superclass +until a method is found. + +Once a match is found method lookup stops. + +If no match is found this repeats from the beginning, but looking for ++method_missing+. The default +method_missing+ is BasicObject#method_missing +which raises a NameError when invoked. + +If refinements (an experimental feature) are active the method lookup changes. +See the {refinements documentation}[rdoc-ref:syntax/refinements.rdoc] for +details. + diff --git a/ruby_2_2/doc/syntax/control_expressions.rdoc b/ruby_2_2/doc/syntax/control_expressions.rdoc new file mode 100644 index 0000000000..0efc1668ad --- /dev/null +++ b/ruby_2_2/doc/syntax/control_expressions.rdoc @@ -0,0 +1,500 @@ += Control Expressions + +Ruby has a variety of ways to control execution. All the expressions described +here return a value. + +For the tests in these control expressions, +nil+ and +false+ are false-values +and +true+ and any other object are true-values. In this document "true" will +mean "true-value" and "false" will mean "false-value". + +== +if+ Expression + +The simplest +if+ expression has two parts, a "test" expression and a "then" +expression. If the "test" expression evaluates to a true then the "then" +expression is evaluated. + +Here is a simple if statement: + + if true then + puts "the test resulted in a true-value" + end + +This will print "the test resulted in a true-value". + +The +then+ is optional: + + if true + puts "the test resulted in a true-value" + end + +This document will omit the optional +then+ for all expressions as that is the +most common usage of +if+. + +You may also add an +else+ expression. If the test does not evaluate to true +the +else+ expression will be executed: + + if false + puts "the test resulted in a true-value" + else + puts "the test resulted in a false-value" + end + +This will print "the test resulted in a false-value". + +You may add an arbitrary number of extra tests to an if expression using ++elsif+. An +elsif+ executes when all tests above the +elsif+ are false. + + a = 1 + + if a == 0 + puts "a is zero" + elsif a == 1 + puts "a is one" + else + puts "a is some other value" + end + +This will print "a is one" as <code>1</code> is not equal to <code>0</code>. +Since +else+ is only executed when there are no matching conditions. + +Once a condition matches, either the +if+ condition or any +elsif+ condition, +the +if+ expression is complete and no further tests will be performed. + +Like an +if+, an +elsif+ condition may be followed by a +then+. + +In this example only "a is one" is printed: + + a = 1 + + if a == 0 + puts "a is zero" + elsif a == 1 + puts "a is one" + elsif a >= 1 + puts "a is greater than or equal to one" + else + puts "a is some other value" + end + +The tests for +if+ and +elsif+ may have side-effects. The most common use of +side-effect is to cache a value into a local variable: + + if a = object.some_value + # do something to a + end + +The result value of an +if+ expression is the last value executed in the +expression. + +== Ternary if + +You may also write a if-then-else expression using <code>?</code> and +<code>:</code>. This ternary if: + + input_type = gets =~ /hello/i ? "greeting" : "other" + +Is the same as this +if+ expression: + + input_type = + if gets =~ /hello/i + "greeting" + else + "other" + end + +While the ternary if is much shorter to write than the more verbose form, for +readability it is recommended that the ternary if is only used for simple +conditionals. Also, avoid using multiple ternary conditions in the same +expression as this can be confusing. + +== +unless+ Expression + +The +unless+ expression is the opposite of the +if+ expression. If the value +is false the "then" expression is executed: + + unless true + puts "the value is a false-value" + end + +This prints nothing as true is not a false-value. + +You may use an optional +then+ with +unless+ just like +if+. + +Note that the above +unless+ expression is the same as: + + if not true + puts "the value is a false-value" + end + +Like an +if+ expression you may use an +else+ condition with +unless+: + + unless true + puts "the value is false" + else + puts "the value is true" + end + +This prints "the value is true" from the +else+ condition. + +You may not use +elsif+ with an +unless+ expression. + +The result value of an +unless+ expression is the last value executed in the +expression. + +== Modifier +if+ and +unless+ + ++if+ and +unless+ can also be used to modify an expression. When used as a +modifier the left-hand side is the "then" expression and the right-hand side +is the "test" expression: + + a = 0 + + a += 1 if a.zero? + + p a + +This will print 1. + + a = 0 + + a += 1 unless a.zero? + + p a + +This will print 0. + +While the modifier and standard versions have both a "test" expression and a +"then" expression, they are not exact transformations of each other due to +parse order. Here is an example that shows the difference: + + p a if a = 0.zero? + +This raises the NameError "undefined local variable or method `a'". + +When ruby parses this expression it first encounters +a+ as a method call in +the "then" expression, then later it sees the assignment to +a+ in the "test" +expression and marks +a+ as a local variable. + +When running this line it first executes the "test" expression, <code>a = +0.zero?</code>. + +Since the test is true it executes the "then" expression, <code>p a</code>. +Since the +a+ in the body was recorded as a method which does not exist the +NameError is raised. + +The same is true for +unless+. + +== +case+ Expression + +The +case+ expression can be used in two ways. + +The most common way is to compare an object against multiple patterns. The +patterns are matched using the +===+ method which is aliased to +==+ on +Object. Other classes must override it to give meaningful behavior. See +Module#=== and Regexp#=== for examples. + +Here is an example of using +case+ to compare a String against a pattern: + + case "12345" + when /^1/ + puts "the string starts with one" + else + puts "I don't know what the string starts with" + end + +Here the string <code>"12345"</code> is compared with <code>/^1/</code> by +calling <code>/^1/ === "12345"</code> which returns +true+. Like the +if+ +expression the first +when+ that matches is executed and all other matches are +ignored. + +If no matches are found the +else+ is executed. + +The +else+ and +then+ are optional, this +case+ expression gives the same +result as the one above: + + case "12345" + when /^1/ + puts "the string starts with one" + end + +You may place multiple conditions on the same +when+: + + case "2" + when /^1/, "2" + puts "the string starts with one or is '2'" + end + +Ruby will try each condition in turn, so first <code>/^1/ === "2"</code> +returns +false+, then <code>"2" === "2"</code> returns +true+, so "the string +starts with one or is '2'" is printed. + +You may use +then+ after the +when+ condition. This is most frequently used +to place the body of the +when+ on a single line. + + case a + when 1, 2 then puts "a is one or two + when 3 then puts "a is three" + else puts "I don't know what a is" + end + +The other way to use a +case+ expression is like an if-elsif expression: + + a = 2 + + case + when a == 1, a == 2 + puts "a is one or two" + when a == 3 + puts "a is three" + else + puts "I don't know what a is" + end + +Again, the +then+ and +else+ are optional. + +The result value of a +case+ expression is the last value executed in the +expression. + +== +while+ Loop + +The +while+ loop executes while a condition is true: + + a = 0 + + while a < 10 do + p a + a += 1 + end + + p a + +Prints the numbers 0 through 10. The condition <code>a < 10</code> is checked +before the loop is entered, then the body executes, then the condition is +checked again. When the condition results in false the loop is terminated. + +The +do+ keyword is optional. The following loop is equivalent to the loop +above: + + while a < 10 + p a + a += 1 + end + +The result of a +while+ loop is +nil+ unless +break+ is used to supply a +value. + +== +until+ Loop + +The +until+ loop executes while a condition is false: + + a = 0 + + until a > 10 do + p a + a += 1 + end + + p a + +This prints the numbers 0 through 11. Like a while loop the condition <code>a +> 10</code> is checked when entering the loop and each time the loop body +executes. If the condition is false the loop will continue to execute. + +Like a +while+ loop the +do+ is optional. + +Like a +while+ loop the result of an +until+ loop is nil unless +break+ is +used. + +== +for+ Loop + +The +for+ loop consists of +for+ followed by a variable to contain the +iteration argument followed by +in+ and the value to iterate over using #each. +The +do+ is optional: + + for value in [1, 2, 3] do + puts value + end + +Prints 1, 2 and 3. + +Like +while+ and +until+, the +do+ is optional. + +The +for+ loop is similar to using #each, but does not create a new variable +scope. + +The result value of a +for+ loop is the value iterated over unless +break+ is +used. + +The +for+ loop is rarely used in modern ruby programs. + +== Modifier +while+ and +until+ + +Like +if+ and +unless+, +while+ and +until+ can be used as modifiers: + + a = 0 + + a += 1 while a < 10 + + p a # prints 10 + ++until+ used as a modifier: + + a = 0 + + a += 1 until a > 10 + + p a # prints 11 + +You can use +begin+ and +end+ to create a +while+ loop that runs the body once +before the condition: + + a = 0 + + begin + a += 1 + end while a < 10 + + p a # prints 10 + +If you don't use +rescue+ or +ensure+ Ruby optimizes away any exception +handling overhead. + +== +break+ Statement + +Use +break+ to leave a block early. This will stop iterating over the items in +values+ if one of them is even: + + values.each do |value| + break if value.even? + + # ... + end + +You can also terminate from a +while+ loop using +break+: + + a = 0 + + while true do + p a + a += 1 + + break if a < 10 + end + + p a + +This prints the numbers 0 and 1. + ++break+ accepts a value that supplies the result of the expression it is +"breaking" out of: + + result = [1, 2, 3].each do |value| + break value * 2 if value.even? + end + + p result # prints 4 + +== +next+ Statement + +Use +next+ to skip the rest of the current iteration: + + result = [1, 2, 3].map do |value| + next if value.even? + + value * 2 + end + + p result # prints [2, nil, 6] + ++next+ accepts an argument that can be used the result of the current block +iteration: + + result = [1, 2, 3].map do |value| + next value if value.even? + + value * 2 + end + + p result # prints [2, 2, 6] + +== +redo+ Statement + +Use +redo+ to redo the current iteration: + + result = [] + + while result.length < 10 do + result << result.length + + redo if result.last.even? + + result << result.length + 1 + end + + p result + +This prints [0, 1, 3, 3, 5, 5, 7, 7, 9, 9, 11] + +In Ruby 1.8 you could also use +retry+ where you used +redo+. This is no +longer true, now you will receive a SyntaxError when you use +retry+ outside +of a +rescue+ block. See {Exceptions}[rdoc-ref:syntax/exceptions.rdoc] +for proper usage of +retry+. + +== Flip-Flop + +The flip-flop is rarely seen conditional expression. It's primary use is +for processing text from ruby one-line programs used with <code>ruby -n</code> +or <code>ruby -p</code>. + +The form of the flip-flop is an expression that indicates when the +flip-flop turns on, <code>..</code> (or <code>...</code>), then an expression +that indicates when the flip-flop will turn off. While the flip-flop is on it +will continue to evaluate to +true+, and +false+ when off. + +Here is an example: + + + selected = [] + + 0.upto 10 do |value| + selected << value if value==2..value==8 + end + + p selected # prints [2, 3, 4, 5, 6, 7, 8] + +In the above example the on condition is <code>n==2</code>. The flip-flop +is initially off (false) for 0 and 1, but becomes on (true) for 2 and remains +on through 8. After 8 it turns off and remains off for 9 and 10. + +The flip-flop must be used inside a conditional such as +if+, +while+, ++unless+, +until+ etc. including the modifier forms. + +When you use an inclusive range (<code>..</code>) the off condition is +evaluated when the on condition changes: + + selected = [] + + 0.upto 5 do |value| + selected << value if value==2..value==2 + end + + p selected # prints [2] + +Here both sides of the flip-flop are evaluated so the flip-flop turns on and +off only when +value+ equals 2. Since the flip-flop turned on in the +iteration it returns true. + +When you use an exclusive range (<code>...</code>) the off condition is +evaluated on the following iteration: + + selected = [] + + 0.upto 5 do |value| + selected << value if value==2...value==2 + end + + p selected # prints [2, 3, 4, 5] + +Here the flip-flop turns on when +value+ equals 2 but doesn't turn off on the +same iteration. The off condition isn't evaluated until the following +iteration and +value+ will never be two again. + diff --git a/ruby_2_2/doc/syntax/exceptions.rdoc b/ruby_2_2/doc/syntax/exceptions.rdoc new file mode 100644 index 0000000000..0efc35a59f --- /dev/null +++ b/ruby_2_2/doc/syntax/exceptions.rdoc @@ -0,0 +1,96 @@ += Exception Handling + +Exceptions are rescued in a +begin+/+end+ block: + + begin + # code that might raise + rescue + # handle exception + end + +If you are inside a method you do not need to use +begin+ or +end+ unless you +wish to limit the scope of rescued exceptions: + + def my_method + # ... + rescue + # ... + end + +The same is true for a +class+ or +module+. + +You can assign the exception to a local variable by using <tt>=> +variable_name</tt> at the end of the +rescue+ line: + + begin + # ... + rescue => exception + warn exception.message + raise # re-raise the current exception + end + +By default StandardError and its subclasses are rescued. You can rescue a +specific set of exception classes (and their subclasses) by listing them after ++rescue+: + + begin + # ... + rescue ArgumentError, NameError + # handle ArgumentError or NameError + end + +You may rescue different types of exceptions in different ways: + + begin + # ... + rescue ArgumentError + # handle ArgumentError + rescue NameError + # handle NameError + rescue + # handle any StandardError + end + +The exception is matched to the rescue section starting at the top, and matches +only once. If an ArgumentError is raised in the begin section it will not be +handled in the StandardError section. + +You may retry rescued exceptions: + + begin + # ... + rescue + # do something that may change the result of the begin block + retry + end + +Execution will resume at the start of the begin block, so be careful not to +create an infinite loop. + +Inside a rescue block is the only valid location for +retry+, all other uses +will raise a SyntaxError. If you wish to retry a block iteration use +redo+. +See {Control Expressions}[rdoc-ref:syntax/control_expressions.rdoc] for +details. + +To always run some code whether an exception was raised or not, use +ensure+: + + begin + # ... + rescue + # ... + ensure + # this always runs + end + +You may also run some code when an exception is not raised: + + begin + # ... + rescue + # ... + else + # this runs only when no exception was raised + ensure + # ... + end + diff --git a/ruby_2_2/doc/syntax/literals.rdoc b/ruby_2_2/doc/syntax/literals.rdoc new file mode 100644 index 0000000000..aadd574a97 --- /dev/null +++ b/ruby_2_2/doc/syntax/literals.rdoc @@ -0,0 +1,347 @@ += Literals + +Literals create objects you can use in your program. Literals include: + +* Booleans and nil +* Numbers +* Strings +* Symbols +* Arrays +* Hashes +* Ranges +* Regular Expressions +* Procs + +== Booleans and nil + ++nil+ and +false+ are both false values. +nil+ is sometimes used to indicate +"no value" or "unknown" but evaluates to +false+ in conditional expressions. + ++true+ is a true value. All objects except +nil+ and +false+ evaluate to a +true value in conditional expressions. + +(There are also the constants +TRUE+, +FALSE+ and +NIL+, but the lowercase +literal forms are preferred.) + +== Numbers + +You can write integers of any size as follows: + + 1234 + 1_234 + +These numbers have the same value, 1,234. The underscore may be used to +enhance readability for humans. You may place an underscore anywhere in the +number. + +Floating point numbers may be written as follows: + + 12.34 + 1234e-2 + 1.234E1 + +These numbers have the same value, 12.34. You may use underscores in floating +point numbers as well. + +You can use a special prefix to write numbers in decimal, hexadecimal, octal +or binary formats. For decimal numbers use a prefix of <tt>0d</tt>, for +hexadecimal numbers use a prefix of <tt>0x</tt>, for octal numbers use a +prefix of <tt>0</tt> or <tt>0o</tt>, for binary numbers use a prefix of +<tt>0b</tt>. The alphabetic component of the number is not case-sensitive. + +Examples: + + 0d170 + 0D170 + + 0xaa + 0xAa + 0xAA + 0Xaa + 0XAa + 0XaA + + 0252 + 0o252 + 0O252 + + 0b10101010 + 0B10101010 + +All these numbers have the same decimal value, 170. Like integers and floats +you may use an underscore for readability. + +== Strings + +The most common way of writing strings is using <tt>"</tt>: + + "This is a string." + +The string may be many lines long. + +Any internal <tt>"</tt> must be escaped: + + "This string has a quote: \". As you can see, it is escaped" + +Double-quote strings allow escaped characters such as <tt>\n</tt> for +newline, <tt>\t</tt> for tab, etc. The full list of supported escape +sequences are as follows: + + \a bell, ASCII 07h (BEL) + \b backspace, ASCII 08h (BS) + \t horizontal tab, ASCII 09h (TAB) + \n newline (line feed), ASCII 0Ah (LF) + \v vertical tab, ASCII 0Bh (VT) + \f form feed, ASCII 0Ch (FF) + \r carriage return, ASCII 0Dh (CR) + \e escape, ASCII 1Bh (ESC) + \s space, ASCII 20h (SPC) + \\ backslash, \ + \nnn octal bit pattern, where nnn is 1-3 octal digits ([0-7]) + \xnn hexadecimal bit pattern, where nn is 1-2 hexadecimal digits ([0-9a-fA-F]) + \unnnn Unicode character, where nnnn is exactly 4 hexadecimal digits ([0-9a-fA-F]) + \u{nnnn ...} Unicode character(s), where each nnnn is 1-6 hexadecimal digits ([0-9a-fA-F]) + \cx or \C-x control character, where x is an ASCII printable character + \M-x meta character, where x is an ASCII printable character + \M-\C-x meta control character, where x is an ASCII printable character + \M-\cx same as above + \c\M-x same as above + \c? or \C-? delete, ASCII 7Fh (DEL) + +Any other character following a backslash is interpreted as the +character itself. + +Double-quote strings allow interpolation of other values using +<tt>#{...}</tt>: + + "One plus one is two: #{1 + 1}" + +Any expression may be placed inside the interpolated section, but it's best to +keep the expression small for readability. + +Interpolation may be disabled by escaping the "#" character or using +single-quote strings: + + '#{1 + 1}' #=> "\#{1 + 1}" + +In addition to disabling interpolation, single-quoted strings also disable all +escape sequences except for the single-quote (<tt>\'</tt>) and backslash +(<tt>\\\\</tt>). + +You may also create strings using <tt>%</tt>: + + %(1 + 1 is #{1 + 1}) #=> "1 + 1 is 2" + +There are two different types of <tt>%</tt> strings <tt>%q(...)</tt> behaves +like a single-quote string (no interpolation or character escaping) while +<tt>%Q</tt> behaves as a double-quote string. See Percent Strings below for +more discussion of the syntax of percent strings. + +Adjacent string literals are automatically concatenated by the interpreter: + + "con" "cat" "en" "at" "ion" #=> "concatenation" + "This string contains "\ + "no newlines." #=> "This string contains no newlines." + +Any combination of adjacent single-quote, double-quote, percent strings will +be concatenated as long as a percent-string is not last. + + %q{a} 'b' "c" #=> "abc" + "a" 'b' %q{c} #=> NameError: uninitialized constant q + +One more way of writing strings is using <tt>?</tt>: + + ?a #=> "a" + +Basically only one character can be placed after <tt>?</tt>: + + ?abc #=> SyntaxError + +Exceptionally, <tt>\C-</tt>, <tt>\M-</tt> and their combination are allowed +before a character. They mean "control", "meta" and "control-meta" +respectively: + + ?\C-a #=> "\x01" + ?\M-a #=> "\xE1" + ?\M-\C-a #=> "\x81" + ?\C-\M-a #=> "\x81", same as above + +=== Here Documents + +If you are writing a large block of text you may use a "here document" or +"heredoc": + + expected_result = <<HEREDOC + This would contain specially formatted text. + + That might span many lines + HEREDOC + +The heredoc starts on the line following <tt><<HEREDOC</tt> and ends with the +next line that starts with <tt>HEREDOC</tt>. The result includes the ending +newline. + +You may use any identifier with a heredoc, but all-uppercase identifiers are +typically used. + +You may indent the ending identifier if you place a "-" after <tt><<</tt>: + + expected_result = <<-INDENTED_HEREDOC + This would contain specially formatted text. + + That might span many lines + INDENTED_HEREDOC + +Note that the while the closing identifier may be indented, the content is +always treated as if it is flush left. If you indent the content those spaces +will appear in the output. + +A heredoc allows interpolation and escaped characters. You may disable +interpolation and escaping by surrounding the opening identifier with single +quotes: + + expected_result = <<-'EXPECTED' + One plus one is #{1 + 1} + EXPECTED + + p expected_result # prints: "One plus one is \#{1 + 1}\n" + +The identifier may also be surrounded with double quotes (which is the same as +no quotes) or with backticks. When surrounded by backticks the HEREDOC +behaves like Kernel#`: + + puts <<-`HEREDOC` + cat #{__FILE__} + HEREDOC + +To call a method on a heredoc place it after the opening identifier: + + expected_result = <<-EXPECTED.chomp + One plus one is #{1 + 1} + EXPECTED + +You may open multiple heredocs on the same line, but this can be difficult to +read: + + puts(<<-ONE, <<-TWO) + content for heredoc one + ONE + content for heredoc two + TWO + +== Symbols + +A Symbol represents a name inside the ruby interpreter. See Symbol for more +details on what symbols are and when ruby creates them internally. + +You may reference a symbol using a colon: <tt>:my_symbol</tt>. + +You may also create symbols by interpolation: + + :"my_symbol1" + :"my_symbol#{1 + 1}" + +Like strings, a single-quote may be used to disable interpolation: + + :'my_symbol#{1 + 1}' #=> :"my_symbol\#{1 + 1}" + +When creating a Hash there is a special syntax for referencing a Symbol as +well. + +== Arrays + +An array is created using the objects between <tt>[</tt> and <tt>]</tt>: + + [1, 2, 3] + +You may place expressions inside the array: + + [1, 1 + 1, 1 + 2] + [1, [1 + 1, [1 + 2]]] + +See Array for the methods you may use with an array. + +== Hashes + +A hash is created using key-value pairs between <tt>{</tt> and <tt>}</tt>: + + { "a" => 1, "b" => 2 } + +Both the key and value may be any object. + +You can create a hash using symbol keys with the following syntax: + + { a: 1, b: 2 } + +This same syntax is used for keyword arguments for a method. + +See Hash for the methods you may use with a hash. + +== Ranges + +A range represents an interval of values. The range may include or exclude +its ending value. + + (1..2) # includes its ending value + (1...2) # excludes its ending value + +You may create a range of any object. See the Range documentation for details +on the methods you need to implement. + +== Regular Expressions + +A regular expression is created using "/": + + /my regular expression/ + +The regular expression may be followed by flags which adjust the matching +behavior of the regular expression. The "i" flag makes the regular expression +case-insensitive: + + /my regular expression/i + +Interpolation may be used inside regular expressions along with escaped +characters. Note that a regular expression may require additional escaped +characters than a string. + +See Regexp for a description of the syntax of regular expressions. + +== Procs + +A proc can be created with <tt>-></tt>: + + -> { 1 + 1 } + +Calling the above proc will give a result of <tt>2</tt>. + +You can require arguments for the proc as follows: + + ->(v) { 1 + v } + +This proc will add one to its argument. + +== Percent Strings + +Besides <tt>%(...)</tt> which creates a String, The <tt>%</tt> may create +other types of object. As with strings, an uppercase letter allows +interpolation and escaped characters while a lowercase letter disables them. + +These are the types of percent strings in ruby: + +<tt>%i</tt> :: Array of Symbols +<tt>%q</tt> :: String +<tt>%r</tt> :: Regular Expression +<tt>%s</tt> :: Symbol +<tt>%w</tt> :: Array of Strings +<tt>%x</tt> :: Backtick (capture subshell result) + +For the two array forms of percent string, if you wish to include a space in +one of the array entries you must escape it with a "\\" character: + + %w[one one-hundred\ one] + #=> ["one", "one-hundred one"] + +If you are using "(", "[", "{", "<" you must close it with ")", "]", "}", ">" +respectively. You may use most other non-alphanumeric characters for percent +string delimiters such as "%", "|", "^", etc. + diff --git a/ruby_2_2/doc/syntax/methods.rdoc b/ruby_2_2/doc/syntax/methods.rdoc new file mode 100644 index 0000000000..2c01810b4c --- /dev/null +++ b/ruby_2_2/doc/syntax/methods.rdoc @@ -0,0 +1,456 @@ += Methods + +Methods implement the functionality of your program. Here is a simple method +definition: + + def one_plus_one + 1 + 1 + end + +A method definition consists of the +def+ keyword, a method name, the body of +the method, +return+ value and the +end+ keyword. When called the method will +execute the body of the method. This method returns +2+. + +This section only covers defining methods. See also the {syntax documentation +on calling methods}[rdoc-ref:syntax/calling_methods.rdoc]. + +== Method Names + +Method names may be one of the operators or must start a letter or a character +with the eight bit set. It may contain letters, numbers, an <code>_</code> +(underscore or low line) or a character with the eight bit set. The convention +is to use underscores to separate words in a multiword method name: + + def method_name + puts "use underscores to separate words" + end + +Ruby programs must be written in a US-ASCII-compatible character set such as +UTF-8, ISO-8859-1 etc. In such character sets if the eight bit is set it +indicates an extended character. Ruby allows method names and other identifiers +to contain such characters. Ruby programs cannot contain some characters like +ASCII NUL (<code>\x00<code>). + +The following are the examples of valid ruby methods: + + def hello + "hello" + end + + def こんにちは + puts "means hello in Japanese" + end + +Typically method names are US-ASCII compatible since the keys to type them +exist on all keyboards. + +Method names may end with a <code>!</code> (bang or exclamation mark), a +<code>?</code> (question mark) or <code>=</code> equals sign. + +The bang methods(<code>!</code> at the end of method name) are called and +executed just like any other method. However, by convention, a method with an +exclamation point or bang is considered dangerous. In ruby core library the +dangerous method implies that when a method ends with a bang(<code>!</code>), +it indicates that unlike its non-bang equivalent, permanently modifies its +receiver. Almost always, Ruby core library will have a non-bang +counterpart(method name which does NOT end with <code>!</code>) of every bang +method (method name which does end with <code>!</code>) that has does not +modify the receiver. This convention is typically true for ruby core libary but +may/may not hold true for other ruby libraries. + +Methods that end with a question mark by convention return boolean. But they +may not always return just +true+ or +false+. Often they will may return an +object to indicate a true value (or "truthy" value). + +Methods that end with an equals sign indicate an assignment method. For +assignment methods the return value is ignored, the arguments are returned +instead. + +These are method names for the various ruby operators. Each of these +operators accept only one argument. Following the operator is the typical +use or name of the operator. Creating an alternate meaning for the operator +may lead to confusion as the user expects plus to add things, minus to +subtract things, etc. Additionally, you cannot alter the precedence of the +operators. + +<code>+</code> :: add +<code>-</code> :: subtract +<code>*</code> :: multiply +<code>**</code> :: power +<code>/</code> :: divide +<code>%</code> :: modulus division, String#% +<code>&</code> :: AND +<code>^</code> :: XOR (exclusive OR) +<code>>></code> :: right-shift +<code><<</code> :: left-shift, append +<code>==</code> :: equal +<code>!=</code> :: not equal +<code>===</code> :: case equality. See Object#=== +<code>=~</code> :: pattern match. (Not just for regular expressions) +<code>!~</code> :: does not match +<code><=></code> :: comparison aka spaceship operator. See Comparable +<code><</code> :: less-than +<code><=</code> :: less-than or equal +<code>></code> :: greater-than +<code>>=</code> :: greater-than or equal + +To define unary methods minus, plus, tilde and not (<code>!</code>) follow the +operator with an <code>@</code> as in <code>+@</code> or <code>!@</code>: + + class C + def -@ + puts "you inverted this object" + end + end + + obj = C.new + + -obj # prints "you inverted this object" + +Unary methods accept zero arguments. + +Additionally, methods for element reference and assignment may be defined: +<code>[]</code> and <code>[]=</code> respectively. Both can take one or more +arguments, and element reference can take none. + + class C + def [](a, b) + puts a + b + end + + def []=(a, b, c) + puts a * b + c + end + end + + obj = C.new + + obj[2, 3] # prints "5" + obj[2, 3] = 4 # prints "10" + +== Return Values + +By default, a method returns the last expression that was evaluated in the body +of the method. In the example above, the last (and only) expression evaluated +was the simple sum <code>1 + 1</code>. The +return+ keyword can be used to +make it explicit that a method returns a value. + + def one_plus_one + return 1 + 1 + end + +It can also be used to make a method return before the last expression is +evaluated. + + def two_plus_two + return 2 + 2 + 1 + 1 # this expression is never evaluated + end + +Note that for assignment methods the return value will always be ignored. +Instead the argument will be returned: + + def a=(value) + return 1 + value + end + + p(a = 5) # prints 5 + +== Scope + +The standard syntax to define a method: + + def my_method + # ... + end + +adds the method to a class. You can define an instance method on a specific +class with the +class+ keyword: + + class C + def my_method + # ... + end + end + +A method may be defined on another object. You may define a "class method" (a +method that is defined on the class, not an instance of the class) like this: + + class C + def self.my_method + # ... + end + end + +However, this is simply a special case of a greater syntactical power in Ruby, +the ability to add methods to any object. Classes are objects, so adding +class methods is simply adding methods to the Class object. + +The syntax for adding a method to an object is as follows: + + greeting = "Hello" + + def greeting.broaden + self + ", world!" + end + + greeting.broaden # returns "Hello, world!" + ++self+ is a keyword referring to the current object under consideration +by the compiler, which might make the use of +self+ in defining a class +method above a little clearer. Indeed, the example of adding a +hello+ +method to the class +String+ can be rewritten thus: + + def String.hello + "Hello, world!" + end + +A method defined like this is called a "singleton method". +broaden+ will only +exist on the string instance +greeting+. Other strings will not have +broaden+. + +== Overriding + +When Ruby encounters the +def+ keyword, it doesn't consider it an error if the +method already exists: it simply redefines it. This is called +_overriding_. Rather like extending core classes, this is a potentially +dangerous ability, and should be used sparingly because it can cause unexpected +results. For example, consider this irb session: + + >> "43".to_i + => 43 + >> class String + >> def to_i + >> 42 + >> end + >> end + => nil + >> "43".to_i + => 42 + +This will effectively sabotage any code which makes use of the method +<code>String#to_i</code> to parse numbers from strings. + +== Arguments + +A method may accept arguments. The argument list follows the method name: + + def add_one(value) + value + 1 + end + +When called, the user of the +add_one+ method must provide an argument. The +argument is a local variable in the method body. The method will then add one +to this argument and return the value. If given +1+ this method will +return +2+. + +The parentheses around the arguments are optional: + + def add_one value + value + 1 + end + +Multiple arguments are separated by a comma: + + def add_values(a, b) + a + b + end + +When called, the arguments must be provided in the exact order. In other +words, the arguments are positional. + +=== Default Values + +Arguments may have default values: + + def add_values(a, b = 1) + a + b + end + +The default value does not need to appear first, but arguments with defaults +must be grouped together. This is ok: + + def add_values(a = 1, b = 2, c) + a + b + c + end + +This will raise a SyntaxError: + + def add_values(a = 1, b, c = 1) + a + b + c + end + +=== Array Decomposition + +You can decompose (unpack or extract values from) an Array using extra +parentheses in the arguments: + + def my_method((a, b)) + p a: a, b: b + end + + my_method([1, 2]) + +This prints: + + {:a=>1, :b=>2} + +If the argument has extra elements in the Array they will be ignored: + + def my_method((a, b)) + p a: a, b: b + end + + my_method([1, 2, 3]) + +This has the same output as above. + +You can use a <code>*</code> to collect the remaining arguments. This splits +an Array into a first element and the rest: + + def my_method((a, *b)) + p a: a, b: b + end + + my_method([1, 2, 3]) + +This prints: + + {:a=>1, :b=>[2, 3]} + +The argument will be decomposed if it responds to #to_ary. You should only +define #to_ary if you can use your object in place of an Array. + +Use of the inner parentheses only uses one of the sent arguments. If the +argument is not an Array it will be assigned to the first argument in the +decomposition and the remaining arguments in the decomposition will be +nil+: + + def my_method(a, (b, c), d) + p a: a, b: b, c: c, d: d + end + + my_method(1, 2, 3) + +This prints: + + {:a=>1, :b=>2, :c=>nil, :d=>3} + +You can nest decomposition arbitrarily: + + def my_method(((a, b), c)) + # ... + end + +=== Array/Hash Argument + +Prefixing an argument with <code>*</code> causes any remaining arguments to be +converted to an Array: + + def gather_arguments(*arguments) + p arguments + end + + gather_arguments 1, 2, 3 # prints [1, 2, 3] + +The array argument must be the last positional argument, it must appear before +any keyword arguments. + +The array argument will capture a Hash as the last entry if a hash was sent by +the caller after all positional arguments. + + gather_arguments 1, a: 2 # prints [1, {:a=>2}] + +However, this only occurs if the method does not declare any keyword arguments. + + def gather_arguments_keyword(*positional, keyword: nil) + p positional: positional, keyword: keyword + end + + gather_arguments_keyword 1, 2, three: 3 + #=> raises: unknown keyword: three (ArgumentError) + +Also, note that a bare <code>*</code> can be used to ignore arguments: + + def ignore_arguments(*) + end + +=== Keyword Arguments + +Keyword arguments are similar to positional arguments with default values: + + def add_values(first: 1, second: 2) + first + second + end + +Arbitrary keyword arguments will be accepted with <code>**</code>: + + def gather_arguments(first: nil, **rest) + p first, rest + end + + gather_arguments first: 1, second: 2, third: 3 + # prints 1 then {:second=>2, :third=>3} + +When calling a method with keyword arguments the arguments may appear in any +order. If an unknown keyword argument is sent by the caller an ArgumentError +is raised. + +When mixing keyword arguments and positional arguments, all positional +arguments must appear before any keyword arguments. + +== Block Argument + +The block argument is indicated by <code>&</code> and must come last: + + def my_method(&my_block) + my_block.call(self) + end + +Most frequently the block argument is used to pass a block to another method: + + def each_item(&block) + @items.each(&block) + end + +If you are only going to call the block and will not otherwise manipulate it +or send it to another method using <code>yield</code> without an explicit +block parameter is preferred. This method is equivalent to the first method +in this section: + + def my_method + yield self + end + +There is also a performance benefit to using yield over a calling a block +parameter. When a block argument is assigned to a variable a Proc object is +created which holds the block. When using yield this Proc object is not +created. + +If you only need to use the block sometimes you can use Proc.new to create a +proc from the block that was passed to your method. See Proc.new for further +details. + +== Exception Handling + +Methods have an implied exception handling block so you do not need to use ++begin+ or +end+ to handle exceptions. This: + + def my_method + begin + # code that may raise an exception + rescue + # handle exception + end + end + +May be written as: + + def my_method + # code that may raise an exception + rescue + # handle exception + end + +If you wish to rescue an exception for only part of your method use +begin+ and ++end+. For more details see the page on {exception +handling}[rdoc-ref:syntax/exceptions.rdoc]. + diff --git a/ruby_2_2/doc/syntax/miscellaneous.rdoc b/ruby_2_2/doc/syntax/miscellaneous.rdoc new file mode 100644 index 0000000000..8f424f019f --- /dev/null +++ b/ruby_2_2/doc/syntax/miscellaneous.rdoc @@ -0,0 +1,107 @@ += Miscellaneous Syntax + +== Ending an Expression + +Ruby uses a newline as the end of an expression. When ending a line with an +operator, open parentheses, comma, etc. the expression will continue. + +You can end an expression with a <code>;</code> (semicolon). Semicolons are +most frequently used with <code>ruby -e</code>. + +== Indentation + +Ruby does not require any indentation. Typically ruby programs are indented +two spaces. + +If you run ruby with warnings enabled and have an indentation mis-match you +will receive a warning. + +== +alias+ + +The +alias+ keyword is most frequently used to alias methods. When aliasing a +method you can use either its name or a symbol: + + alias new_name old_name + alias :new_name :old_name + +For methods, Module#alias_method can often be used instead of +alias+. + +You can also use +alias+ to alias global variables: + + $old = 0 + + alias $new $old + + p $new # prints 0 + +You may use +alias+ in any scope. + +== +undef+ + +The +undef+ keyword prevents the current class from responding to calls to the +named methods. + + undef my_method + +You may use symbols instead of method names: + + undef :my_method + +You may undef multiple methods: + + undef method1, method2 + +You may use +undef+ in any scope. See also Module#undef_method + +== +defined?+ + ++defined?+ is a keyword that returns a string describing its argument: + + p defined?(UNDEFINED_CONSTANT) # prints nil + p defined?(RUBY_VERSION) # prints "constant" + p defined?(1 + 1) # prints "method" + +You don't need to use parenthesis with +defined?+ but they are recommended due +to the {low precedence}[rdoc-ref:syntax/precedence.rdoc] of +defined?+. + +For example, if you wish to check if an instance variable exists and that the +instance variable is zero: + + defined? @instance_variable && @instance_variable.zero? + +This returns <code>"expression"</code> which is not what you want if the +instance variable is not defined. + + @instance_variable = 1 + defined?(@instance_variable) && @instance_variable.zero? + +Adding parentheses when checking if the instance variable is defined is a +better check. This correctly returns +nil+ when the instance variable is not +defined and +false+ when the instance variable is not zero. + +Using the specific reflection methods such as instance_variable_defined? for +instance variables or const_defined? for constants is less error prone than +using +defined?+. + +== +BEGIN+ and +END+ + ++BEGIN+ defines a block that is run before any other code in the current file. +It is typically used in one-liners with <code>ruby -e</code>. Similarly +END+ +defines a block that is run after any other code. + ++BEGIN+ must appear at top-level and +END+ will issue a warning when you use it +inside a method. + +Here is an example: + + BEGIN { + count = 0 + } + +You must use <code>{</code> and <code>}</code> you may not use +do+ and +end+. + +Here is an example one-liner that adds numbers from standard input or any files +in the argument list: + + ruby -ne 'BEGIN { count = 0 }; END { puts count }; count += gets.to_i' + diff --git a/ruby_2_2/doc/syntax/modules_and_classes.rdoc b/ruby_2_2/doc/syntax/modules_and_classes.rdoc new file mode 100644 index 0000000000..a82a6f27ed --- /dev/null +++ b/ruby_2_2/doc/syntax/modules_and_classes.rdoc @@ -0,0 +1,345 @@ += Modules + +Modules serve two purposes in Ruby, namespacing and mix-in functionality. + +A namespace can be used to organize code by package or functionality that +separates common names from interference by other packages. For example, the +IRB namespace provides functionality for irb that prevents a collision +for the common name "Context". + +Mix-in functionality allows sharing common methods across multiple classes or +modules. Ruby comes with the Enumerable mix-in module which provides many +enumeration methods based on the +each+ method and Comparable allows comparison +of objects based on the <code><=></code> comparison method. + +Note that there are many similarities between modules and classes. Besides the +ability to mix-in a module, the description of modules below also applies to +classes. + +== Module Definition + +A module is created using the +module+ keyword: + + module MyModule + # ... + end + +A module may be reopened any number of times to add, change or remove +functionality: + + module MyModule + def my_method + end + end + + module MyModule + alias my_alias my_method + end + + module MyModule + remove_method :my_method + end + +Reopening classes is a very powerful feature of Ruby, but it is best to only +reopen classes you own. Reopening classes you do not own may lead to naming +conflicts or difficult to diagnose bugs. + +== Nesting + +Modules may be nested: + + module Outer + module Inner + end + end + +Many packages create a single outermost module (or class) to provide a +namespace for their functionality. + +You may also define inner modules using <code>::</code> provided the outer +modules (or classes) are already defined: + + module Outer::Inner::GrandChild + end + +Note that this will raise a +NameError+ if +Outer+ and +<code>Outer::Inner</code> are not already defined. + +This style has the benefit of allowing the author to reduce the amount +of indentation. Instead of 3 levels of indentation only one is necessary. +However, the scope of constant lookup is different for creating a namespace +using this syntax instead of the more verbose syntax. + +== Scope + +=== +self+ + ++self+ refers to the object that defines the current scope. +self+ will change +when entering a different method or when defining a new module. + +=== Constants + +Accessible constants are different depending on the module nesting (which +syntax was used to define the module). In the following example +the constant <code>A::Z</code> is accessible from B as A is part of the +nesting: + + module A + Z = 1 + + module B + p Module.nesting #=> [A::B, A] + p Z #=> 1 + end + end + +However, if you use <code>::</code> to define <code>A::B</code> without +nesting it inside +A+ a NameError exception will be raised because the nesting +does not include +A+: + + module A + Z = 1 + end + + module A::B + p Module.nesting #=> [A::B] + p Z #=> raises NameError + end + +If a constant is defined at the top-level you may preceded it with +<code>::</code> to reference it: + + Z = 0 + + module A + Z = 1 + + module B + p ::Z #=> 0 + end + end + +=== Methods + +For method definition documentation see the {syntax documentation for +methods}[rdoc-ref:syntax/methods.rdoc]. + +Class methods may be called directly. (This is slightly confusing, but a +method on a module is often called a "class method" instead of a "module +method". See also Module#module_function which can convert an instance method +into a class method.) + +When a class method references a constant it uses the same rules as referencing +it outside the method as the scope is the same. + +Instance methods defined in a module are only callable when included. These +methods have access to the constants defined when they were included through +the ancestors list: + + module A + Z = 1 + + def z + Z + end + end + + include A + + p self.class.ancestors #=> [Object, A, Kernel, BasicObject] + p z #=> 1 + +=== Visibility + +Ruby has three types of visibility. The default is +public+. A public method +may be called from any other object. + +The second visibility is +protected+. When calling a protected method the +sender must be a subclass of the receiver or the receiver must be a subclass of +the sender. Otherwise a NoMethodError will be raised. + +Protected visibility is most frequently used to define <code>==</code> and +other comparison methods where the author does not wish to expose an object's +state to any caller and would like to restrict it only to inherited classes. + +Here is an example: + + class A + def n(other) + other.m + end + end + + class B < A + def m + 1 + end + + protected :m + + end + + class C < B + end + + a = A.new + b = B.new + c = C.new + + c.n b #=> 1 -- C is a subclass of B + b.n b #=> 1 -- m called on defining class + a.n b # raises NoMethodError A is not a subclass of B + +The third visibility is +private+. A private method may not be called with a +receiver, not even +self+. If a private method is called with a receiver a +NoMethodError will be raised. + +=== +alias+ and +undef+ + +You may also alias or undefine methods, but these operations are not +restricted to modules or classes. See the {miscellaneous syntax +section}[rdoc-ref:syntax/miscellaneous.rdoc] for documentation. + += Classes + +Every class is also a module, but unlike modules a class may not be mixed-in to +another module (or class). Like a module, a class can be used as a namespace. +A class also inherits methods and constants from its superclass. + +== Defining a class + +Use the +class+ keyword to create a class: + + class MyClass + # ... + end + +If you do not supply a superclass your new class will inherit from Object. You +may inherit from a different class using <code><</code> followed by a class +name: + + class MySubclass < MyClass + # ... + end + +There is a special class BasicObject which is designed as a blank class and +includes a minimum of built-in methods. You can use BasicObject to create an +independent inheritance structure. See the BasicObject documentation for +further details. + +== Inheritance + +Any method defined on a class is callable from its subclass: + + class A + Z = 1 + + def z + Z + end + end + + class B < A + end + + p B.new.z #=> 1 + +The same is true for constants: + + class A + Z = 1 + end + + class B < A + def z + Z + end + end + + p B.new.z #=> 1 + +You can override the functionality of a superclass method by redefining the +method: + + class A + def m + 1 + end + end + + class B < A + def m + 2 + end + end + + p B.new.m #=> 2 + +If you wish to invoke the superclass functionality from a method use +super+: + + class A + def m + 1 + end + end + + class B < A + def m + 2 + super + end + end + + p B.new.m #=> 3 + +When used without any arguments +super+ uses the arguments given to the +subclass method. To send no arguments to the superclass method use +<code>super()</code>. To send specific arguments to the superclass method +provide them manually like <code>super(2)</code>. + ++super+ may be called as many times as you like in the subclass method. + += Singleton Classes + +The singleton class (also known as the metaclass or eigenclass) of an object is +a class that holds methods for only that instance. You can access the +singleton class of an object using <code>class << object</code> like this: + + class C + end + + class << C + # self is the singleton class here + end + +Most frequently you'll see the singleton class accessed like this: + + class C + class << self + # ... + end + end + +This allows definition of methods and attributes on a class (or module) without +needing to write <code>def self.my_method</code>. + +Since you can open the singleton class of any object this means that this code +block: + + o = Object.new + + def o.my_method + 1 + 1 + end + +is equivalent to this code block: + + o = Object.new + + class << o + def my_method + 1 + 1 + end + end + +Both objects will have a +my_method+ that returns +2+. + diff --git a/ruby_2_2/doc/syntax/precedence.rdoc b/ruby_2_2/doc/syntax/precedence.rdoc new file mode 100644 index 0000000000..515626c74f --- /dev/null +++ b/ruby_2_2/doc/syntax/precedence.rdoc @@ -0,0 +1,60 @@ += Precedence + +From highest to lowest, this is the precedence table for ruby. High precedence +operations happen before low precedence operations. + + !, ~, unary + + + ** + + unary - + + *, /, % + + +, - + + <<, >> + + & + + |, ^ + + >, >=, <, <= + + <=>, ==, ===, !=, =~, !~ + + && + + || + + .., ... + + ?, : + + modifier-rescue + + =, +=, -=, etc. + + defined? + + not + + or, and + + modifier-if, modifier-unless, modifier-while, modifier-until + + { } blocks + +Unary <code>+</code> and unary <code>-</code> are for <code>+1</code>, +<code>-1</code> or <code>-(a + b)</code>. + +Modifier-if, modifier-unless, etc. are for the modifier versions of those +keywords. For example, this is a modifier-unless expression: + + a += 1 unless a.zero? + +<code>{ ... }</code> blocks have priority below all listed operations, but +<code>do ... end</code> blocks have lower priority. + +All other words in the precedence table above are keywords. + diff --git a/ruby_2_2/doc/syntax/refinements.rdoc b/ruby_2_2/doc/syntax/refinements.rdoc new file mode 100644 index 0000000000..3ba03f6d58 --- /dev/null +++ b/ruby_2_2/doc/syntax/refinements.rdoc @@ -0,0 +1,261 @@ += Refinements + +Due to Ruby's open classes you can redefine or add functionality to existing +classes. This is called a "monkey patch". Unfortunately the scope of such +changes is global. All users of the monkey-patched class see the same +changes. This can cause unintended side-effects or breakage of programs. + +Refinements are designed to reduce the impact of monkey patching on other +users of the monkey-patched class. Refinements provide a way to extend a +class locally. + +Here is a basic refinement: + + class C + def foo + puts "C#foo" + end + end + + module M + refine C do + def foo + puts "C#foo in M" + end + end + end + +First, a class +C+ is defined. Next a refinement for +C+ is created using +Module#refine. Refinements only modify classes, not modules so the argument +must be a class. + +Module#refine creates an anonymous module that contains the changes or +refinements to the class (+C+ in the example). +self+ in the refine block is +this anonymous module similar to Module#module_eval. + +Activate the refinement with #using: + + using M + + c = C.new + + c.foo # prints "C#foo in M" + +== Scope + +You may only activate refinements at top-level, not inside any class, module +or method scope. You may activate refinements in a string passed to +Kernel#eval that is evaluated at top-level. Refinements are active until the +end of the file or the end of the eval string, respectively. + +Refinements are lexical in scope. When control is transferred outside the +scope the refinement is deactivated. This means that if you require or load a +file or call a method that is defined outside the current scope the refinement +will be deactivated: + + class C + end + + module M + refine C do + def foo + puts "C#foo in M" + end + end + end + + def call_foo(x) + x.foo + end + + using M + + x = C.new + x.foo # prints "C#foo in M" + call_foo(x) #=> raises NoMethodError + +If a method is defined in a scope where a refinement is active the refinement +will be active when the method is called. This example spans multiple files: + +c.rb: + + class C + end + +m.rb: + + require "c" + + module M + refine C do + def foo + puts "C#foo in M" + end + end + end + +m_user.rb: + + require "m" + + using M + + class MUser + def call_foo(x) + x.foo + end + end + +main.rb: + + require "m_user" + + x = C.new + m_user = MUser.new + m_user.call_foo(x) # prints "C#foo in M" + x.foo #=> raises NoMethodError + +Since the refinement +M+ is active in <code>m_user.rb</code> where +<code>MUser#call_foo</code> is defined it is also active when +<code>main.rb</code> calls +call_foo+. + +Since #using is a method, refinements are only active when it is called. Here +are examples of where a refinement +M+ is and is not active. + +In a file: + + # not activated here + using M + # activated here + class Foo + # activated here + def foo + # activated here + end + # activated here + end + # activated here + +In eval: + + # not activated here + eval <<EOF + # not activated here + using M + # activated here + EOF + # not activated here + +When not evaluated: + + # not activated here + if false + using M + end + # not activated here + +When defining multiple refinements in the same module, inside a refine block +all refinements from the same module are active when a refined method is +called: + + module ToJSON + refine Integer do + def to_json + to_s + end + end + + refine Array do + def to_json + "[" + map { |i| i.to_json }.join(",") + "]" + end + end + + refine Hash do + def to_json + "{" + map { |k, v| k.to_s.dump + ":" + v.to_json }.join(",") + "}" + end + end + end + + using ToJSON + + p [{1=>2}, {3=>4}].to_json # prints "[{\"1\":2},{\"3\":4}]" + +You may also activate refinements in a class or module definition, in which +case the refinements are activated from the point where using is called to +the end of the class or module definition: + + # not activated here + class Foo + # not activated here + using M + # activated here + def foo + # activated here + end + # activated here + end + # not activated here + +Note that the refinements in M are not activated automatically even if the class +Foo is reopened later. + +== Method Lookup + +When looking up a method for an instance of class +C+ Ruby checks: + +* If refinements are active for +C+, in the reverse order they were activated: + * The prepended modules from the refinement for +C+ + * The refinement for +C+ + * The included modules from the refinement for +C+ +* The prepended modules of +C+ +* +C+ +* The included modules of +C+ + +If no method was found at any point this repeats with the superclass of +C+. + +Note that methods in a subclass have priority over refinements in a +superclass. For example, if the method <code>/</code> is defined in a +refinement for Integer <code>1 / 2</code> invokes the original Fixnum#/ +because Fixnum is a subclass of Integer and is searched before the refinements +for the superclass Integer. + +If a method +foo+ is defined on Integer in a refinement, <code>1.foo</code> +invokes that method since +foo+ does not exist on Fixnum. + +== +super+ + +When +super+ is invoked method lookup checks: + +* The included modules of the current class. Note that the current class may + be a refinement. +* If the current class is a refinement, the method lookup proceeds as in the + Method Lookup section above. +* If the current class has a direct superclass, the method proceeds as in the + Method Lookup section above using the superclass. + +Note that +super+ in a method of a refinement invokes the method in the +refined class even if there is another refinement which has been activated in +the same context. + +== Indirect Method Calls + +When using indirect method access such as Kernel#send, Kernel#method or +Kernel#respond_to? refinements are not honored for the caller context during +method lookup. + +This behavior may be changed in the future. + +== Refinements and module inclusion + +Refinements are inherited by module inclusion. That is, using activates all +refinements in the ancestors of the specified module. Refinements in a +descendant have priority over refinements in an ancestor. + +== Further Reading + +See http://bugs.ruby-lang.org/projects/ruby-trunk/wiki/RefinementsSpec for the +current specification for implementing refinements. The specification also +contains more details. + |