As always, a few errors slipped past us despite our best efforts. This is a list of all the known errors in The Ruby Way, 3rd Edition, and their corrections. Page numbers are accurate for the print and PDF versions of the book.
should instead readabort "#{temp} is not a valid number." if temp !~ /\A-?\d+\Z/
if temp !~ /\A-?\d+\Z/ abort "#{temp} is not a valid number." end
The exclamation point as a prefixshould instead read
The exclamation point as a suffix
statement1 if y == 3
should instead read statement1 if y == 37.0
.
loop 3 is merely an indirect referenceshould instead read
loop 5 is merely an indirect reference
we are allowed to use anshould instead readelse
clause after all therescue
clauses
we can use anotherThe following code sample should instead contain this code:rescue
clause to catch any errors uncaught by previousrescue
clauses
begin # Error-prone code... rescue FirstErrorClass # ... rescue SecondErrorClass # ... rescue # Other StandardError exceptions... end
_idtoref
should instead read _id2ref
.
s1 = str.ljust(13) # "Moby-Dick"
should instead read s1 = str.ljust(13) # "Moby-Dick "
.
should instead read:/ghi\Z/ =~ string # 8 /\Aabc/ =~ str2 # 8
/ghi\Z/ =~ string # 8 /ghi\Z/ =~ str2 # 8
Prime.new
should instead read Prime.instance
.
The method member?
is an alias.
should instead read:
Theinclude?
method is equivalent toto_a.include?
, and the methodmember?
is an alias.
Another method,cover?
, checks for a different kind of inclusion—whether the value in question falls between the start and end of the range.
Once again, beware of string ranges:should instead read
Beware when using cover?
on string ranges:
The code sample should also read as follows:
s1 = "2".."5" str = "28" s1.include?(str) # false (as expected) s1.cover?(str) # true (misleading!)
These are typically based on the UNIX epoch and therefore cannot represent times before 1970.should instead read
These are typically based on the UNIX epoch, and indeed converting aTime
before 1970 usingto_i
will produce a negative number
calendar
function should instead be defined by this code:
def calendar(month, year)
num_days = month_days(month, year)
list = (1..num_days).to_a
first_day = Time.mktime(year, month, 1)
first_day.wday.times { list.unshift(nil) }
list << nil until (list.size % 7).zero?
list.each_slice(7).to_a
end
if d < e # false
should instead read
if (d <=> e) < 0 # true
Bear in mind thatIn addition, the last line of the final code sample, which reads+
and even+=
will create a new array object, whileconcat
and<<
methods will modify the existing array. Also bear in mind that<<
is unique in that it will add only a single new element (which may itself be an array):
a = a.concat(b) # [1,2,3,4]
should instead read
a.concat(b) # [1, 2, 3, 4]
# ["green","blue","red"]
should instead read
# ["blue", "green", "red"]
should instead readwith_index
(mixed in fromEnumerable
)
with_index
(a method on theEnumerable::Enumerator
object returned byeach
)
class ZeroArray < Array
should instead read:
class ZeroArray < Array
# When reading a value, return 0 for missing indexes
def [](x)
x > size ? 0 : super(x)
end
# When setting a value, fill missing indexes with zero
def []=(index, value)
(size...index).each{|i| self[i] = 0 }
super(index, value)
end
end
num = ZeroArray.new
num[1] = 1 # => [0, 1]
num[2] = 4 # => [0, 1, 4]
num[5] = 25 # => [0, 1, 4, 0, 0, 25]
(Thec1 = {"flat" => 3,"curved" => 2} # For a1 and b1, there must be an even number of elements.
{"flat", 3, "curved", 2}
Hash creation syntax was removed in Ruby
1.9.)
should instead readHash
has class methods[]
and[]=
Hash
has instance methods[]
and[]=
There is no predictable way to tell which one will be usedshould instead read
The last-inserted key will be used as the inverted value
An alias forshould instead readmerge
isupdate
Themerge
method creates a new hash, while themerge!
method changes the receiver in place. Theupdate
method is an alias formerge!
The inject
method comes to Ruby via Smalltalk.
should instead read
TheAdditionally, the lineinject
method (also aliased asreduce
) comes to Ruby via Smalltalk.
Obviously, this is equivalent to the following piece of codeand the following code example should instead read:
Instead of passing a block, it is also possible to pass a symbol representing the method that should be used on each item. The previous example could instead have been written this way:Or even written without usingsum = nums.inject(:+)
inject
, like this:sum = 0 nums.each {|n| sum += n }
hands << dealer.next } # not actually how a human deals
should instead read
hands << dealer.next # not actually how a human deals
acc[n] += 1 } # Better
should instead read
acc[n] += 1 # Better
The section beginning "The reduce
method" and ending "it’s impossible to specify both a binary operator symbol and a block together" should be removed entirely, since this functionality was covered in Section 8.3.1.
In addition, the line of code
arr1 = hash.drop(2) # [[4,8], [5,10], [7 => 14]]
should instead read
arr1 = hash.drop(2) # [[4, 8], [5, 10], [7, 14]]
Finally, the line of code
arr2 = hash.take_while {|k,v| v <= 8 } # [[5,10], [7 => 14]]
should instead read
arr2 = hash.drop_while {|k,v| v <= 8 } # [[5, 10], [7, 14]]
The unary minusshould instead read
The minus method
The corresponding instance methods in the Array
class are called unpush and shift, respectively.
should instead read
The corresponding instance methods onArray
are eitherpush
andshift
, orunshift
andpop
. The first pair adds to the end of the array and removes from the front, while the second pair adds to the front of the array and removes from the end.
paren_match
function will raise an exception instead of returning false
as it should. To resolve this, change this line of code
top = stack.peek
to instead be these two lines
top = stack.peek
return false if top.nil?
$defout
and STDOUT
should all instead read $stdout
.
Be aware thatshould instead readFileUtils
used to mix functionality directly into theFile
class by reopening it; now these methods stay in their own module.
Most of the functionality in theIn addition, the textFileUtils
module is named after the UNIX utility that provides the same function, as inmv
andcp
.
Theshould instead readcopy
method will copy a file to a new name or location. It has an optional flag parameter to write error messages to standard error. The UNIX-like namecp
is an alias:
TheLastly, the textcp
method (aliasedcopy
) will copy a file to a new name or location. The related methodcp_r
will copy directories recursively.
A file may be moved with theshould instead readmove
method (aliasmv
). Like copy, it also has an optional verbose flag:
A file or directory may be moved with themv
method, which is aliased asmove
.
arr.size
should instead read str.size
. The sentence beginning "Obviously because" should instead begin "Because".
"ABC"
should all instead read "ABC\n"
.
In Ruby code, we can do this by using the FileUtils.makedirs
method:
should instead read
In Ruby code, we can do this by using theIn the code sample below, the textFileUtils.mkdir_p
method, also aliased asmkpath
.
FileUtils.mkpath
should instead read FileUtils.mkdir_p
.
Note that bothPathname#rmtree
andFileUtils.rm_r
delete files that lack write permissions, making them equivalent to the shell commandrm -rf
. The similarly-named methodFileUtils.rm_rf
instead suppresses anyStandardError
exceptions raised while the removal is running.
CSV.open('data.csv', 'r') do |row|
should instead read CSV.open('data.csv', 'r').each do |row|
.
Proc
and a lambda
should instead contain this code:
def philippe_proc
Proc.new do
return "Too soon, Philippe!"
end.call
"Good morning, everyone."
end
def philippe_lambda
lambda do
return "Too soon, Philippe!"
end.call
"Good morning, everyone."
end
p philippe_proc # => "Too soon, Philippe!"
p philippe_lambda # => "Good morning, everyone."
In AOP, programmers to deal withshould instead read
In AOP, programmers deal with
undef_method
will literally cause the method to be undefined (removing it from superclasses as well)
the text should read
At the end of the accompanying code sample, the codeundef_method
will force aNoMethodError
if that method is called later (preventing that method from being found in superclasses or modules)
should instead readx = Child.new x.alpha # parent alpha x.beta # Error!
Child.new.alpha # parent alpha Child.new.beta # Error! Parent.new.beta # parent beta
Object#method_missing
and "the method_missing
method defined in class Object
" should instead read BasicObject#method_missing
.
~
." should be checked for the column 3.Process
" should both be checked in column 3.
At the time of this writing, Ruby/Tk is based on the most recent release, Tk 8.5.should instead read
Ruby/Tk supports Tk 8.4, 8.5, and 8.6, which is the most recent release of Tk at the time of this writing.
Qt is distributed via dual license—either the GPL or a purchased commercial license for proprietary work.should instead read
Qt is distributed via dual license—either LGPLv3 or a purchased commercial license for proprietary work.
Here is an example of thread-local data in action:should instead read
(Technically, these are not thread-local but fiber-local variables. We'll talk about the cases where this matters soon, in section 13.3.) Here is an example of thread-local data in action:
Section 13.3.1 Fiber-local variablesBack in section 13.1.2, we mentioned that the
Thread
methods[]
and[]=
manipulate fiber-local variables instead of true thread-local variables. If a thread does not explicitly run additional fibers, those methods provide variables that are functionally identical to thread-local variables.However, in a thread that executes multiple fibers there is another pair of methods providing access to variables that are shared across all fibers on a single
Thread
,thread_variable_get
andthread_variable_set
. Any time you need to set a variable inside one fiber and access it from another fiber that is run on the same thread, you will need to usethread_variable_set
andthread_variable_get
instead. For more discussion of the differences between thread-local and fiber-local variables, see the Ruby API documentation forThread#[]
andThread#thread_variable_get
.
In the second text paragraph, kernel
should instead read Kernel
.
The line alias old_execute '
should instead read alias old_execute `
.
In addition, the line def '(cmd)
should instead read def `(cmd)
.
(You would use a semicolon rather than a colon on Windows.)should instead read
(We use File::PATH_SEPARATOR
for compatibility across operating systems—the separator is a colon on UNIX, but a semicolon on Windows.)
In addition, the line dirs = mypath.split(":")
should read dirs = mypath.split(File::PATH_SEPARATOR)
.
Second, an environment variable set by a child is not propagated back up to the parent:should instead read
After the fork, environment changes are not shared—any changes made in either the parent or child will not apply to the other.Finally, the line
There is a consequence of the fact that parent processes don’t know about their children’s variables. Because a Ruby program is typically run in a subshell, anyshould read
A direct application of this principle is the way that a Ruby program (as a child process) cannot change the environment variables of the shell it was run from (a parent process). Any
open sans font by ascender fonts. icons by the noun project. site design by saliorhg.