by David Flanagan and Yukihiro Matsumoto
I, Michael Parker, own this book and took these notes to further my own learning. If you enjoy these notes, please purchase the book!
- pg 2: Every value is an object, even simple numeric literals and the values
true
,false
, andnil
. - pg 3: Parentheses are usually optional and commonly omitted, and so method invocations can look like references to named fields or named variables of an object.
- pg 4: Symbols are immutable, interned strings, and so can be compared by identity rather than textual content.
- pg 4: Double quoted strings can include arbitrary Ruby expressions delimited by
#{
and}
, and interpolated values are converted to strings by callingto_s
. - pg 5: Strings, arrays, and streams use the
<<
operator for an append operation. - pg 6: Methods can be defined on individual objects by prefixing the name of the method with the object, and are called singletonmethods.
- pg 6: Methods that end with
=
are special because they can be invoked using assignment syntax. - pg 7: Global variables are prefixed with
$
, instance variables with@
, and class variables with@@
. - pg 7: The
..
operator has an inclusive right endpoint, while the...
operator has an exclusive right endpoint. - pg 7:
Regexp
andRange
objects define===
for membership, which is what thecase
statement also uses, and so it is called the case equality operator. - pg 10: Even core classes in Ruby are open, and so any program can add methods to them.
- pg 10: Strings in Ruby are mutable, and so a string literal in a loop evaluates to a new object on each iteration.
- pg 11: When evaluating conditional expressions, the value
nil
is treated asfalse
, and any other value is the same astrue
. - pg 11: In Ruby 1.9, the MRI (Matz's Ruby Implementation) was merged with YARV (Yet Another Ruby Virtual machine) that executes to bytecode before execution.
- pg 12: Unlike
print
,puts
ends with a newline, and its alternativep
converts objects to strings usinginspect
which can return more programmer-friendly representations. - pg 13: When using
ri
, you must use::
to refer to a class method or#
to refer to an instance method if both are defined with the same name. - pg 14: Ruby 1.9 knows how to find installed gems on its own, and you do not need to put
require rubygems
in your programs that use gems. - pg 15: You can use the
gem
method before callingrequire
to load a specific version of a gem other than the most recent one.
- pg 26: Ruby has no equivalent of
/* */
that allows embedding a comment in code. - pg 27: Embedded documents defined with
=begin
and=end
allow defining multi-line comments easily, and are usually intended for use by a source code postprocessing tool. - pg 27: The
rdoc
tool converts comments to HTML or prepares them for display usingri
, and works with comments using#
, or embedded documents that start with=begin rdoc
. - pg 28: Identifiers that begin with a capital letter are constants, but the Ruby interpreter will issue a warning and not an error if their values are altered.
- pg 30: A number of Ruby's operators are implemented as methods so that classes can redefine them for their own purposes.
- pg 31: Ruby does not complain if you prefix keywords with
@
,@@
, or$
and use them as instance, class, or global variable names, but clearly don't do that. - pg 31: Important features are implemented as methods of the
Kernel
,Module
,Class
, andObject
classes, so their identifiers should be treated as reserved as well. - pg 32: Ruby continues parsing a statement on the next line if the first line is not complete.
- pg 32: To prevent automatically terminating a statement, you can escape a line break with a backslash.
- pg 33: In Ruby 1.9, if the first nonspace character is a period, then the line is considered a continuation line, which allows creation of fluent APIs.
- pg 33: If warnings are enabled with
-w
, Ruby issues a warning whenever it finds ambiguous code from omitting parentheses in method calls. - pg 34: In Ruby the term methods is used, not functions, procedures, or subroutines.
- pg 35: Nested blocks of code are indented two spaces relative to their delimiters by convention.
- pg 35: Formal blocks may be delimited with curly braces, or they may be delimited with the keywords
do
andend
. - pg 36: The
require
method prevents any given module from being loaded more than once. - pg 38: UTF-8 encoded files can identify their encoding if the first three bytes are 0xEF 0xBB 0xBF, which is called the "Byte Order Mark," or BOM.
- pg 38: In Ruby 1.9, the language keyword
__ENCODING__
evaluates to the source encoding of the currently executing code. - pg 38: The default external encoding is what Ruby uses when reading from files and streams; to convert that text to a single common encoding, specify the default internal encoding.
- pg 39: Query the default external and internal encodings using methods
Encoding.default_external
andEncoding.default_internal
, respectively.
- pg 42: If a value fits into a
Fixnum
, it is stored as such; otherwise, it is automatically converted to aBignum
. - pg 43: Underscores may be inserted into integer literals, and this feature can be used as a thousands separator.
- pg 43: Integer literals starting with
0x
or0X
are hexadecimal, ones starting with0b
or0B
are binary, and ones starting with0
and no subsequent letter are octal. - pg 44: Floating point values require that digits appear before the decimal point.
- pg 44: Integer division by zero causes a
ZeroDivisionError
to be thrown, while floating-point division by zero simply returns the valueInfinity
. - pg 45: Integer values can also be indexed like arrays to query, but not set, individual bits.
- pg 45: When one of the operands in integer division is negative, Ruby rounds towards negative infinity instead of toward
0
like C and Java. - pg 45: The sign of the result of a modulo operation in Ruby is that of the second operand, instead of the first operand like C and Java.
- pg 47: In single-quoted strings, a backslash is not special if the character that follows is anything other than a quote or a backslash.
- pg 47: To break a single-quoted string across multiple lines, break it into multiple adjacent string literals while escaping the newlines between the literals.
- pg 48: Curly braces may be omitted when the expression to be interpolated in a double-quoted string literal is a reference to a global, instance, or class variable.
- pg 48: Ruby uses the
%
operator to performsprintf
-style string interpolation, just like Python does. - pg 48: Double-quoted string literals may span multiple lines, and line terminators become part of the literal unless escaped by a backslash.
- pg 51: The sequence
%q
follows single-quoted rules, and the sequence%Q
follows double-quoted rules. - pg 51: A string literal formed with
%q
or%Q
continues until a matching unescaped delimiter is found, and the delimiters(
,[
,<
pair with)
,]
, and>
, respectively. - pg 53: Text using sequence
%x
or between backticks is treated as a double-quoted string literal and run as a shell command by `Kernel.``, which runs it as a shell command. - pg 53: Every time Ruby encounters a string literal, it creates a new object, and so avoid using literals in loops for efficiency.
- pg 54: Single characters can be included literally by preceding them with
?
, but since characters are strings with length 1 in Ruby 1.9, this has little use. - pg 55: If the righthand operand of a string’s
<<
operator is an integer, it is taken to be a Unicode codepoint, and the corresponding character is appended. - pg 56: Ruby does not throw an exception if you access a character beyond the end of the string, but instead returns
nil
. - pg 57: Reading
s[s.length]
returnsnil
, while readings[s.length, 1]
returns an empty string and will not work for indexes greater thans.length
. - pg 57: Assigning
s[s.length]
is an error, while assignings[s.length, 0]
appends to the end of the string. - pg 58: Indexing a string with another string is only really useful when you want to replace the matched string with some other string.
- pg 58: The
each_char
iterator may be more efficient than using the[]
operator, and complements theeach_byte
andeach_line
iterators. - pg 59: In Ruby 1.9, string elements are characters which are strings of length 1, unlike 1.8 which assumes ASCII, where elements are numbers representing byte values.
- pg 60: If a string consists of only one-byte characters, random access is efficient; otherwise Ruby 1.9 must sequentially iterate to the character.
- pg 60: Encoding of string literals is the same as the source file encoding, except that literals containing
\u
escapes are always encoded in UTF-8. - pg 60: The
ASCII-8BIT
encoding in Ruby 1.9 has the aliasBINARY
and is equivalent to the encoding in Ruby 1.8, while theUS-ASCII
encoding is true 7-bit ASCII. - pg 61: The
force_encoding
method does not perform validation, which is done by thevalid_encoding?
method. - pg 62: If a string you call
encode
on consists of unencoded bytes, you need to specify the encoding by which to interpret those bytes before transcoding them. - pg 63: To obtain the encoding for the current locale, call
Encoding.locale_charmap
and pass the resulting string to theEncoding.find
factory method. - pg 64: Attempting to read an index with
index >= size
orindex < -size
returnsnil
as opposed to raising an exception. - pg 64: Assigning an element to an index beyond the end of the array automatically extends the array with
nil
elements. - pg 64: The
%w
and%W
sequences express array literals whose elements are strings without spaces, and follow the same rules as%q
and%Q
. - pg 65: Arrays indexed with a negative value cannot be used on the left side of assignment statements; to prepend, index with the two integers
0,0
. - pg 65: When replacing a subarray by indexing with two integers, if the right side is a single element, the brackets
[
and]
are optional. - pg 66: Treating arrays as unordered sets, the boolean operators
|
and&
perform union and intersection, while-
is like set difference but may contain duplicate elements. - pg 67: Ruby 1.9 supports a succinct hash literal syntax where the keys are symbols, and the colon moves to the end of the hash key and replaces the arrow.
- pg 68: If you define a new class that overrides the
eql?
method, you must also override thehash
method or else instances of the class will not work as keys. - pg 68: As a special case, Ruby makes private copies of all strings used as hash keys; otherwise, if you mutate a key, you must call the
rehash
method after doing so. - pg 69: A value can only be used as a range endpoint if it responds to the comparison operator
<=>
. - pg 69: A range where the class of the endpoints defines a
succ
method is called a discrete range, and can be iterated usingeach
,step
, andEnumerable
methods. - pg 69: To invoke a method on a range literal, you must parenthesize the literal, or else the method invocation is actually on the range endpoint.
- pg 70: A continuous membership test compares against the range endpoints, while a discrete membership test uses
succ
to enumerate all values and is potentially more expensive. - pg 70: In Ruby 1.9, unless the endpoints are numeric,
include?
andmember?
perform a discrete membership test, whilecover?
performs a continuous membership test. - pg 71: The
%s
sequence defines a literal syntax for symbols the same way that%q
and%Q
does for strings. - pg 71: The
intern
andto_sym
methods convert strings to symbols, and theto_s
andid2name
methods convert back. - pg 72: There is no
Boolean
class in Ruby, andTrueClass
andFalseClass
both haveObject
as their superclass. - pg 73: The
new
method of theClass
class allocates memory to hold the new object, and then initializes its state by invoking itsinitialize
method. - pg 74: By default the
Object
class implements methodhash
by returning the object’s ID, which is also returned by theobject_id
method. - pg 75: The
instance_of?
method tests if an object is a given class, whileis_a?
,kind_of?
, and the===
operator test if an object is an instance or a subclass. - pg 76: The
equal?
method tests whether two values refer to exactly the same object, and by convention, subclasses never override it. - pg 77: The
==
operator behaves likeequal?
unless overridden, and typically checks equality while performing needed type conversion, like between aFixnum
andFloat
. - pg 77: The
eql?
method behaves likeequal?
unless overridden, and is typically used as a strict version of==
that performs no type conversion. - pg 78: If the
<=>
comparator cannot make a meaningful comparison, it should returnnil
. - pg 79: The
Comparable
mixin defines the operators<
,<=
,==
,>=
, and>
in terms of<=>
, as well as thebetween?
operator. - pg 79: The
to_s
,to_i
,to_f
, andto_a
methods allow explicit conversion toString
,Integer
,Float
, andArray
, respectively. - pg 80: The default
inspect
method simply callsto_s
, but should be overridden to return a representation useful for Ruby developers and not end users. - pg 81: The
Kernel
module defines the functionsArray
,Float
,Integer
, andString
, which attempt to perform conversions that in some cases use both implicit and explicit conversion methods. - pg 81: Numeric objects have a
coerce
method tries to convert an argument to its own type, or else it converts both itself and the argument to a more general compatible type. - pg 82: By default both
clone
anddup
return a shallow copy, but if aninitialize_copy
method is provided, they allocate a new, empty instance and call that. - pg 83: The
clone
method copies both the frozen and tainted state of an object, whereasdup
only copies tainted state, andclone
also copies any singleton methods, whereasdup
does not. - pg 84: Once an instance of a class is frozen, it cannot be thawed, and a copy created with
clone
will also be frozen, while a copy created withdup
will be thawed. - pg 84: The tainted property allows tracking of user input and data derived from it, and the trusted property allows tracking of untrusted data.
- pg 86: Everything in Ruby, including class and method definitions, can be evaluated as an expression and can return a value.
- pg 87: Variables whose names begin with an underscore or lowercase letter are local variables, defined only within the current method or block.
- pg 88: If the interpreter hasn’t seen an assignment to a variable, it treats an expression as a method invocation, and raises a
NameError
if no such method exists. - pg 88: A variable comes into existence when the interpreter sees an assignment for that variable, even if the assignment is not actually executed.
- pg 89: Global functions and constants are defined and looked up within the
Object
class, and so omitting the lefthand side of::
is actually the same as usingObject::
. - pg 89: Unlike variables that come into existence when the interpreter sees them, constants do not exist until a value is assigned to them, and so no constants are uninitialized.
- pg 90: A method name can be separated from the object it is invoked on with
::
instead of.
, but this is rare because it looks more like a constant reference expression. - pg 90: Methods in
Kernel
are global functions, and because global functions are methods ofObject
, they can be invoked in any context regardless of the value ofself
. - pg 91: Ruby objects expose only methods to the outside world, and it is intentional that attribute accessor methods without arguments look like variable references.
- pg 92: By itself,
super
passes the arguments of the current method to the method with the same name in the superclass. - pg 94: Assignment to constants is not allowed within the body of a method, since Ruby assumes that methods are intended to be executed more than once.
- pg 95: When an object has both a getter method and a setter method, it is called an attribute.
- pg 97: When using the
||=
idiom for assigning a default value, if the left operand is notnil
orfalse
, then no assignment is actually performed nor setter method is invoked. - pg 97: Given a single lvalue and multiple rvalues, an array creating all the rvalues is assigned to the lvalue.
- pg 98: Following a lvalue with a comma performs parallel assignment and discards superfluous rvalues, which is useful for unpacking an array.
- pg 99: In Ruby 1.9 a list of rvalues can have any number of splats, but you cannot perform a "double splat" on a nested array.
- pg 99: Any ravlue that defines a
to_a
method can be prefixed with a splat, otherwise no expansion is performed and the splat evaluates to the object itself. - pg 99: In Ruby 1.9 a list of lvalues may include one splat operator at any position in the list.
- pg 100: If a parallel assignment is prefixed with the name of a method, Ruby will interpret the commas as method argument separators rather than lvalue and rvalue separators.
- pg 102: In general, classes may define their own arithmetic, ordering, and equality operators, but they may not redefine the various boolean operators.
- pg 103: Unary plus and minus have the method names
+@
and-@
to disambiguate themselves from the binary plus and minus methods. - pg 103: The exponentiation operator handles fractional and negative exponents.
- pg 104: When an array is multiplied by a string, the result is the same as calling its
join
method and passing that string as an argument. - pg 104: The
String
,Array
, andIO
classes define<<
as the append operator, as do other "appendable" classes likeQueue
andLogger
. - pg 105: The boolean operators
&&
and||
are more efficient than&
,|
, and^
because they do not evaluate their righthand operand unless otherwise needed. - pg 105: The
Module
class, which is the superclass ofClass
, definesA < B
astrue
if classA
is a subclass or descendant of classB
. - pg 106: The
Module
comparison operators returnnil
between classes where neither one is a subclass of the other. - pg 106:
String
defines the pattern matching operator~=
so that it expects aRegExp
as its argument, andRegExp
defines it so that it expects aString
. - pg 106: There is no
!==
operator; if you want to negate===
, you must do it yourself. - pg 107: An idiomatic use of
&&
is to only access an attribute of an object if that object is notnil
. - pg 108: One idiomatic use of
||
is to return the first non-nil
value in a series of alternatives. - pg 108: The
and
,or
, andnot
operators are low precedence versions of&&
,||
, and!
, and are even lower than the assignment operator. - pg 109: The
and
andor
operators have the same precedence, withnot
slightly higher, which is unlike&&
having a higher precedence than||
. - pg 110: A flip-flop expression is false until the lefthand expression evaluates to
true
, and remainstrue
until the righthand expression evaluates totrue
. - pg 110: When a
..
flip-flop flips totrue
, it immediately evaluates its righthand expression to see if it should flop back tofalse
, while a...
flip-flop waits until the next evaluation. - pg 112: Since method names can end in a question mark, you must put parentheses around the first operand of the ternary operator or add a disambiguating space.
- pg 113: Although assignment operators cannot be redefined as methods, compound assignment operators like
+=
use redefinable operators like+
. - pg 113: The
defined?
method returnsnil
given an undefined variable or method, or if the operand is an expression that usesyield
orsuper
in an inappropriate context. - pg 115: It is better to think of method invocation as a special kind of expression than to think of
()
as a method-invocation operator.
- pg 118: The expression of a conditional must be separated from the body by a newline or semicolon or the keyword
then
. - pg 121: Using
if
as a statement modifier does not allow any kind ofelse
clause. - pg 124: Comma separated expressions in the
when
clause act like the||
operator, as if any expression evaluates totrue
, its body is executed. - pg 126: If a
when
clause contains multiple expressions separated by commas, the===
operator is invoked on each one. - pg 126: Expressions in
when
clauses do not have to be compile-time constants, so no lookup table is used, and performance is comparable to anif
statement andelsif
clauses. - pg 128: When using
while
oruntil
as a modifier, if the loop body is between thebegin
andend
keywords then the body runs at least once like ado
/while
loop, but this usage is discouraged. - pg 129: The
for
/in
loop calls theeach
method of the specified object. - pg 129: A loop variable in a
for
loop remains defined after the loop exits, as does new variables defined within the body of the loop. - pg 130: Iterators are methods that interact with a block of code that follows them by use of the
yield
statement, and do not need to serve an iteration or looping function. - pg 132: In general,
n.times
is equivalent to0.upto(n-1)
. - pg 132: The
Enumerable
module implements the methodeach_with_index
, and the rhymingcollect
(also calledmap
),select
,reject
, andinject
methods on top of theeach
method. - pg 133: If no initial accumulator value is provided to
inject
, it is assigned the first element in the enumerable object, and the block is called first with the second element. - pg 134: You can pass a hash literal without curly braces around it to
yield
, but you cannot pass a block, i.e. you cannot pass a block to a block. - pg 135: The
block_given?
method and its synonymiterator?
determines whether there is a block associated with the invocation. - pg 135: The
to_enum
andenum_for
methods return enumerators that can serve as immutable proxy objects, instead of requiring defensive copies. - pg 136: The built-in iterator methods of Ruby 1.9 automatically return an enumerator when invoked with no block, bypassing the need to use
to_enum
orenum_for
. - pg 137: In Ruby 1.9, enumerators are also external iterators, where the client can control iteration using the
next
method untilStopIteration
is raised. - pg 138: The
Kernel.loop
method in Ruby 1.9 includes an implicitrescue
clause and exits cleanly whenStopIteration
is raised. - pg 138: In general, if new invocations of each on the underlying
Enumerable
object do not restart iteration from the beginning, then callingrewind
will not restart it either. - pg 141: Omitting parentheses around method arguments and using curly brace delimiters will associate a block with the last method argument instead of the method itself.
- pg 142: A
return
inside a block causes the containing method to return; usenext
instead, or rely on the block returning the value of the last expression evaluated. - pg 142: While variables created in a block are undefined outside the block, assigning to a variable already defined outside the block does not create a new block-local variable.
- pg 143: Follow the list of block parameters with a semicolon and a list of block local variables to prevent inadvertently clobbering the value of some existing variable.
- pg 145: In Ruby 1.9, prefix a block parameter with
*
to assign it an array with multiple yielded values, or else extra values are silently discarded as if,
were appended. - pg 145: In Ruby 1.9, the final block parameter may be prefixed with
&
to indicate that it is to receive any block associated with the invocation of the block. - pg 147: The
return
statement always causes the lexically enclosing method, or the method that the block appears inside of when viewing the source code, to return. - pg 148: The
break
statement transfers control out of the block, out of the iterator that invoked it, and to the first expression following the invocation of the iterator. - pg 148: A
break
statement can be used with a single expression or multiple expressions; this value or array of values becomes the value of the loop or the iterator return value. - pg 151: The
redo
statement transfers control to the first expression of the body, and does not retest the loop condition or fetch the next element from an iterator. - pg 151: The
redo
statement is uncommon, but is useful to recover from errors when prompting a user for input. - pg 153: Unlike a labeled break,
throw
andcatch
are not restricted to loops, and can propagate up the call stack to cause a block in an invoking thread to exit. - pg 154: If
throw
is called, by default the return value of the correspondingcatch
isnil
, unless you pass a second argument tothrow
. - pg 155: The
StandardError
exception type is for recoverable errors; all other subclasses ofException
represent more serious ones that programs do not attempt to recover. - pg 157:
raise
with no arguments creates aRuntimeError
, whileraise
with a single string argument creates aRuntimeError
with that as its message. - pg 157: If the first argument to
raise
is an object with anexception
method, it is called and its return value is raised;Exception
defines such a method. - pg 158: The global variable
$!
refers to theException
object that is being handled, but a better alternative is to specify a name in the clause itself. - pg 160: To define a catch-all
rescue
clause that handles any exception not handled by previous clauses, userescue Exception => ex
as the last clause. - pg 161: When the
retry
statement is used in arescue
clause, it reruns the block of code to which therescue
is attached. - pg 162: Putting code in an
else
clause differs from appending it to the end of thebegin
clause in that any exceptions raised in it are not handled by therescue
statements. - pg 163: An
ensure
clause can cancel exception propagation by raising a new exception, or executing a control statement likereturn
,break
, ornext
. - pg 163: If the body of a
begin
statement includes areturn
statement, then if theensure
clause has areturn
statement of its own, it changes the return value of the method. - pg 164: The
rescue
,else
, andensure
keywords can be used as clauses of adef
statement, aclass
statement, or amodule
statement. - pg 165:
rescue
can be used as a statement modifier, but must be used alone, with no exception class names and no variable names. - pg 166: The
at_exit
method ofKernel
allows registering blocks of code to execute just before the interpreter exits, where the block registered first is executed last. - pg 167: The
value
method of aThread
object returns the value returned by the associated block, and the caller will block until it becomes available. - pg 168: While arguments to the first call of
resume
become block parameters, afterward arguments toresume
become the return value ofFiber.yield
, and vice versa. - pg 171: Avoid using the additional features of fibers found in the
fiber
module, as they are so powerful that misusing them can crash the VM. - pg 172: Continuations were part of the core platform in 1.8 but have been replaced by fibers in 1.9, and should now be considered a curiosity.
- pg 176: Blocks and methods are not objects that Ruby can manipulate, but they can be represented by instances of
Proc
andMethod
, respectively. - pg 178: To return more than one value, separate the values by commas and explicitly use
return
, or create an array of values explicitly without usingreturn
. - pg 179: Singleton methods are prohibited on
Symbol
andNumeric
objects, because Ruby treatsFixnum
andSymbol
values as immediate values and not object references. - pg 180: The
undef
statement cannot be used to undefine a singleton method in the way thatdef
can be used to define such a method. - pg 180: Methods that end with
?
are called predicates, and are not required to returntrue
orfalse
. - pg 181: Methods that end with
!
should be used with caution, and are not required to be mutators. - pg 181: Operator methods
[]
and[]=
are special because they can be invoked with any number of arguments, and for[]=
, the last argument is the value assigned. - pg 182: The keyword
alias
lets a Ruby method have two different names, but method overloading is not permitted. - pg 183: Omitting the parentheses in method invocations gives the illusion of property access.
- pg 184: When you do use parentheses in a method invocation, the opening parenthesis must immediately follow the method name with no intervening space.
- pg 184: To reduce confusion, always use parentheses around a method invocation if any of the arguments use parentheses for expression grouping.
- pg 186: Argument defaults don’t need to be constants, and can refer to instance variables and to previous parameters in the parameter list.
- pg 186: Ruby 1.9 allows ordinary parameters to appear after parameters with defaults, but all parameters with defaults must be adjacent in the parameter list.
- pg 187: In Ruby 1.9, a parameter with
*
must appear after any parameters with defaults specified, but it may be followed by additional ordinary parameters. - pg 187: In Ruby 1.9, enumerators are splattable objects and can be used with
*
. - pg 189: To better support hashes for named arguments, Ruby allows you to omit the curly braces around a hash literal that is the last argument; this is called a bare hash.
- pg 189: If you omit the parentheses in a method call, then you must omit the curly braces of the hash, or else Ruby thinks you’re passing a block to the method.
- pg 190: Block arguments prefixed with
&
must be the last objects in a method definition. - pg 191: Even if a block has been converted to a
Proc
object and passed as an argument, it can still be invoked as an anonymous block usingyield
. - pg 191: If you find yourself using two identical blocks, create a
Proc
to represent the block, and use the singleProc
object twice. - pg 192: You can use
&
before any object with ato_proc
method, such asMethod
orSymbol
. - pg 192: The
to_proc
method ofSymbol
returns aProc
object that invokes the named method of its first argument, and passes the remaining arguments as parameters. - pg 192: While procs have block-like behavior and lambdas have method-like behavior, both are instances of the class
Proc
. - pg 193: All
Proc
objects have acall
method that, when invoked, runs the contained by the block from which the proc was created. - pg 193: If
Proc.new
is invoked without a block within a method that does have an associated block, then it returns a proc representing that block. - pg 195: A lambda literal argument list requires parentheses if it includes a semicolon and block-local variable names, and there must be no preceding space.
- pg 195: Lambda literals create
Proc
objects, so you must precede the definition with&
to pass one to where a block is expected, but regular block syntax is simpler. - pg 196: Instead of invoking
call
, Ruby 1.9 allows you to invoke aProc
using parentheses prefixed with a period, like the method name is missing. - pg 196: Only if a proc has a
*
-prefixed final argument, itsarity
method returns a negative numbern
, where the number of required arguments is~n
or-n-1
. - pg 197: The
==
method only returnstrue
if oneProc
is a clone or duplicate of the other. - pg 197: Calling a proc is like yielding to a block, whereas calling a lambda is like invoking a method; you can test if a
Proc
object is a lambda by calling itslambda?
method. - pg 198: If a proc executes a
return
statement after its lexically enclosing method has already returned, it raises aLocalJumpError
, so omit thereturn
or use a lambda instead. - pg 199: It never makes sense to have a top-level
break
statement in a proc created byProc.new
, asnew
is the iterator thatbreak
returns from. - pg 199: A lambda is method-like; if
break
is used without an enclosing loop or iteration, it acts just likereturn
. - pg 200: A proc uses yield semantics to assign arguments, which is similar to parallel assignment and is flexible, while a lambda uses invocation semantics, which is inflexible.
- pg 202: If a method returns more than one closure, pay attention to the variables they use, as it’s easy to introduce bugs if they are unintentionally sharing variables, or state.
- pg 203: The
Kernel.binding
method returns aBinding
object that represents the bindings in effect at whatever point you call it. - pg 203: Invoking a
Method
object is less efficient than invoking it directly. - pg 204: To use a
Method
where a trueProc
is required, call itsto_proc
method, or prefix the method object with&
as shorthand. - pg 204: An
UnboundMethod
cannot be invoked and does not define acall
method; you must first convert it to aMethod
object usingbind
.
- pg 215: The
class
keyword creates a new constant to refer to the class, which is why all class names must begin with a capital letter. - pg 216: The
initialize
method is automatically made private, so an object can callinitialize
on itself, but you cannot explicitly callinitialize
on an object. - pg 218: Assignment expressions only invoke a setter method when used with an object, so using a setter without
self
in an instance method creates a new local variable. - pg 218: The
attr_reader
andattr_writer
methods create getters and setters respectively, whileattr_accessor
creates both. - pg 219: The getter and setter methods defined with
attr_reader
orattr_accessor
are just as fast as hardcoded ones. - pg 221: If a binary operator of a class expects an argument of a different type, and the operator is called on that different type, the
coerce
method can reverse the operand order. - pg 223: Duck typing should not be supported in
==
oreql?
methods, which should returnfalse
instead of raisingNoMethodException
if accessors are missing. - pg 224: A
==
method should be defined in terms of==
operators, and aneql?
method should be defined in terms ofeql?
methods. - pg 224: A good general purpose hash function is to start with the value
17
, and multiply that value by37
before a new variable’s hash is added. - pg 225: Ideally the
==
and<=>
operator should have consistent definitions of equality, but it is not required. - pg 226: When defining a mutator method, add
!
to the end if there is a non-mutating version of the same method. - pg 226:
Struct
is a class that creates other classes, with read and write accessors, a==
operator andto_s
methods, and other useful methods. - pg 227: If you assign an unnamed class object to a constant, the name of that constant becomes the name of a class.
- pg 228: When defining class methods, you can use
self
instead of the class name, which is slightly less clear but applies the DRY principle. - pg 230: If constants of a class refer to instances of the class, they must be defined after the
initialize
method of the class. - pg 232: Class instance variables are just instance variables, so you can use
attr_reader
andattr_writer
to define them in the context defined by the syntaxclass << self
. - pg 232: A private method
m
must be invoked in a functional style asm
, and not aso.m
or evenself.m
, but a protected method can be explicitly invoked on any class instance. - pg 233: One object can call another’s protected method if it is defined in a class that both objects are instantiated from, or are subclasses of.
- pg 233: The
public
,protected
, andprivate
methods, when invoked with the names of one or more methods, alter the visibility of the named methods. - pg 234: Use
private_class_method
to make a class method private; you can use this to make the new method private if you define factory methods. - pg 235: You can also subclass a struct-based class in order to add methods other than the automatically generated ones.
- pg 238: Private methods cannot be invoked from outside the class that defines them, but they are inherited by subclasses, which can invoke them and override them.
- pg 238: To avoid accidentally overriding a private method of a class you didn’t write, extend its functionality by encapsulating and delegating to it.
- pg 239: Because a bare
super
has a special meaning, you must use a pair of empty parentheses to pass zero arguments from a method that has one or more arguments. - pg 239: When invoking a class method with an explicit receiver, always invoke the class method on the class that defines it for clarity.
- pg 240: Instance variables are unrelated with inheritance, so a subclass cannot "shadow" an instance variable in a superclass, and is another reason to prefer encapsulation and delegation.
- pg 241: A subclass can alter a class variable defined and used by a superclass, but class instance variables are not inherited, and so this is a strong reason to prefer them.
- pg 241: Constants are looked up in the lexical scope of where they are used before the inheritance hierarchy, and so inherited methods will not find a redefined constant in a subclass.
- pg 242: The
Class#new
method is inherited by all class objects and is used to initialize new instances, whileClass::new
can be used to create new classes. - pg 244: The
initialize_copy
method can rely ondup
orclone
to perform a deep copy. - pg 244: A class that defines an enumerated type can use
private_class_method
on:new
and:allocate
, andprivate
on:dup
and:clone
to prevent unwanted instances. - pg 246: Note that if you have disabled the
clone
anddup
methods for a class, you must implement custom marshalling methods, or else a copy can still be made. - pg 246: Add
require 'singleton'
and theninclude Singleton
into your class to properly implement a singleton using the techniques described before. - pg 248:
Class
is a subclass ofModule
; both classes and modules can be used as namespaces, but classes cannot be used in mixins as modules can. - pg 249: A class or module within another has no special access to the class or module it is nested within.
- pg 250: Nesting classes keeps the namespace tidy, but does not actually make the nested class private in any way.
- pg 250: While
include
is usually used as if it were a language keyword, it is a private instance method ofModule
, implicitly invoked onself
. - pg 251: You can include one module within another, and while every class is a module, the arguments to
include
must be modules, not classes. - pg 251: To make instance methods of a specified module into singleton methods of the receiver object, use
Object.extend
. - pg 252: When defining a module function, avoid using
self
, because the value ofself
will depend on how it is invoked. - pg 253: Ruby 1.9 defines a
require_relative
method, which works likerequire
but ignores the load path and searches relative to the directory from which the invoking code was loaded. - pg 254: The current working directory
.
in a load path is the directory from which a user invokes a Ruby program, and not the directory in which the program is installed. - pg 256: The
autoload
function allows lazy-loading a library when a given constant, typically a class or module name, is first encountered. - pg 257: Singleton methods of an object are not defined by an object, but must be associated with a class; this is called the eigenclass, singleton class, or metaclass.
- pg 258: When you open the eigenclass of an object using
class <<
,self
refers to the eigenclass object. - pg 258: When performing a method lookup, Ruby searches the instance methods of any modules included by a class before searching the superclass.
- pg 260: Invoking a class method performs a standard method lookup on the object that represents the class, and so proceeds through
Class
,Module
,Object
, andKernel
. - pg 261: The eigenclass of a class is the eigenclass of its superclass, and to find a method, Ruby first checks the singleton methods of eigenclasses before looking for instance methods.
- pg 262: Constants defined in enclosing modules are found before those in included modules, and modules included by a class are searched before the superclass of the class.