the-ruby-programming-language.markdown
January 15, 2014 · View on GitHub
The Ruby Programming Language
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!
Chapter 1: Introduction
- 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:
RegexpandRangeobjects define===for membership, which is what thecasestatement 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
nilis 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,putsends with a newline, and its alternativepconverts objects to strings usinginspectwhich 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 rubygemsin your programs that use gems. - pg 15: You can use the
gemmethod before callingrequireto load a specific version of a gem other than the most recent one.
Chapter 2: The Structure and Execution of Ruby Programs
- pg 26: Ruby has no equivalent of
/* */that allows embedding a comment in code. - pg 27: Embedded documents defined with
=beginand=endallow defining multi-line comments easily, and are usually intended for use by a source code postprocessing tool. - pg 27: The
rdoctool 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, andObjectclasses, 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
doandend. - pg 36: The
requiremethod 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_externalandEncoding.default_internal, respectively.
Chapter 3: Datatypes and Objects
- 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
0xor0Xare hexadecimal, ones starting with0bor0Bare binary, and ones starting with0and 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
ZeroDivisionErrorto 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
0like 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
%qfollows single-quoted rules, and the sequence%Qfollows double-quoted rules. - pg 51: A string literal formed with
%qor%Qcontinues until a matching unescaped delimiter is found, and the delimiters(,[,<pair with),], and>, respectively. - pg 53: Text using sequence
%xor 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_chariterator may be more efficient than using the[]operator, and complements theeach_byteandeach_lineiterators. - 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
\uescapes are always encoded in UTF-8. - pg 60: The
ASCII-8BITencoding in Ruby 1.9 has the aliasBINARYand is equivalent to the encoding in Ruby 1.8, while theUS-ASCIIencoding is true 7-bit ASCII. - pg 61: The
force_encodingmethod does not perform validation, which is done by thevalid_encoding?method. - pg 62: If a string you call
encodeon 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_charmapand pass the resulting string to theEncoding.findfactory method. - pg 64: Attempting to read an index with
index >= sizeorindex < -sizereturnsnilas opposed to raising an exception. - pg 64: Assigning an element to an index beyond the end of the array automatically extends the array with
nilelements. - pg 64: The
%wand%Wsequences express array literals whose elements are strings without spaces, and follow the same rules as%qand%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 thehashmethod 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
rehashmethod 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
succmethod is called a discrete range, and can be iterated usingeach,step, andEnumerablemethods. - 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
succto 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
%ssequence defines a literal syntax for symbols the same way that%qand%Qdoes for strings. - pg 71: The
internandto_symmethods convert strings to symbols, and theto_sandid2namemethods convert back. - pg 72: There is no
Booleanclass in Ruby, andTrueClassandFalseClassboth haveObjectas their superclass. - pg 73: The
newmethod of theClassclass allocates memory to hold the new object, and then initializes its state by invoking itsinitializemethod. - pg 74: By default the
Objectclass implements methodhashby returning the object’s ID, which is also returned by theobject_idmethod. - 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 aFixnumandFloat. - 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
Comparablemixin defines the operators<,<=,==,>=, and>in terms of<=>, as well as thebetween?operator. - pg 79: The
to_s,to_i,to_f, andto_amethods allow explicit conversion toString,Integer,Float, andArray, respectively. - pg 80: The default
inspectmethod simply callsto_s, but should be overridden to return a representation useful for Ruby developers and not end users. - pg 81: The
Kernelmodule 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
coercemethod 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
cloneanddupreturn a shallow copy, but if aninitialize_copymethod is provided, they allocate a new, empty instance and call that. - pg 83: The
clonemethod copies both the frozen and tainted state of an object, whereasduponly copies tainted state, andclonealso copies any singleton methods, whereasdupdoes not. - pg 84: Once an instance of a class is frozen, it cannot be thawed, and a copy created with
clonewill also be frozen, while a copy created withdupwill 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.
Chapter 4: Expressions and Operators
- 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
NameErrorif 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
Objectclass, 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
Kernelare 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,
superpasses 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 notnilorfalse, 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_amethod 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
joinmethod and passing that string as an argument. - pg 104: The
String,Array, andIOclasses define<<as the append operator, as do other "appendable" classes likeQueueandLogger. - 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
Moduleclass, which is the superclass ofClass, definesA < Bastrueif classAis a subclass or descendant of classB. - pg 106: The
Modulecomparison operators returnnilbetween classes where neither one is a subclass of the other. - pg 106:
Stringdefines the pattern matching operator~=so that it expects aRegExpas its argument, andRegExpdefines 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-nilvalue in a series of alternatives. - pg 108: The
and,or, andnotoperators are low precedence versions of&&,||, and!, and are even lower than the assignment operator. - pg 109: The
andandoroperators have the same precedence, withnotslightly 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 remainstrueuntil 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 returnsnilgiven an undefined variable or method, or if the operand is an expression that usesyieldorsuperin 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.
Chapter 5: Statements and Control Structures
- 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
ifas a statement modifier does not allow any kind ofelseclause. - pg 124: Comma separated expressions in the
whenclause act like the||operator, as if any expression evaluates totrue, its body is executed. - pg 126: If a
whenclause contains multiple expressions separated by commas, the===operator is invoked on each one. - pg 126: Expressions in
whenclauses do not have to be compile-time constants, so no lookup table is used, and performance is comparable to anifstatement andelsifclauses. - pg 128: When using
whileoruntilas a modifier, if the loop body is between thebeginandendkeywords then the body runs at least once like ado/whileloop, but this usage is discouraged. - pg 129: The
for/inloop calls theeachmethod of the specified object. - pg 129: A loop variable in a
forloop 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
yieldstatement, and do not need to serve an iteration or looping function. - pg 132: In general,
n.timesis equivalent to0.upto(n-1). - pg 132: The
Enumerablemodule implements the methodeach_with_index, and the rhymingcollect(also calledmap),select,reject, andinjectmethods on top of theeachmethod. - 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_enumandenum_formethods 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_enumorenum_for. - pg 137: In Ruby 1.9, enumerators are also external iterators, where the client can control iteration using the
nextmethod untilStopIterationis raised. - pg 138: The
Kernel.loopmethod in Ruby 1.9 includes an implicitrescueclause and exits cleanly whenStopIterationis raised. - pg 138: In general, if new invocations of each on the underlying
Enumerableobject do not restart iteration from the beginning, then callingrewindwill 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
returninside a block causes the containing method to return; usenextinstead, 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
returnstatement 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
breakstatement 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
breakstatement 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
redostatement 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
redostatement is uncommon, but is useful to recover from errors when prompting a user for input. - pg 153: Unlike a labeled break,
throwandcatchare not restricted to loops, and can propagate up the call stack to cause a block in an invoking thread to exit. - pg 154: If
throwis called, by default the return value of the correspondingcatchisnil, unless you pass a second argument tothrow. - pg 155: The
StandardErrorexception type is for recoverable errors; all other subclasses ofExceptionrepresent more serious ones that programs do not attempt to recover. - pg 157:
raisewith no arguments creates aRuntimeError, whileraisewith a single string argument creates aRuntimeErrorwith that as its message. - pg 157: If the first argument to
raiseis an object with anexceptionmethod, it is called and its return value is raised;Exceptiondefines such a method. - pg 158: The global variable
$!refers to theExceptionobject that is being handled, but a better alternative is to specify a name in the clause itself. - pg 160: To define a catch-all
rescueclause that handles any exception not handled by previous clauses, userescue Exception => exas the last clause. - pg 161: When the
retrystatement is used in arescueclause, it reruns the block of code to which therescueis attached. - pg 162: Putting code in an
elseclause differs from appending it to the end of thebeginclause in that any exceptions raised in it are not handled by therescuestatements. - pg 163: An
ensureclause can cancel exception propagation by raising a new exception, or executing a control statement likereturn,break, ornext. - pg 163: If the body of a
beginstatement includes areturnstatement, then if theensureclause has areturnstatement of its own, it changes the return value of the method. - pg 164: The
rescue,else, andensurekeywords can be used as clauses of adefstatement, aclassstatement, or amodulestatement. - pg 165:
rescuecan be used as a statement modifier, but must be used alone, with no exception class names and no variable names. - pg 166: The
at_exitmethod ofKernelallows registering blocks of code to execute just before the interpreter exits, where the block registered first is executed last. - pg 167: The
valuemethod of aThreadobject 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
resumebecome block parameters, afterward arguments toresumebecome the return value ofFiber.yield, and vice versa. - pg 171: Avoid using the additional features of fibers found in the
fibermodule, 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.
Chapter 6: Methods, Procs, Lambdas, and Closures
- pg 176: Blocks and methods are not objects that Ruby can manipulate, but they can be represented by instances of
ProcandMethod, 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
SymbolandNumericobjects, because Ruby treatsFixnumandSymbolvalues as immediate values and not object references. - pg 180: The
undefstatement cannot be used to undefine a singleton method in the way thatdefcan be used to define such a method. - pg 180: Methods that end with
?are called predicates, and are not required to returntrueorfalse. - 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
aliaslets 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
Procobject 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
Procto represent the block, and use the singleProcobject twice. - pg 192: You can use
&before any object with ato_procmethod, such asMethodorSymbol. - pg 192: The
to_procmethod ofSymbolreturns aProcobject 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
Procobjects have acallmethod that, when invoked, runs the contained by the block from which the proc was created. - pg 193: If
Proc.newis 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
Procobjects, 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 aProcusing parentheses prefixed with a period, like the method name is missing. - pg 196: Only if a proc has a
*-prefixed final argument, itsaritymethod returns a negative numbern, where the number of required arguments is~nor-n-1. - pg 197: The
==method only returnstrueif oneProcis 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
Procobject is a lambda by calling itslambda?method. - pg 198: If a proc executes a
returnstatement after its lexically enclosing method has already returned, it raises aLocalJumpError, so omit thereturnor use a lambda instead. - pg 199: It never makes sense to have a top-level
breakstatement in a proc created byProc.new, asnewis the iterator thatbreakreturns from. - pg 199: A lambda is method-like; if
breakis 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.bindingmethod returns aBindingobject that represents the bindings in effect at whatever point you call it. - pg 203: Invoking a
Methodobject is less efficient than invoking it directly. - pg 204: To use a
Methodwhere a trueProcis required, call itsto_procmethod, or prefix the method object with&as shorthand. - pg 204: An
UnboundMethodcannot be invoked and does not define acallmethod; you must first convert it to aMethodobject usingbind.
Chapter 7: Classes and Modules
- pg 215: The
classkeyword creates a new constant to refer to the class, which is why all class names must begin with a capital letter. - pg 216: The
initializemethod is automatically made private, so an object can callinitializeon itself, but you cannot explicitly callinitializeon an object. - pg 218: Assignment expressions only invoke a setter method when used with an object, so using a setter without
selfin an instance method creates a new local variable. - pg 218: The
attr_readerandattr_writermethods create getters and setters respectively, whileattr_accessorcreates both. - pg 219: The getter and setter methods defined with
attr_readerorattr_accessorare 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
coercemethod can reverse the operand order. - pg 223: Duck typing should not be supported in
==oreql?methods, which should returnfalseinstead of raisingNoMethodExceptionif 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 by37before 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:
Structis a class that creates other classes, with read and write accessors, a==operator andto_smethods, 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
selfinstead 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
initializemethod of the class. - pg 232: Class instance variables are just instance variables, so you can use
attr_readerandattr_writerto define them in the context defined by the syntaxclass << self. - pg 232: A private method
mmust be invoked in a functional style asm, and not aso.mor 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, andprivatemethods, when invoked with the names of one or more methods, alter the visibility of the named methods. - pg 234: Use
private_class_methodto 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
superhas 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#newmethod is inherited by all class objects and is used to initialize new instances, whileClass::newcan be used to create new classes. - pg 244: The
initialize_copymethod can rely onduporcloneto perform a deep copy. - pg 244: A class that defines an enumerated type can use
private_class_methodon:newand:allocate, andprivateon:dupand:cloneto prevent unwanted instances. - pg 246: Note that if you have disabled the
cloneanddupmethods for a class, you must implement custom marshalling methods, or else a copy can still be made. - pg 246: Add
require 'singleton'and theninclude Singletoninto your class to properly implement a singleton using the techniques described before. - pg 248:
Classis 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
includeis 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
includemust 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 ofselfwill depend on how it is invoked. - pg 253: Ruby 1.9 defines a
require_relativemethod, which works likerequirebut 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
autoloadfunction 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 <<,selfrefers 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.