SlideShare una empresa de Scribd logo
1 de 32
Descargar para leer sin conexión
Ruby
GotchasLast edited 2014-11-26
by Dave Aronson,
T. Rex of Codosaurus, LLC
Though "engineered to
maximize programmer
happiness", with the
"principle of least surprise",
Ruby still has gotchas.
This presentation will
proceed from newbie trivial
gotchas, to more advanced
and confusing gotchas.
We = 2
class Fixnum
def rb; self; end
end
We <3 .rb
=> true
But = 3
still = 1
perfect = 4
But - still .rb < perfect
=> true
Ruby can be surprising!
Don't quote me on this, but . . . .
x = 3
puts 'x = #{x}nx'
x = #{x}nx
puts "x = #{x}nx"
x = 3
x
String interpolation
(including special chars
like n) fails with 'single'
quotes -- it requires
"double" quotes.
(Just like in most
languages with string
interpolation.)
To avoid: use doubles
whenever practical.
Only two things are false
(falsey): false, and nil.
Everything else is true
(truthy), even 0 (false in C),
"" (false in JS), [], etc.
(Trips up people from C, JS,
etc. where some of these are
false.)
It's twue! It's twue!
true ? "true" : "false"
=> "true"
false ? "true" : "false"
=> "false"
nil ? "true" : "false"
=> "false"
1 ? "true" : "false"
=> "true"
0 ? "true" : "false"
=> "true"
"false"? "true" : "false"
=> "true"
"" ? "true" : "false"
=> "true"
[] ? "true" : "false"
=> "true"
Symbols != strings.
Even if same, printed.
Remember which one to
use for what (args).
Ideally, take either: "Be
liberal in what you accept,
and conservative in what
you send." (Postel's Law)
str = "string"
sym = :string
puts str
string
puts sym
string
str == sym
=> false
Hang him in effigy
(String him up, symbolically)
bash> irb-1.9
str = "string"
=> "string"
str[2]
=> "r"
# makes sense *now*
bash> irb-1.8
str = "string"
=> "string"
str[2]
=> 114
# ??? ascii code!
str[2..2]
=> "r"
# that's better!
str[2,1]
=> "r"
# works too....
String... or nothing!
FOO = 5
=> 5
FOO = 7
(irb):3: warning:
already initialized
constant FOO
=> 7
FOO
=> 7
Constants Aren't (Part 1/2)
(Initial uppercase means
constant, in Ruby.)
Try to change a constant.
Ooooh, you get a
WARNING! BFD.
Even freezing doesn't
work for Fixnums.
It does work for arrays
(sort of) and most other
objects . . . he said
foreshadowingly.
FOO
=> 7
FOO.freeze
=> 7
FOO += 2
(irb):5: warning: already
initialized constant FOO
=> 9
FOO
=> 9
Constants Aren't (Part 2/2)
Some are more equal than others
Effectively:
== is the usual
(same value)
.eql? is value and class
(1 is Fixnum, 1.0 is Float)
.equal? is same object
It's actually much hairier;
see docs on class Object
1 == 1.0
=> true
1.eql? 1.0
=> false
a = "foo"
b = "foo"
a == b
=> true
a.eql? b
=> true
a.equal? b
=> false
a.equal? a
=> true
Effectively:
=== is "case equality", as in
case statements. A better name
(IMHO) might be ".describes?",
or overload ".includes?"!
Again, it's actually much hairier;
see the docs on class Object.
Gets people from languages
where === is identity, or same
value and class.
=== != ==!
1 === 1
=> true
Fixnum === 1
=> true
1 === Fixnum
=> false
Class === Class
Object === Object
Class === Object
Object === Class
=> all true
Fixnum === Fixnum
=> false
(1..3) === 2
=> true
2 === (1..3)
=> false
&& has higher precedence
than =, so
x = true && false
means
x = (true && false)
and has lower precedence, so
x = true and false
means
(x = true) and false
Ruby Style Guide: Use && / ||
for boolean expressions, [use]
and / or for control flow.
x = true && false
=> false
x
=> false
# OK so far, but:
x = true and false
=> false
x
=> true
Return value is false
but variable is true!
Why the mismatch?!
and != &&
|| has higher precedence
than =, so
x = false || true
means
x = (false || true)
or has lower precedence so
x = false or true
means
(x = false) or true
Also, && is higher than ||,
but and and or are equal, so
they are evaluated left-to-right!
x = false || true
=> true
x
=> true
# OK so far, but:
x = false or true
=> true
x
=> false
Return value is true
but variable is false!
Why the mismatch?!
or != ||
Whitespace-insensitive?
NOT ALWAYS!
With multiple args:
- No parens, no problem.
- Parens w/o space, OK.
- Parens and space, NO!
Parser thinks it's an
expression, as one arg,
but (1, 2) is not a valid
Ruby expression!
(All work fine w/ 1 arg.)
def method(arg1, arg2); end
method 1, 2
=> nil
method(1, 2)
=> nil
method (1, 2)
syntax error, unexpected
',', expecting ')'
method (1, 2)
^
Don't be so sensitive! (Part 1/4)
def method; 42; end
num = 21
method/num
=> 2
method / num
=> 2
method/ num
=> 2
method /num
SyntaxError:
unterminated regexp
"method /num" is an
unended regex or string!
Ruby thinks you might be
giving an argument to
method meth.
General principle: use
BALANCED whitespace;
both sides or neither.
Don't be so sensitive! (Part 2/4)
"one -1" makes Ruby
think you might be giving
an argument (of -1) to
method one. (Same for
+1 . . . or even *1!)
Again: use BALANCED
whitespace; both sides or
neither.
def one
1
end
one - 1
=> 0
one-1
=> 0
one- 1
=> 0
one -1
ArgumentError: wrong number
of arguments (1 for 0)
Don't be so sensitive! (Part 3/4)
dbl = ->(x) { x * 2 }
=> #<Proc:... (lambda)>
dbl = ->x{ x * 2 }
=> #<Proc:... (lambda)>
dbl = -> x { x * 2 }
=> #<Proc:... (lambda)>
two = -> { 2 }
=> #<Proc:... (lambda)>
dbl = -> (x) { x * 2 }
syntax error, unexpected
tLPAREN_ARG, expecting
keyword_do_LAMBDA or tLAMBEG
two = -> () { 2 }
same syntax error
"Stabby" lambdas (1.9+)
Parentheses optional
Space before/after args
without parens, OK.
Space after parens, OK.
Again, space before
parens, NO!
UPDATE: Fixed in 2.0!
Don't be so sensitive! (Part 4/4)
class Foo
attr_reader :value
def initialize(v)
value = v
end
def set_val(v)
@value = v
end
end
f = Foo.new(3)
f.value
=> nil # not 3?!
f.set_val 5
=> 5
f.value
=> 5
'Ang onto yer @!
Naked value becomes a
temporary local variable!
Solution: remember the @! (Or
"self.".)
Gets people from Java/C++,
not so much Python (which
needs "self." too).
"You keep on using that variable. I don't
think it means what you think it means."
What the fillintheblank? We didn't
change Parent’s @@value before
checking it, nor Child’s at all!
. . . Or did we?
@@ variables are shared with
subclasses -- not just that they
exist, but the variables
themselves! Declaring Child’s
@@value changed Parent’s, and
inc’ing Parent’s changed Child’s.
IMHO, best just forget them.
class Parent
@@value = 6
def self.value
@@value
end
def self.inc_value
@@value += 1
end
end
class Child < Parent
@@value = 42
end
Parent.value
=> 42 # wtf?
Parent.inc_value
Child.value
=> 43 # wtf?!
Look out, it’s an @@!
class Parent
def initialize
puts "Parent init"
end
end
class NoInitChild < Parent
end
NoInitChild.new
Parent init
class NormalChild < Parent
def initialize
puts "NormalChild init"
end
end
NormalChild.new
"NormalChild init"
With init(ialize) or without it
class SuperChild < Parent
def initialize
puts "SuperChild"
super
puts "init"
end
end
SuperChild.new
SuperChild
Parent init
init
Parent's initialize runs
automagically only if child
has none. Else, parent's
must be called to run.
Superman vs. the Invisible Man
Child2.new.add 1, 2, 3, 5
ArgumentError: wrong
number of arguments (4
for 2)
Child2.new.add 1, 2
=> 3
Child4.new.add 1, 2, 3, 5
=> 11
super with no arg list
sends what caller got
super with explicit args
sends those args
to send NO args, use
empty parens: super()
class Parent
def add *args
args.inject :+
end
end
class Child2 < Parent
def add arg1, arg2
super arg1, arg2
end
end
class Child4 < Parent
def add a1, a2, a3, a4
super # no args!
end
end
When will it end? (Or start?)
str = "OnenTwonThree"
str =~ /^Two$/
=> 4
str =~ /ATwoZ/
=> nil
str =~ /AOne/
=> 0
str =~ /ThreeZ/
=> 8
In "standard" regexps:
^ is start and $ is end...
of the whole string.
Ruby’s regexes default to
multiline, so:
^ is start and $ is end...
of any line!
A is start and Z is end
of the whole string. (Or z
to include any newline…
which is another gotcha!)
[].any?
=> false
[1].any?
=> true
[:foo, :bar].any?
=> true
# ok so far, BUT:
[nil].any?
=> false
[false].any?
=> false
[false, nil].any?
=> false
.any? does not mean
“any elements?”!
With block: “do any
make the block true?”
Without: “are any truthy?”
Has implicit block:
{ |element| element }
getting .any?
Variables declared in blocks
passed to iterators (e.g.,
times or each) are undefined
at the top of each iteration!
Iterators call the block
repeatedly, so vars are out of
scope again after each call.
Built-in looping constructs (e.
g., while or for) are OK.
(Or declare vars before block.)
3.times do |loop_num|
sum ||= 0
sum += 1
puts sum
end
1
1
1
for loop_num in 1..3
sum ||= 0
sum += 1
puts sum
end
1
2
3
(Un)Def Leppard
arr = ["one", "two", "three"]
arr.freeze
arr << "four"
RuntimeError: can't modify
frozen Array
arr[0] = "eno"
RuntimeError: can't modify
frozen Array
arr[0].object_id
=> 1234567890
arr[0].reverse!
arr
=> ["eno", "two", "three"]
arr[0].object_id
=> 1234567890
Freezing an array (or a
hash) freezes it, not the
items it contains.
Strings can be modified
in place. This way, you
can modify a given slot in
a frozen Array of Strings.
Freeze (Ar)ray
Changing Fixnum to new
value means new object.
They can't be modified in
place! So, can’t modify a
frozen Array of Fixnums.
(Fixnums and Integers
have no bang-methods to
demo trying with.)
BTW: a Fixnum's object_id
is value * 2 + 1.
1 is 1 … and ever more shall be so!
arr = [1, 2, 3, 4]
arr.freeze
=> [1, 2, 3, 4]
arr << 5
RuntimeError: can't modify
frozen Array
arr[0] += 2
RuntimeError: can't modify
frozen Array
1.object_id
=> 3
3.object_id
=> 7
str = "foo"
str.upcase
=> ”FOO”
str
=> ”foo”
str.upcase!
=> ”FOO”
str
=> ”FOO”
# Now that it’s already FOO:
str.upcase!
=> nil # ?!
str
=> ”FOO”
Well-known semi-gotcha:
bang versions of methods
are dangerous; usually
may modify receiver.
DO NOT RELY ON THEM
RETURNING SAME
VALUE AS NON-BANG
VERSION!
Many return nil if no
change needed!
(to! || ! to!) == ?
Initial value given as
object is same object
for each slot (if modded
in place, not reassigned
as with = or +=).
Initial value given as
block gets evaluated
separately for each slot.
Use this to create new
vars for each.
An Array of New Gotchas
class Person
attr_accessor :name
end
people = Array.new(3, Person.new)
people[0].name = "Alice"
people[1].name = "Bob"
people[0].name
=> "Bob"
# should have been "Alice"!
people = Array.new(3) { Person.new
}
people[0].name = "Alice"
people[1].name = "Bob"
people[0].name
=> "Alice"
Mostly same problem (and
solution) as Arrays.
WARNING: creates new
object on any access to
empty slot! May create
excessive number of new
objects; ruins checking
“real” contents or count
(nil-checking, .size, etc.).
langs = Hash.new []
langs[:jane] << "Java"
langs[:rachel] << "Ruby"
langs[:jane]
=> ["Java", "Ruby"]
langs[:rachel]
=> ["Java", "Ruby"]
langs = Hash.new { |h, k|
h[k] = [] }
langs[:jane] << "Java"
langs[:rachel] << "Ruby"
langs[:jane]
=> ["Java"]
langs[:rachel]
=> ["Ruby"]
Making a Hash of it
/* JAVA: */
try {
throw new MyException("blah");
} catch(MyException e) {
fix_it();
}
# RUBY:
index = catch(:idx) {
arr.each_with_index do |v, i|
throw :idx, i if v == target
end
-1
}
begin
raise MyException.new "blah"
rescue MyException => e
fix_it
end
Rescue Me, Throw a Line, I'll Try to Catch It!
In Ruby, throw and catch
are NOT for exceptions!
They are advanced flow
control, to exit deep
nesting.
Ruby uses raise and
rescue for exceptions.
- Watch out for these gotchas as you code.
- If Ruby behaves badly, refer to these slides.
- Available at http://bit.ly/RubyGotchas
- If your gotcha isn’t listed, tell me; maybe I’ll add it!
I’m Gonna Getcha Getcha Getcha Getcha!
Add gotchas:
- to_s vs. to_str
- need to coordinate method_missing and respond_to_missing?
- rescue from a StandardError, not an Exception
- instance_eval with calls in local scope
- private data isn’t really, and not at all w/ class methods
- private/protected not same as in other languages
- diffs in lambda/proc/block/method, WRT break/next/return/etc.
- braces vs. do-end (TL;DR: braces high precedence, do-end low)
- attribute=(val) always returns the argument, no matter the code
- Proxies are always truthy, even if the target is not
- class Foo::Bar, defined outside Module Foo, won’t see inside Foo
- in debugging, “next” goes into loops but skips over blocks
- vars introduced in a loop (not block!) are visible outside it (?)
- private methods are accessible by the instance, not the whole class
Rails gotchas?
Screencast series -- maybe text, audio, and screencast versions?
The Someday-Maybe List
questions.any? ; gotchas[:more].any?
Contact information / shameless plug:
T.Rex-2015 [at] Codosaur [dot] us
+1-571-308-6622
www.Codosaur.us (Codosaurus, LLC main site)
www.linkedin.com/profile/view?id=719998
Blog.Codosaur.us (code blog)
www.Dare2XL.com (excellence blog)
@davearonson
AVAILABLE FOR CONSULTING!
Questions/Contact/Etc.

Más contenido relacionado

La actualidad más candente

Introduction to modern c++ principles(part 1)
Introduction to modern c++ principles(part 1)Introduction to modern c++ principles(part 1)
Introduction to modern c++ principles(part 1)Oky Firmansyah
 
The Sincerest Form of Flattery
The Sincerest Form of FlatteryThe Sincerest Form of Flattery
The Sincerest Form of FlatteryJosé Paumard
 
A JavaScript Master Class - From the Wows to the WTFs
A JavaScript Master Class - From the Wows to the WTFsA JavaScript Master Class - From the Wows to the WTFs
A JavaScript Master Class - From the Wows to the WTFsShahriar Hyder
 
Douglas Crockford Presentation Goodparts
Douglas Crockford Presentation GoodpartsDouglas Crockford Presentation Goodparts
Douglas Crockford Presentation GoodpartsAjax Experience 2009
 
Notes5
Notes5Notes5
Notes5hccit
 
Programming with Java: the Basics
Programming with Java: the BasicsProgramming with Java: the Basics
Programming with Java: the BasicsJussi Pohjolainen
 
Erlang kickstart
Erlang kickstartErlang kickstart
Erlang kickstartRyan Brown
 
DEFUN 2008 - Real World Haskell
DEFUN 2008 - Real World HaskellDEFUN 2008 - Real World Haskell
DEFUN 2008 - Real World HaskellBryan O'Sullivan
 
Frege - consequently functional programming for the JVM
Frege - consequently functional programming for the JVMFrege - consequently functional programming for the JVM
Frege - consequently functional programming for the JVMDierk König
 
Hipster FP code harder to maintain because it actively removes domain knowledge
Hipster FP code harder to maintain because it actively removes domain knowledge Hipster FP code harder to maintain because it actively removes domain knowledge
Hipster FP code harder to maintain because it actively removes domain knowledge Philip Schwarz
 
basic of desicion control statement in python
basic of  desicion control statement in pythonbasic of  desicion control statement in python
basic of desicion control statement in pythonnitamhaske
 
An introduction to property based testing
An introduction to property based testingAn introduction to property based testing
An introduction to property based testingScott Wlaschin
 
The Sincerest Form of Flattery
The Sincerest Form of FlatteryThe Sincerest Form of Flattery
The Sincerest Form of FlatteryJosé Paumard
 
Ruby Topic Maps Tutorial (2007-10-10)
Ruby Topic Maps Tutorial (2007-10-10)Ruby Topic Maps Tutorial (2007-10-10)
Ruby Topic Maps Tutorial (2007-10-10)Benjamin Bock
 
Javascript basics
Javascript basicsJavascript basics
Javascript basicsSolv AS
 
Java if and else
Java if and elseJava if and else
Java if and elsepratik8897
 
JavaScript - From Birth To Closure
JavaScript - From Birth To ClosureJavaScript - From Birth To Closure
JavaScript - From Birth To ClosureRobert Nyman
 
BayFP: Concurrent and Multicore Haskell
BayFP: Concurrent and Multicore HaskellBayFP: Concurrent and Multicore Haskell
BayFP: Concurrent and Multicore HaskellBryan O'Sullivan
 

La actualidad más candente (20)

Introduction to modern c++ principles(part 1)
Introduction to modern c++ principles(part 1)Introduction to modern c++ principles(part 1)
Introduction to modern c++ principles(part 1)
 
The Sincerest Form of Flattery
The Sincerest Form of FlatteryThe Sincerest Form of Flattery
The Sincerest Form of Flattery
 
A JavaScript Master Class - From the Wows to the WTFs
A JavaScript Master Class - From the Wows to the WTFsA JavaScript Master Class - From the Wows to the WTFs
A JavaScript Master Class - From the Wows to the WTFs
 
Douglas Crockford Presentation Goodparts
Douglas Crockford Presentation GoodpartsDouglas Crockford Presentation Goodparts
Douglas Crockford Presentation Goodparts
 
Notes5
Notes5Notes5
Notes5
 
Kleisli Composition
Kleisli CompositionKleisli Composition
Kleisli Composition
 
Programming with Java: the Basics
Programming with Java: the BasicsProgramming with Java: the Basics
Programming with Java: the Basics
 
Erlang kickstart
Erlang kickstartErlang kickstart
Erlang kickstart
 
DEFUN 2008 - Real World Haskell
DEFUN 2008 - Real World HaskellDEFUN 2008 - Real World Haskell
DEFUN 2008 - Real World Haskell
 
Frege - consequently functional programming for the JVM
Frege - consequently functional programming for the JVMFrege - consequently functional programming for the JVM
Frege - consequently functional programming for the JVM
 
Hipster FP code harder to maintain because it actively removes domain knowledge
Hipster FP code harder to maintain because it actively removes domain knowledge Hipster FP code harder to maintain because it actively removes domain knowledge
Hipster FP code harder to maintain because it actively removes domain knowledge
 
basic of desicion control statement in python
basic of  desicion control statement in pythonbasic of  desicion control statement in python
basic of desicion control statement in python
 
An introduction to property based testing
An introduction to property based testingAn introduction to property based testing
An introduction to property based testing
 
The Sincerest Form of Flattery
The Sincerest Form of FlatteryThe Sincerest Form of Flattery
The Sincerest Form of Flattery
 
Ruby Topic Maps Tutorial (2007-10-10)
Ruby Topic Maps Tutorial (2007-10-10)Ruby Topic Maps Tutorial (2007-10-10)
Ruby Topic Maps Tutorial (2007-10-10)
 
Javascript basics
Javascript basicsJavascript basics
Javascript basics
 
Assign
AssignAssign
Assign
 
Java if and else
Java if and elseJava if and else
Java if and else
 
JavaScript - From Birth To Closure
JavaScript - From Birth To ClosureJavaScript - From Birth To Closure
JavaScript - From Birth To Closure
 
BayFP: Concurrent and Multicore Haskell
BayFP: Concurrent and Multicore HaskellBayFP: Concurrent and Multicore Haskell
BayFP: Concurrent and Multicore Haskell
 

Destacado

Linked in Research Tips
Linked in Research TipsLinked in Research Tips
Linked in Research TipsCaity Heflin
 
How to master the interview
How to master the interviewHow to master the interview
How to master the interviewCaity Heflin
 
параг 22
параг 22параг 22
параг 22iLeushev
 
DataStax's Vision 06.12.2013 (CassandraSF 2013)
DataStax's Vision 06.12.2013 (CassandraSF 2013)DataStax's Vision 06.12.2013 (CassandraSF 2013)
DataStax's Vision 06.12.2013 (CassandraSF 2013)joaquincasares
 
LinkedIn research tips
LinkedIn research tipsLinkedIn research tips
LinkedIn research tipsCaity Heflin
 
параг 22
параг 22параг 22
параг 22iLeushev
 
Linked in research tips
Linked in research tipsLinked in research tips
Linked in research tipsCaity Heflin
 
OOP - A Silver Bullet ?
OOP - A Silver Bullet ?OOP - A Silver Bullet ?
OOP - A Silver Bullet ?mudabbirwarsi
 
импульс
импульсимпульс
импульсiLeushev
 
Session 29 Tomas Klemets
Session 29 Tomas KlemetsSession 29 Tomas Klemets
Session 29 Tomas Klemetsklemets
 
Cover letter and resume power point
Cover letter and resume power pointCover letter and resume power point
Cover letter and resume power pointCaity Heflin
 

Destacado (15)

Linked in Research Tips
Linked in Research TipsLinked in Research Tips
Linked in Research Tips
 
How to master the interview
How to master the interviewHow to master the interview
How to master the interview
 
параг 22
параг 22параг 22
параг 22
 
UT Career Fair 2012
UT Career Fair 2012UT Career Fair 2012
UT Career Fair 2012
 
DataStax's Vision 06.12.2013 (CassandraSF 2013)
DataStax's Vision 06.12.2013 (CassandraSF 2013)DataStax's Vision 06.12.2013 (CassandraSF 2013)
DataStax's Vision 06.12.2013 (CassandraSF 2013)
 
Design patterns
Design patternsDesign patterns
Design patterns
 
LinkedIn research tips
LinkedIn research tipsLinkedIn research tips
LinkedIn research tips
 
параг 22
параг 22параг 22
параг 22
 
Linked in research tips
Linked in research tipsLinked in research tips
Linked in research tips
 
OOP - A Silver Bullet ?
OOP - A Silver Bullet ?OOP - A Silver Bullet ?
OOP - A Silver Bullet ?
 
Social Media
Social MediaSocial Media
Social Media
 
импульс
импульсимпульс
импульс
 
Session 29 Tomas Klemets
Session 29 Tomas KlemetsSession 29 Tomas Klemets
Session 29 Tomas Klemets
 
Cpp unit
Cpp unit Cpp unit
Cpp unit
 
Cover letter and resume power point
Cover letter and resume power pointCover letter and resume power point
Cover letter and resume power point
 

Similar a Ruby Gotchas: Common Surprises and Confusing Cases in Ruby Programming

A limited guide to intermediate and advanced Ruby
A limited guide to intermediate and advanced RubyA limited guide to intermediate and advanced Ruby
A limited guide to intermediate and advanced RubyVysakh Sreenivasan
 
Threequals - Case Equality in Ruby
Threequals - Case Equality in RubyThreequals - Case Equality in Ruby
Threequals - Case Equality in RubyLouis Scoras
 
JavaScript 1 for high school
JavaScript 1 for high schoolJavaScript 1 for high school
JavaScript 1 for high schooljekkilekki
 
Ruby -the wheel Technology
Ruby -the wheel TechnologyRuby -the wheel Technology
Ruby -the wheel Technologyppparthpatel123
 
Brogramming - Python, Bash for Data Processing, and Git
Brogramming - Python, Bash for Data Processing, and GitBrogramming - Python, Bash for Data Processing, and Git
Brogramming - Python, Bash for Data Processing, and GitRon Reiter
 
Ceylon idioms by Gavin King
Ceylon idioms by Gavin KingCeylon idioms by Gavin King
Ceylon idioms by Gavin KingUnFroMage
 
Red Flags in Programming
Red Flags in ProgrammingRed Flags in Programming
Red Flags in ProgrammingxSawyer
 
Unit I Advanced Java Programming Course
Unit I   Advanced Java Programming CourseUnit I   Advanced Java Programming Course
Unit I Advanced Java Programming Courseparveen837153
 
Learning puppet chapter 2
Learning puppet chapter 2Learning puppet chapter 2
Learning puppet chapter 2Vishal Biyani
 
Java Pitfalls and Good-to-Knows
Java Pitfalls and Good-to-KnowsJava Pitfalls and Good-to-Knows
Java Pitfalls and Good-to-KnowsMiquel Martin
 
The Swift Programming Language - Xcode6 for iOS App Development - AgileInfowa...
The Swift Programming Language - Xcode6 for iOS App Development - AgileInfowa...The Swift Programming Language - Xcode6 for iOS App Development - AgileInfowa...
The Swift Programming Language - Xcode6 for iOS App Development - AgileInfowa...Mark Simon
 
Slides chapter3part1 ruby-forjavaprogrammers
Slides chapter3part1 ruby-forjavaprogrammersSlides chapter3part1 ruby-forjavaprogrammers
Slides chapter3part1 ruby-forjavaprogrammersGiovanni924
 
name name2 n
name name2 nname name2 n
name name2 ncallroom
 
name name2 n2
name name2 n2name name2 n2
name name2 n2callroom
 

Similar a Ruby Gotchas: Common Surprises and Confusing Cases in Ruby Programming (20)

A limited guide to intermediate and advanced Ruby
A limited guide to intermediate and advanced RubyA limited guide to intermediate and advanced Ruby
A limited guide to intermediate and advanced Ruby
 
Threequals - Case Equality in Ruby
Threequals - Case Equality in RubyThreequals - Case Equality in Ruby
Threequals - Case Equality in Ruby
 
JavaScript 1 for high school
JavaScript 1 for high schoolJavaScript 1 for high school
JavaScript 1 for high school
 
Ruby -the wheel Technology
Ruby -the wheel TechnologyRuby -the wheel Technology
Ruby -the wheel Technology
 
Brogramming - Python, Bash for Data Processing, and Git
Brogramming - Python, Bash for Data Processing, and GitBrogramming - Python, Bash for Data Processing, and Git
Brogramming - Python, Bash for Data Processing, and Git
 
ruby1_6up
ruby1_6upruby1_6up
ruby1_6up
 
ruby1_6up
ruby1_6upruby1_6up
ruby1_6up
 
Ceylon idioms by Gavin King
Ceylon idioms by Gavin KingCeylon idioms by Gavin King
Ceylon idioms by Gavin King
 
Red Flags in Programming
Red Flags in ProgrammingRed Flags in Programming
Red Flags in Programming
 
Unit I Advanced Java Programming Course
Unit I   Advanced Java Programming CourseUnit I   Advanced Java Programming Course
Unit I Advanced Java Programming Course
 
Learning puppet chapter 2
Learning puppet chapter 2Learning puppet chapter 2
Learning puppet chapter 2
 
Java Pitfalls and Good-to-Knows
Java Pitfalls and Good-to-KnowsJava Pitfalls and Good-to-Knows
Java Pitfalls and Good-to-Knows
 
Ruby Intro {spection}
Ruby Intro {spection}Ruby Intro {spection}
Ruby Intro {spection}
 
The Swift Programming Language - Xcode6 for iOS App Development - AgileInfowa...
The Swift Programming Language - Xcode6 for iOS App Development - AgileInfowa...The Swift Programming Language - Xcode6 for iOS App Development - AgileInfowa...
The Swift Programming Language - Xcode6 for iOS App Development - AgileInfowa...
 
Slides chapter3part1 ruby-forjavaprogrammers
Slides chapter3part1 ruby-forjavaprogrammersSlides chapter3part1 ruby-forjavaprogrammers
Slides chapter3part1 ruby-forjavaprogrammers
 
Ruby 101
Ruby 101Ruby 101
Ruby 101
 
ppt7
ppt7ppt7
ppt7
 
ppt2
ppt2ppt2
ppt2
 
name name2 n
name name2 nname name2 n
name name2 n
 
name name2 n2
name name2 n2name name2 n2
name name2 n2
 

Más de Dave Aronson

Kill All Mutants! (Intro to Mutation Testing, from Scenic City Summit 2021)
Kill All Mutants! (Intro to Mutation Testing, from Scenic City Summit 2021)Kill All Mutants! (Intro to Mutation Testing, from Scenic City Summit 2021)
Kill All Mutants! (Intro to Mutation Testing, from Scenic City Summit 2021)Dave Aronson
 
Write Better Software With ACRUMEN slides from Scenic City Summit 2021
Write Better Software With ACRUMEN slides from Scenic City Summit 2021Write Better Software With ACRUMEN slides from Scenic City Summit 2021
Write Better Software With ACRUMEN slides from Scenic City Summit 2021Dave Aronson
 
Kill All Mutants! (Intro to Mutation Testing), Code Europe (Poland), 2021
Kill All Mutants! (Intro to Mutation Testing), Code Europe (Poland), 2021Kill All Mutants! (Intro to Mutation Testing), Code Europe (Poland), 2021
Kill All Mutants! (Intro to Mutation Testing), Code Europe (Poland), 2021Dave Aronson
 
Kill All Mutants KCDC 2021
Kill All Mutants KCDC 2021Kill All Mutants KCDC 2021
Kill All Mutants KCDC 2021Dave Aronson
 
"Kill All Mutants! (Intro to Mutation Testing)" Slides from NDC Sydney 2020
"Kill All Mutants! (Intro to Mutation Testing)" Slides from NDC Sydney 2020"Kill All Mutants! (Intro to Mutation Testing)" Slides from NDC Sydney 2020
"Kill All Mutants! (Intro to Mutation Testing)" Slides from NDC Sydney 2020Dave Aronson
 
ACRUMEN Slides for DevConf Poland
ACRUMEN Slides for DevConf PolandACRUMEN Slides for DevConf Poland
ACRUMEN Slides for DevConf PolandDave Aronson
 
ACRUMEN Slides for Arlington Ruby (Practice for DevConf)
ACRUMEN Slides for Arlington Ruby (Practice for DevConf)ACRUMEN Slides for Arlington Ruby (Practice for DevConf)
ACRUMEN Slides for Arlington Ruby (Practice for DevConf)Dave Aronson
 
ACRUMEN Slides for RubyNation and CapitalGo, 2018
ACRUMEN Slides for RubyNation and CapitalGo, 2018ACRUMEN Slides for RubyNation and CapitalGo, 2018
ACRUMEN Slides for RubyNation and CapitalGo, 2018Dave Aronson
 
ACRUMEN: Key Aspects of Software Quality (half-hour talk slides)
ACRUMEN: Key Aspects of Software Quality (half-hour talk slides)ACRUMEN: Key Aspects of Software Quality (half-hour talk slides)
ACRUMEN: Key Aspects of Software Quality (half-hour talk slides)Dave Aronson
 

Más de Dave Aronson (9)

Kill All Mutants! (Intro to Mutation Testing, from Scenic City Summit 2021)
Kill All Mutants! (Intro to Mutation Testing, from Scenic City Summit 2021)Kill All Mutants! (Intro to Mutation Testing, from Scenic City Summit 2021)
Kill All Mutants! (Intro to Mutation Testing, from Scenic City Summit 2021)
 
Write Better Software With ACRUMEN slides from Scenic City Summit 2021
Write Better Software With ACRUMEN slides from Scenic City Summit 2021Write Better Software With ACRUMEN slides from Scenic City Summit 2021
Write Better Software With ACRUMEN slides from Scenic City Summit 2021
 
Kill All Mutants! (Intro to Mutation Testing), Code Europe (Poland), 2021
Kill All Mutants! (Intro to Mutation Testing), Code Europe (Poland), 2021Kill All Mutants! (Intro to Mutation Testing), Code Europe (Poland), 2021
Kill All Mutants! (Intro to Mutation Testing), Code Europe (Poland), 2021
 
Kill All Mutants KCDC 2021
Kill All Mutants KCDC 2021Kill All Mutants KCDC 2021
Kill All Mutants KCDC 2021
 
"Kill All Mutants! (Intro to Mutation Testing)" Slides from NDC Sydney 2020
"Kill All Mutants! (Intro to Mutation Testing)" Slides from NDC Sydney 2020"Kill All Mutants! (Intro to Mutation Testing)" Slides from NDC Sydney 2020
"Kill All Mutants! (Intro to Mutation Testing)" Slides from NDC Sydney 2020
 
ACRUMEN Slides for DevConf Poland
ACRUMEN Slides for DevConf PolandACRUMEN Slides for DevConf Poland
ACRUMEN Slides for DevConf Poland
 
ACRUMEN Slides for Arlington Ruby (Practice for DevConf)
ACRUMEN Slides for Arlington Ruby (Practice for DevConf)ACRUMEN Slides for Arlington Ruby (Practice for DevConf)
ACRUMEN Slides for Arlington Ruby (Practice for DevConf)
 
ACRUMEN Slides for RubyNation and CapitalGo, 2018
ACRUMEN Slides for RubyNation and CapitalGo, 2018ACRUMEN Slides for RubyNation and CapitalGo, 2018
ACRUMEN Slides for RubyNation and CapitalGo, 2018
 
ACRUMEN: Key Aspects of Software Quality (half-hour talk slides)
ACRUMEN: Key Aspects of Software Quality (half-hour talk slides)ACRUMEN: Key Aspects of Software Quality (half-hour talk slides)
ACRUMEN: Key Aspects of Software Quality (half-hour talk slides)
 

Último

08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Servicegiselly40
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEarley Information Science
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Igalia
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilV3cube
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...gurkirankumar98700
 

Último (20)

08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of Brazil
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
 

Ruby Gotchas: Common Surprises and Confusing Cases in Ruby Programming

  • 1. Ruby GotchasLast edited 2014-11-26 by Dave Aronson, T. Rex of Codosaurus, LLC
  • 2. Though "engineered to maximize programmer happiness", with the "principle of least surprise", Ruby still has gotchas. This presentation will proceed from newbie trivial gotchas, to more advanced and confusing gotchas. We = 2 class Fixnum def rb; self; end end We <3 .rb => true But = 3 still = 1 perfect = 4 But - still .rb < perfect => true Ruby can be surprising!
  • 3. Don't quote me on this, but . . . . x = 3 puts 'x = #{x}nx' x = #{x}nx puts "x = #{x}nx" x = 3 x String interpolation (including special chars like n) fails with 'single' quotes -- it requires "double" quotes. (Just like in most languages with string interpolation.) To avoid: use doubles whenever practical.
  • 4. Only two things are false (falsey): false, and nil. Everything else is true (truthy), even 0 (false in C), "" (false in JS), [], etc. (Trips up people from C, JS, etc. where some of these are false.) It's twue! It's twue! true ? "true" : "false" => "true" false ? "true" : "false" => "false" nil ? "true" : "false" => "false" 1 ? "true" : "false" => "true" 0 ? "true" : "false" => "true" "false"? "true" : "false" => "true" "" ? "true" : "false" => "true" [] ? "true" : "false" => "true"
  • 5. Symbols != strings. Even if same, printed. Remember which one to use for what (args). Ideally, take either: "Be liberal in what you accept, and conservative in what you send." (Postel's Law) str = "string" sym = :string puts str string puts sym string str == sym => false Hang him in effigy (String him up, symbolically)
  • 6. bash> irb-1.9 str = "string" => "string" str[2] => "r" # makes sense *now* bash> irb-1.8 str = "string" => "string" str[2] => 114 # ??? ascii code! str[2..2] => "r" # that's better! str[2,1] => "r" # works too.... String... or nothing!
  • 7. FOO = 5 => 5 FOO = 7 (irb):3: warning: already initialized constant FOO => 7 FOO => 7 Constants Aren't (Part 1/2) (Initial uppercase means constant, in Ruby.) Try to change a constant. Ooooh, you get a WARNING! BFD.
  • 8. Even freezing doesn't work for Fixnums. It does work for arrays (sort of) and most other objects . . . he said foreshadowingly. FOO => 7 FOO.freeze => 7 FOO += 2 (irb):5: warning: already initialized constant FOO => 9 FOO => 9 Constants Aren't (Part 2/2)
  • 9. Some are more equal than others Effectively: == is the usual (same value) .eql? is value and class (1 is Fixnum, 1.0 is Float) .equal? is same object It's actually much hairier; see docs on class Object 1 == 1.0 => true 1.eql? 1.0 => false a = "foo" b = "foo" a == b => true a.eql? b => true a.equal? b => false a.equal? a => true
  • 10. Effectively: === is "case equality", as in case statements. A better name (IMHO) might be ".describes?", or overload ".includes?"! Again, it's actually much hairier; see the docs on class Object. Gets people from languages where === is identity, or same value and class. === != ==! 1 === 1 => true Fixnum === 1 => true 1 === Fixnum => false Class === Class Object === Object Class === Object Object === Class => all true Fixnum === Fixnum => false (1..3) === 2 => true 2 === (1..3) => false
  • 11. && has higher precedence than =, so x = true && false means x = (true && false) and has lower precedence, so x = true and false means (x = true) and false Ruby Style Guide: Use && / || for boolean expressions, [use] and / or for control flow. x = true && false => false x => false # OK so far, but: x = true and false => false x => true Return value is false but variable is true! Why the mismatch?! and != &&
  • 12. || has higher precedence than =, so x = false || true means x = (false || true) or has lower precedence so x = false or true means (x = false) or true Also, && is higher than ||, but and and or are equal, so they are evaluated left-to-right! x = false || true => true x => true # OK so far, but: x = false or true => true x => false Return value is true but variable is false! Why the mismatch?! or != ||
  • 13. Whitespace-insensitive? NOT ALWAYS! With multiple args: - No parens, no problem. - Parens w/o space, OK. - Parens and space, NO! Parser thinks it's an expression, as one arg, but (1, 2) is not a valid Ruby expression! (All work fine w/ 1 arg.) def method(arg1, arg2); end method 1, 2 => nil method(1, 2) => nil method (1, 2) syntax error, unexpected ',', expecting ')' method (1, 2) ^ Don't be so sensitive! (Part 1/4)
  • 14. def method; 42; end num = 21 method/num => 2 method / num => 2 method/ num => 2 method /num SyntaxError: unterminated regexp "method /num" is an unended regex or string! Ruby thinks you might be giving an argument to method meth. General principle: use BALANCED whitespace; both sides or neither. Don't be so sensitive! (Part 2/4)
  • 15. "one -1" makes Ruby think you might be giving an argument (of -1) to method one. (Same for +1 . . . or even *1!) Again: use BALANCED whitespace; both sides or neither. def one 1 end one - 1 => 0 one-1 => 0 one- 1 => 0 one -1 ArgumentError: wrong number of arguments (1 for 0) Don't be so sensitive! (Part 3/4)
  • 16. dbl = ->(x) { x * 2 } => #<Proc:... (lambda)> dbl = ->x{ x * 2 } => #<Proc:... (lambda)> dbl = -> x { x * 2 } => #<Proc:... (lambda)> two = -> { 2 } => #<Proc:... (lambda)> dbl = -> (x) { x * 2 } syntax error, unexpected tLPAREN_ARG, expecting keyword_do_LAMBDA or tLAMBEG two = -> () { 2 } same syntax error "Stabby" lambdas (1.9+) Parentheses optional Space before/after args without parens, OK. Space after parens, OK. Again, space before parens, NO! UPDATE: Fixed in 2.0! Don't be so sensitive! (Part 4/4)
  • 17. class Foo attr_reader :value def initialize(v) value = v end def set_val(v) @value = v end end f = Foo.new(3) f.value => nil # not 3?! f.set_val 5 => 5 f.value => 5 'Ang onto yer @! Naked value becomes a temporary local variable! Solution: remember the @! (Or "self.".) Gets people from Java/C++, not so much Python (which needs "self." too). "You keep on using that variable. I don't think it means what you think it means."
  • 18. What the fillintheblank? We didn't change Parent’s @@value before checking it, nor Child’s at all! . . . Or did we? @@ variables are shared with subclasses -- not just that they exist, but the variables themselves! Declaring Child’s @@value changed Parent’s, and inc’ing Parent’s changed Child’s. IMHO, best just forget them. class Parent @@value = 6 def self.value @@value end def self.inc_value @@value += 1 end end class Child < Parent @@value = 42 end Parent.value => 42 # wtf? Parent.inc_value Child.value => 43 # wtf?! Look out, it’s an @@!
  • 19. class Parent def initialize puts "Parent init" end end class NoInitChild < Parent end NoInitChild.new Parent init class NormalChild < Parent def initialize puts "NormalChild init" end end NormalChild.new "NormalChild init" With init(ialize) or without it class SuperChild < Parent def initialize puts "SuperChild" super puts "init" end end SuperChild.new SuperChild Parent init init Parent's initialize runs automagically only if child has none. Else, parent's must be called to run.
  • 20. Superman vs. the Invisible Man Child2.new.add 1, 2, 3, 5 ArgumentError: wrong number of arguments (4 for 2) Child2.new.add 1, 2 => 3 Child4.new.add 1, 2, 3, 5 => 11 super with no arg list sends what caller got super with explicit args sends those args to send NO args, use empty parens: super() class Parent def add *args args.inject :+ end end class Child2 < Parent def add arg1, arg2 super arg1, arg2 end end class Child4 < Parent def add a1, a2, a3, a4 super # no args! end end
  • 21. When will it end? (Or start?) str = "OnenTwonThree" str =~ /^Two$/ => 4 str =~ /ATwoZ/ => nil str =~ /AOne/ => 0 str =~ /ThreeZ/ => 8 In "standard" regexps: ^ is start and $ is end... of the whole string. Ruby’s regexes default to multiline, so: ^ is start and $ is end... of any line! A is start and Z is end of the whole string. (Or z to include any newline… which is another gotcha!)
  • 22. [].any? => false [1].any? => true [:foo, :bar].any? => true # ok so far, BUT: [nil].any? => false [false].any? => false [false, nil].any? => false .any? does not mean “any elements?”! With block: “do any make the block true?” Without: “are any truthy?” Has implicit block: { |element| element } getting .any?
  • 23. Variables declared in blocks passed to iterators (e.g., times or each) are undefined at the top of each iteration! Iterators call the block repeatedly, so vars are out of scope again after each call. Built-in looping constructs (e. g., while or for) are OK. (Or declare vars before block.) 3.times do |loop_num| sum ||= 0 sum += 1 puts sum end 1 1 1 for loop_num in 1..3 sum ||= 0 sum += 1 puts sum end 1 2 3 (Un)Def Leppard
  • 24. arr = ["one", "two", "three"] arr.freeze arr << "four" RuntimeError: can't modify frozen Array arr[0] = "eno" RuntimeError: can't modify frozen Array arr[0].object_id => 1234567890 arr[0].reverse! arr => ["eno", "two", "three"] arr[0].object_id => 1234567890 Freezing an array (or a hash) freezes it, not the items it contains. Strings can be modified in place. This way, you can modify a given slot in a frozen Array of Strings. Freeze (Ar)ray
  • 25. Changing Fixnum to new value means new object. They can't be modified in place! So, can’t modify a frozen Array of Fixnums. (Fixnums and Integers have no bang-methods to demo trying with.) BTW: a Fixnum's object_id is value * 2 + 1. 1 is 1 … and ever more shall be so! arr = [1, 2, 3, 4] arr.freeze => [1, 2, 3, 4] arr << 5 RuntimeError: can't modify frozen Array arr[0] += 2 RuntimeError: can't modify frozen Array 1.object_id => 3 3.object_id => 7
  • 26. str = "foo" str.upcase => ”FOO” str => ”foo” str.upcase! => ”FOO” str => ”FOO” # Now that it’s already FOO: str.upcase! => nil # ?! str => ”FOO” Well-known semi-gotcha: bang versions of methods are dangerous; usually may modify receiver. DO NOT RELY ON THEM RETURNING SAME VALUE AS NON-BANG VERSION! Many return nil if no change needed! (to! || ! to!) == ?
  • 27. Initial value given as object is same object for each slot (if modded in place, not reassigned as with = or +=). Initial value given as block gets evaluated separately for each slot. Use this to create new vars for each. An Array of New Gotchas class Person attr_accessor :name end people = Array.new(3, Person.new) people[0].name = "Alice" people[1].name = "Bob" people[0].name => "Bob" # should have been "Alice"! people = Array.new(3) { Person.new } people[0].name = "Alice" people[1].name = "Bob" people[0].name => "Alice"
  • 28. Mostly same problem (and solution) as Arrays. WARNING: creates new object on any access to empty slot! May create excessive number of new objects; ruins checking “real” contents or count (nil-checking, .size, etc.). langs = Hash.new [] langs[:jane] << "Java" langs[:rachel] << "Ruby" langs[:jane] => ["Java", "Ruby"] langs[:rachel] => ["Java", "Ruby"] langs = Hash.new { |h, k| h[k] = [] } langs[:jane] << "Java" langs[:rachel] << "Ruby" langs[:jane] => ["Java"] langs[:rachel] => ["Ruby"] Making a Hash of it
  • 29. /* JAVA: */ try { throw new MyException("blah"); } catch(MyException e) { fix_it(); } # RUBY: index = catch(:idx) { arr.each_with_index do |v, i| throw :idx, i if v == target end -1 } begin raise MyException.new "blah" rescue MyException => e fix_it end Rescue Me, Throw a Line, I'll Try to Catch It! In Ruby, throw and catch are NOT for exceptions! They are advanced flow control, to exit deep nesting. Ruby uses raise and rescue for exceptions.
  • 30. - Watch out for these gotchas as you code. - If Ruby behaves badly, refer to these slides. - Available at http://bit.ly/RubyGotchas - If your gotcha isn’t listed, tell me; maybe I’ll add it! I’m Gonna Getcha Getcha Getcha Getcha!
  • 31. Add gotchas: - to_s vs. to_str - need to coordinate method_missing and respond_to_missing? - rescue from a StandardError, not an Exception - instance_eval with calls in local scope - private data isn’t really, and not at all w/ class methods - private/protected not same as in other languages - diffs in lambda/proc/block/method, WRT break/next/return/etc. - braces vs. do-end (TL;DR: braces high precedence, do-end low) - attribute=(val) always returns the argument, no matter the code - Proxies are always truthy, even if the target is not - class Foo::Bar, defined outside Module Foo, won’t see inside Foo - in debugging, “next” goes into loops but skips over blocks - vars introduced in a loop (not block!) are visible outside it (?) - private methods are accessible by the instance, not the whole class Rails gotchas? Screencast series -- maybe text, audio, and screencast versions? The Someday-Maybe List
  • 32. questions.any? ; gotchas[:more].any? Contact information / shameless plug: T.Rex-2015 [at] Codosaur [dot] us +1-571-308-6622 www.Codosaur.us (Codosaurus, LLC main site) www.linkedin.com/profile/view?id=719998 Blog.Codosaur.us (code blog) www.Dare2XL.com (excellence blog) @davearonson AVAILABLE FOR CONSULTING! Questions/Contact/Etc.