summaryrefslogtreecommitdiff
path: root/doc/syntax
diff options
context:
space:
mode:
Diffstat (limited to 'doc/syntax')
-rw-r--r--doc/syntax/assignment.rdoc10
-rw-r--r--doc/syntax/calling_methods.rdoc14
-rw-r--r--doc/syntax/comments.rdoc2
-rw-r--r--doc/syntax/control_expressions.rdoc70
-rw-r--r--doc/syntax/exceptions.rdoc10
-rw-r--r--doc/syntax/literals.rdoc18
-rw-r--r--doc/syntax/modules_and_classes.rdoc32
-rw-r--r--doc/syntax/operators.rdoc75
-rw-r--r--doc/syntax/pattern_matching.rdoc32
-rw-r--r--doc/syntax/refinements.rdoc2
10 files changed, 209 insertions, 56 deletions
diff --git a/doc/syntax/assignment.rdoc b/doc/syntax/assignment.rdoc
index 1321bbf3ac..f45f5bc0ea 100644
--- a/doc/syntax/assignment.rdoc
+++ b/doc/syntax/assignment.rdoc
@@ -107,7 +107,7 @@ 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.
+variable.
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
@@ -162,9 +162,7 @@ Here is an example of instance variable usage:
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.
+An uninitialized instance variable has a value of +nil+.
The +value+ method has access to the value set by the +initialize+ method, but
only for the same object.
@@ -403,6 +401,10 @@ assigning. This is similar to multiple assignment:
p a # prints [1, 2, 3]
+ b = *1
+
+ p b # prints [1]
+
You can splat anywhere in the right-hand side of the assignment:
a = 1, *[2, 3]
diff --git a/doc/syntax/calling_methods.rdoc b/doc/syntax/calling_methods.rdoc
index da061dbfdb..c2c6c61a10 100644
--- a/doc/syntax/calling_methods.rdoc
+++ b/doc/syntax/calling_methods.rdoc
@@ -210,7 +210,7 @@ definition. If a keyword argument is given that the method did not list,
and the method definition does not accept arbitrary keyword arguments, an
ArgumentError will be raised.
-Keyword argument value can be omitted, meaning the value will be be fetched
+Keyword argument value can be omitted, meaning the value will be fetched
from the context by the name of the key
keyword1 = 'some value'
@@ -322,18 +322,6 @@ 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)
-
-Note that this behavior is currently deprecated and will emit a warning.
-This behavior will be removed in Ruby 3.0.
-
You may also use the <code>**</code> (described next) to convert a Hash into
keyword arguments.
diff --git a/doc/syntax/comments.rdoc b/doc/syntax/comments.rdoc
index dbc7816984..00d19d588a 100644
--- a/doc/syntax/comments.rdoc
+++ b/doc/syntax/comments.rdoc
@@ -196,7 +196,7 @@ The method Module#const_set is not affected.
In this mode, all values assigned to constants are deeply copied and
made shareable. It is safer mode than +experimental_everything+.
- # shareable_constant_value: experimental_everything
+ # shareable_constant_value: experimental_copy
var = [{foo: []}]
var.frozen? # => false (assignment was made to local variable)
X = var # => calls `Ractor.make_shareable(var, copy: true)`
diff --git a/doc/syntax/control_expressions.rdoc b/doc/syntax/control_expressions.rdoc
index df3b5ced38..9126289389 100644
--- a/doc/syntax/control_expressions.rdoc
+++ b/doc/syntax/control_expressions.rdoc
@@ -189,7 +189,7 @@ The same is true for +unless+.
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
+patterns are matched using the <tt>===</tt> method which is aliased to <tt>==</tt> on
Object. Other classes must override it to give meaningful behavior. See
Module#=== and Regexp#=== for examples.
@@ -569,3 +569,71 @@ evaluated on the following iteration:
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.
+
+== throw/catch
+
++throw+ and +catch+ are used to implement non-local control flow in Ruby. They
+operate similarly to exceptions, allowing control to pass directly from the
+place where +throw+ is called to the place where the matching +catch+ is
+called. The main difference between +throw+/+catch+ and the use of exceptions
+is that +throw+/+catch+ are designed for expected non-local control flow,
+while exceptions are designed for exceptional control flow situations, such
+as handling unexpected errors.
+
+When using +throw+, you provide 1-2 arguments. The first argument is the
+value for the matching +catch+. The second argument is optional (defaults to
++nil+), and will be the value that +catch+ returns if there is a matching
++throw+ inside the +catch+ block. If no matching +throw+ method is called
+inside a +catch+ block, the +catch+ method returns the return value of the
+block passed to it.
+
+ def a(n)
+ throw :d, :a if n == 0
+ b(n)
+ end
+
+ def b(n)
+ throw :d, :b if n == 1
+ c(n)
+ end
+
+ def c(n)
+ throw :d if n == 2
+ end
+
+ 4.times.map do |i|
+ catch(:d) do
+ a(i)
+ :default
+ end
+ end
+ # => [:a, :b, nil, :default]
+
+If the first argument you pass to +throw+ is not handled by a matching
++catch+, an UncaughtThrowError exception will be raised. This is because
++throw+/+catch+ should only be used for expected control flow changes, so
+using a value that is not already expected is an error.
+
++throw+/+catch+ are implemented as Kernel methods (Kernel#throw and
+Kernel#catch), not as keywords. So they are not usable directly if you are
+in a BasicObject context. You can use Kernel.throw and Kernel.catch in
+this case:
+
+ BasicObject.new.instance_exec do
+ def a
+ b
+ end
+
+ def b
+ c
+ end
+
+ def c
+ ::Kernel.throw :d, :e
+ end
+
+ result = ::Kernel.catch(:d) do
+ a
+ end
+ result # => :e
+ end
diff --git a/doc/syntax/exceptions.rdoc b/doc/syntax/exceptions.rdoc
index 31e2f0175c..ac5ff78a95 100644
--- a/doc/syntax/exceptions.rdoc
+++ b/doc/syntax/exceptions.rdoc
@@ -86,7 +86,7 @@ To always run some code whether an exception was raised or not, use +ensure+:
rescue
# ...
ensure
- # this always runs
+ # this always runs BUT does not implicitly return the last evaluated statement.
end
You may also run some code when an exception is not raised:
@@ -96,7 +96,11 @@ You may also run some code when an exception is not raised:
rescue
# ...
else
- # this runs only when no exception was raised
+ # this runs only when no exception was raised AND return the last evaluated statement
ensure
- # ...
+ # this always runs.
+ # It is evaluated after the evaluation of either the `rescue` or the `else` block.
+ # It will not return implicitly.
end
+
+NB : Without explicit +return+ in the +ensure+ block, +begin+/+end+ block will return the last evaluated statement before entering in the `ensure` block.
diff --git a/doc/syntax/literals.rdoc b/doc/syntax/literals.rdoc
index 5e10e6a140..0c1e4a434b 100644
--- a/doc/syntax/literals.rdoc
+++ b/doc/syntax/literals.rdoc
@@ -277,6 +277,12 @@ the content. Note that empty lines and lines consisting solely of literal tabs
and spaces will be ignored for the purposes of determining indentation, but
escaped tabs and spaces are considered non-indentation characters.
+For the purpose of measuring an indentation, a horizontal tab is regarded as a
+sequence of one to eight spaces such that the column position corresponding to
+its end is a multiple of eight. The amount to be removed is counted in terms
+of the number of spaces. If the boundary appears in the middle of a tab, that
+tab is not removed.
+
A heredoc allows interpolation and escaped characters. You may disable
interpolation and escaping by surrounding the opening identifier with single
quotes:
@@ -408,9 +414,9 @@ slash (<tt>'/'</tt>) characters:
re = /foo/ # => /foo/
re.class # => Regexp
-The trailing slash may be followed by one or more _flag_ characters
-that modify the behavior.
-See {Regexp options}[rdoc-ref:Regexp@Options] for details.
+The trailing slash may be followed by one or more modifiers characters
+that set modes for the regexp.
+See {Regexp modes}[rdoc-ref:Regexp@Modes] for details.
Interpolation may be used inside regular expressions along with escaped
characters. Note that a regular expression may require additional escaped
@@ -517,9 +523,9 @@ A few "symmetrical" character pairs may be used as delimiters:
%r(foo) # => /foo/
%r<foo> # => /foo/
-The trailing delimiter may be followed by one or more _flag_ characters
-that modify the behavior.
-See {Regexp options}[rdoc-ref:Regexp@Options] for details.
+The trailing delimiter may be followed by one or more modifier characters
+that set modes for the regexp.
+See {Regexp modes}[rdoc-ref:Regexp@Modes] for details.
=== <tt>%x</tt>: Backtick Literals
diff --git a/doc/syntax/modules_and_classes.rdoc b/doc/syntax/modules_and_classes.rdoc
index 6122f6e08e..9e05c5c774 100644
--- a/doc/syntax/modules_and_classes.rdoc
+++ b/doc/syntax/modules_and_classes.rdoc
@@ -40,9 +40,9 @@ functionality:
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.
+Reopening modules (or classes) is a very powerful feature of Ruby, but it is
+best to only reopen modules you own. Reopening modules you do not own may lead
+to naming conflicts or difficult to diagnose bugs.
== Nesting
@@ -155,8 +155,8 @@ 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.
+sender must inherit the Class or Module which defines the method. 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
@@ -259,6 +259,28 @@ includes a minimum of built-in methods. You can use BasicObject to create an
independent inheritance structure. See the BasicObject documentation for
further details.
+Just like modules, classes can also be reopened. You can omit its superclass
+when you reopen a class. Specifying a different superclass than the previous
+definition will raise an error.
+
+ class C
+ end
+
+ class D < C
+ end
+
+ # OK
+ class D < C
+ end
+
+ # OK
+ class D
+ end
+
+ # TypeError: superclass mismatch for class D
+ class D < String
+ end
+
== Inheritance
Any method defined on a class is callable from its subclass:
diff --git a/doc/syntax/operators.rdoc b/doc/syntax/operators.rdoc
new file mode 100644
index 0000000000..d3045ac99e
--- /dev/null
+++ b/doc/syntax/operators.rdoc
@@ -0,0 +1,75 @@
+= Operators
+
+In Ruby, operators such as <code>+</code>, are defined as methods on the class.
+Literals[rdoc-ref:syntax/literals.rdoc] define their methods within the lower
+level, C language. String class, for example.
+
+Ruby objects can define or overload their own implementation for most operators.
+
+Here is an example:
+
+ class Foo < String
+ def +(str)
+ self.concat(str).concat("another string")
+ end
+ end
+
+ foobar = Foo.new("test ")
+ puts foobar + "baz "
+
+This prints:
+
+ test baz another string
+
+What operators are available is dependent on the implementing class.
+
+== Operator Behavior
+
+How a class behaves to a given operator is specific to that class, since
+operators are method implementations.
+
+When using an operator, it's the expression on the left-hand side of the
+operation that specifies the behavior.
+
+ 'a' * 3 #=> "aaa"
+ 3 * 'a' # TypeError: String can't be coerced into Integer
+
+== Logical Operators
+
+Logical operators are not methods, and therefore cannot be
+redefined/overloaded. They are tokenized at a lower level.
+
+Short-circuit logical operators (<code>&&</code>, <code>||</code>,
+<code>and</code>, and <code>or</code>) do not always result in a boolean value.
+Similar to blocks, it's the last evaluated expression that defines the result
+of the operation.
+
+=== <code>&&</code>, <code>and</code>
+
+Both <code>&&</code>/<code>and</code> operators provide short-circuiting by executing each
+side of the operator, left to right, and stopping at the first occurrence of a
+falsey expression. The expression that defines the result is the last one
+executed, whether it be the final expression, or the first occurrence of a falsey
+expression.
+
+Some examples:
+
+ true && 9 && "string" #=> "string"
+ (1 + 2) && nil && "string" #=> nil
+ (a = 1) && (b = false) && (c = "string") #=> false
+
+ puts a #=> 1
+ puts b #=> false
+ puts c #=> nil
+
+In this last example, <code>c</code> was initialized, but not defined.
+
+=== <code>||</code>, <code>or</code>
+
+The means by which <code>||</code>/<code>or</code> short-circuits, is to return the result of
+the first expression that is truthy.
+
+Some examples:
+
+ (1 + 2) || true || "string" #=> 3
+ false || nil || "string" #=> "string"
diff --git a/doc/syntax/pattern_matching.rdoc b/doc/syntax/pattern_matching.rdoc
index b7d614770c..6a30380f46 100644
--- a/doc/syntax/pattern_matching.rdoc
+++ b/doc/syntax/pattern_matching.rdoc
@@ -415,9 +415,15 @@ Additionally, when matching custom classes, the expected class can be specified
end
#=> "matched: 1"
+These core and library classes implement deconstruction:
+
+* MatchData#deconstruct and MatchData#deconstruct_keys;
+* Time#deconstruct_keys, Date#deconstruct_keys, DateTime#deconstruct_keys.
+
== Guard clauses
-+if+ can be used to attach an additional condition (guard clause) when the pattern matches. This condition may use bound variables:
++if+ can be used to attach an additional condition (guard clause) when the pattern matches in +case+/+in+ expressions.
+This condition may use bound variables:
case [1, 2]
in a, b if b == a*2
@@ -445,28 +451,10 @@ Additionally, when matching custom classes, the expected class can be specified
end
#=> "matched"
-== Current feature status
-
-As of Ruby 3.1, find patterns are considered _experimental_: its syntax can change in the future. Every time you use these features in code, a warning will be printed:
-
- [0] => [*, 0, *]
- # warning: Find pattern is experimental, and the behavior may change in future versions of Ruby!
- # warning: One-line pattern matching is experimental, and the behavior may change in future versions of Ruby!
-
-To suppress this warning, one may use the Warning::[]= method:
-
- Warning[:experimental] = false
- eval('[0] => [*, 0, *]')
- # ...no warning printed...
-
-Note that pattern-matching warnings are raised at compile time, so this will not suppress the warning:
-
- Warning[:experimental] = false # At the time this line is evaluated, the parsing happened and warning emitted
- [0] => [*, 0, *]
-
-So, only subsequently loaded files or `eval`-ed code is affected by switching the flag.
+Note that <code>=></code> and +in+ operator can not have a guard clause.
+The following examples is parsed as a standalone expression with modifier +if+.
-Alternatively, the command line option <code>-W:no-experimental</code> can be used to turn off "experimental" feature warnings.
+ [1, 2] in a, b if b == a*2
== Appendix A. Pattern syntax
diff --git a/doc/syntax/refinements.rdoc b/doc/syntax/refinements.rdoc
index c900ab1bdc..17d5e67c21 100644
--- a/doc/syntax/refinements.rdoc
+++ b/doc/syntax/refinements.rdoc
@@ -279,6 +279,6 @@ Refinements in descendants have higher precedence than those of ancestors.
== Further Reading
-See https://bugs.ruby-lang.org/projects/ruby-master/wiki/RefinementsSpec for the
+See https://github.com/ruby/ruby/wiki/Refinements-Spec for the
current specification for implementing refinements. The specification also
contains more details.