What Ruby can learn 
from Python 
(and vice versa) 
Reuven M. Lerner, PhD • reuven@lerner.co.il 
Rails Israel 2014 
November 4th, 2014
Who am I? 
• Programmer, consultant, developer, trainer 
• Long-time Ruby, Python user 
• Linux Journal columnist 
• Author, Practice Makes Python! 
• PhD in Learning Sciences from Northwestern 
• Read (lots) more at http://lerner.co.il/ 
2
Python, Ruby, and me
Sapir-Whorf Hypothesis 
"Cognitive processes, such as thought and 
experience, may be influenced by the categories and 
patterns of the language a person speaks." — 
Wikipedia 
4
Or: 
You are what you speak! 
5
Learning a language 
helps you not only communicate, 
but also to think in new ways 
6
7
你有叉⼦子吗? 
Nǐ yǒu chāzi ma? 
Do you have a fork? 
8
Possible answers 
• "Yes" 
• "No" 
• "What's a fork?" 
• "Your accent is so bad, I have no idea what you're 
saying" 
9
The actual answer? 
• None of the above! 
• Chinese doesn't have words for "yes" and "no." 
10
你有叉⼦子吗? 
Nǐ yǒu chāzi ma? 
Do you have a fork? 
Answer: 有 (yǒu) 
"Have" 
11
Can you think of 
another language that 
works this way? 
12
בראשית כ״ט, ו׳ 
ויאמר, ״השלום לו?״ 
ויאמרו ״שלום.״ 
Genesis 29:6 
And he said, "Is he well?" 
And they said, "Well!" (i.e., "Yes!") 
13
And also… 
CREATE TABLE Foo (id SERIAL, stuff TEXT); 
CREATE TABLE 
INSERT INTO Foo (stuff) VALUES ('abc'); 
INSERT 0 1 
14
Comparing languages 
• Appreciate each one more 
• Reflect on the relative trade-offs 
15
Ruby and Python both… 
• … dynamically and strongly typed 
• … are JIT byte-compiled 
• … are cross-platform 
• … are widely used for a variety of tasks 
• … popular among Web developers 
• … have multiple implementations 
• … have an object system based (in part) on Smalltalk 
16
And yet 
• Python and Ruby feel very different 
• What can we learn from these differences? 
• What can we learn from the Python world? (And 
what can they learn from us?) 
17
General attitude 
• Ruby wants to give you freedom, to allow you to be 
creative and flexible, as in a natural language 
• TMTOWTDI, POLS 
• Python wants to restrict you, for your own good 
• "There should be one — and preferably only one 
— obvious way to do it." 
18
The result? 
• Python is 
• easier to learn 
• easier to debug and maintain 
• Ruby 
• offers you richer options 
• greater expressiveness 
19
Development process 
• Python Enhancement Proposals (PEPs) 
• Ruby could use such a system 
• Heck, Rails could use such a system 
20
Backward compatibility 
• Historically, Python upgrades were conservative 
• But not 2.x -> 3.x 
• Ruby was less conservative, breaking things 
(especially going from 1.8 to 1.9/2.0) 
• Maybe Python emphasis on compatibility and 
inclusiveness hurt the 3.x upgrade 
21
What is truth? 
• Ruby: Everything is true, except for false and nil 
• Python: Everything is true, except for None, False, 
0, and empty data (e.g., '' or []) 
• So: 0 is false in Python, but true in Ruby! 
• But we all like #blank? and #present? in Rails… 
22
Everything is an object… 
• In both Ruby and Python, everything is an object! 
• But in Python, some objects are more equal than 
others… 
• So you can't do this in Python: 
5.times { puts "Hello" } 
23
Blocks 
• Ruby people love blocks! 
• Python doesn't have them. 
• They create functions, and pass those 
• Or they use lambdas (or not) 
24
Namespaces 
• Python has a single namespace for functions and 
variables. So x can be an int, a str, or a function 
• Ruby has two separate namespaces — one for 
methods, and one for data 
• Ruby's approach can lead to surprises! 
x = 10 # set a local variable 
self.x = 10 # invoke an attr_ method 
25
Reserved words 
• Python barely has any: 
True, False = False, True 
• Ruby lets us open built-in classes, but not this! 
26
Modern Python 
• Fine, modern Python outlaws this. But it allows: 
>>> str = [1,2,3] 
>>> type(str) 
<class 'list'> 
27
Scoping 
• Python has clear rules for scoping: LEGB (local, 
enclosing function, global builtin) 
• Ruby's scoping rules feel natural, but the rules 
aren't easy to learn or remember. 
28
Indentation 
• Newcomers to Python hate the indentation rules 
• But I actually like them! 
• Easy to read 
• No annoying "end - end - end - end" all over 
• Easy to see where code begins and ends 
• That said, Ruby's syntax would never work with 
Python's indentation rules 
29
Parentheses 
• Needed in Python to invoke methods and create classes 
• Makes it easier to pass functions as parameters 
• Not needed in Ruby to invoke methods 
• Makes DSLs cleaner, easier to write and read 
• You cannot pass a method just by name; use 
method(:foo) 
• DSLs in non-Ruby languages look far uglier, and look like 
the original language, not a new one 
30
Explicit return 
• In Ruby, the value of the final line evaluated is the 
value of the method. We often don't say "return" 
• In Python, if you don't say "return", then your 
method returns None 
• I don't see an advantage to Python's behavior 
31
Attributes vs. methods 
• In Ruby, object state is private, and access is all done 
through methods. 
• Want to access data? Write a getter or setter 
• Or use attr_*, and Ruby will write them for you 
• In Python, object state is public 
• Getters and setters are discouraged 
• Want the logic of a getter or setter? Use a "property," 
which invokes a method when you access an attribute 
32
In other words 
• Ruby tries to make data look like methods 
• Method calls are the fundamental form of inter-object 
communication 
• Python tries to make methods look like data 
• Attributes are open, and thus there is less need 
for methods to access data 
• Besides, attributes exist in a single namespace 
33
Object model 
• In Ruby, the object model emphasizes methods 
and inheritance of those methods 
• What are your methods, and what are your 
superclass's methods? 
• In Python, the object model emphasizes attributes 
and "inheritance" of those attributes 
• What attributes are defined on an object, and 
what are define on its class? 
34
What is hard to learn? 
• Each object model leads to something that is hard 
for people to understand 
• In Ruby, you have to understand singleton classes 
(aka eigenclasses) 
• In Python, you have to understand how attributes 
work, including attribute scoping rules 
35
Multiple inheritance vs. 
include/extend 
• Python: Multiple inheritance is OK, if you do it right 
• Ruby: You won't get it right. Use modules!. 
• The inheritance tree is very easy to figure out 
• Modules allow for mixins, the only good reason 
for multiple inheritance 
36
for loops vs. Enumerable 
• In Ruby, we want to iterate over everything 
• Implement #each in your class 
• include Enumerable 
• Now you get map, select, and many other 
methods 
37
for loops vs. Enumerable 
• In Python, we also want to iterate over everything 
• We do that with "for" loops and other global 
constructs (e.g., comprehensions) 
• Our object plug into these constructs by 
implementing the iteration protocol 
38
list.sort's return type 
• Python's, list.sort returns None, not the list 
• In Ruby, we almost always return an object from a 
method, so that we can chain the method calls. 
39
Comprehensions 
• Python has comprehensions: 
[str(x) for x in range(5)] 
[x*x for x in range(5)] 
[line.split(":")[0] 
for line in open('/etc/passwd')] 
40
Sets and dicts 
• Set comprehensions 
{word.strip() 
for word in open('/usr/share/dict/words')} 
• Dictionary comprehensions 
{line.split(":")[0] : line.split(":")[2] 
for line in open('/etc/passwd') 
if line.startswith("#")} 
41
Comprehensible? 
No. 
42
Ruby is more consistent 
• In Ruby, we use the block syntax everywhere 
(0..4).map {|n| n.to_s} 
(0..4).map {|n| n * n} 
File.open('/etc/passwd').readlines. 
map {|line| line.split(":")[0]} 
43
The Ruby version 
Hash[File.open('/etc/passwd'). 
readlines. 
select {|line| line[0] != '#'}. 
map {|line| line.split(":")}. 
map {|row| [row[0], row[2]]} ] 
• Longer, but more consistent 
44
Easy metaprogramming 
• Metaprogramming is fun and easy in Ruby 
• Python permits it, but discourages such things 
• Most of the time, use decorators 
45
46 
Oscar 
Felix 
(Python) 
(Ruby)
你们有问题吗? 
יש לכם שאלות? 
(Do you have any questions?) 
reuven@lerner.co.il 
@reuvenmlerner 
http://lerner.co.il/ 
47

What can Ruby learn from Python (and vice versa)?

  • 1.
    What Ruby canlearn from Python (and vice versa) Reuven M. Lerner, PhD • reuven@lerner.co.il Rails Israel 2014 November 4th, 2014
  • 2.
    Who am I? • Programmer, consultant, developer, trainer • Long-time Ruby, Python user • Linux Journal columnist • Author, Practice Makes Python! • PhD in Learning Sciences from Northwestern • Read (lots) more at http://lerner.co.il/ 2
  • 3.
  • 4.
    Sapir-Whorf Hypothesis "Cognitiveprocesses, such as thought and experience, may be influenced by the categories and patterns of the language a person speaks." — Wikipedia 4
  • 5.
    Or: You arewhat you speak! 5
  • 6.
    Learning a language helps you not only communicate, but also to think in new ways 6
  • 7.
  • 8.
    你有叉⼦子吗? Nǐ yǒuchāzi ma? Do you have a fork? 8
  • 9.
    Possible answers •"Yes" • "No" • "What's a fork?" • "Your accent is so bad, I have no idea what you're saying" 9
  • 10.
    The actual answer? • None of the above! • Chinese doesn't have words for "yes" and "no." 10
  • 11.
    你有叉⼦子吗? Nǐ yǒuchāzi ma? Do you have a fork? Answer: 有 (yǒu) "Have" 11
  • 12.
    Can you thinkof another language that works this way? 12
  • 13.
    בראשית כ״ט, ו׳ ויאמר, ״השלום לו?״ ויאמרו ״שלום.״ Genesis 29:6 And he said, "Is he well?" And they said, "Well!" (i.e., "Yes!") 13
  • 14.
    And also… CREATETABLE Foo (id SERIAL, stuff TEXT); CREATE TABLE INSERT INTO Foo (stuff) VALUES ('abc'); INSERT 0 1 14
  • 15.
    Comparing languages •Appreciate each one more • Reflect on the relative trade-offs 15
  • 16.
    Ruby and Pythonboth… • … dynamically and strongly typed • … are JIT byte-compiled • … are cross-platform • … are widely used for a variety of tasks • … popular among Web developers • … have multiple implementations • … have an object system based (in part) on Smalltalk 16
  • 17.
    And yet •Python and Ruby feel very different • What can we learn from these differences? • What can we learn from the Python world? (And what can they learn from us?) 17
  • 18.
    General attitude •Ruby wants to give you freedom, to allow you to be creative and flexible, as in a natural language • TMTOWTDI, POLS • Python wants to restrict you, for your own good • "There should be one — and preferably only one — obvious way to do it." 18
  • 19.
    The result? •Python is • easier to learn • easier to debug and maintain • Ruby • offers you richer options • greater expressiveness 19
  • 20.
    Development process •Python Enhancement Proposals (PEPs) • Ruby could use such a system • Heck, Rails could use such a system 20
  • 21.
    Backward compatibility •Historically, Python upgrades were conservative • But not 2.x -> 3.x • Ruby was less conservative, breaking things (especially going from 1.8 to 1.9/2.0) • Maybe Python emphasis on compatibility and inclusiveness hurt the 3.x upgrade 21
  • 22.
    What is truth? • Ruby: Everything is true, except for false and nil • Python: Everything is true, except for None, False, 0, and empty data (e.g., '' or []) • So: 0 is false in Python, but true in Ruby! • But we all like #blank? and #present? in Rails… 22
  • 23.
    Everything is anobject… • In both Ruby and Python, everything is an object! • But in Python, some objects are more equal than others… • So you can't do this in Python: 5.times { puts "Hello" } 23
  • 24.
    Blocks • Rubypeople love blocks! • Python doesn't have them. • They create functions, and pass those • Or they use lambdas (or not) 24
  • 25.
    Namespaces • Pythonhas a single namespace for functions and variables. So x can be an int, a str, or a function • Ruby has two separate namespaces — one for methods, and one for data • Ruby's approach can lead to surprises! x = 10 # set a local variable self.x = 10 # invoke an attr_ method 25
  • 26.
    Reserved words •Python barely has any: True, False = False, True • Ruby lets us open built-in classes, but not this! 26
  • 27.
    Modern Python •Fine, modern Python outlaws this. But it allows: >>> str = [1,2,3] >>> type(str) <class 'list'> 27
  • 28.
    Scoping • Pythonhas clear rules for scoping: LEGB (local, enclosing function, global builtin) • Ruby's scoping rules feel natural, but the rules aren't easy to learn or remember. 28
  • 29.
    Indentation • Newcomersto Python hate the indentation rules • But I actually like them! • Easy to read • No annoying "end - end - end - end" all over • Easy to see where code begins and ends • That said, Ruby's syntax would never work with Python's indentation rules 29
  • 30.
    Parentheses • Neededin Python to invoke methods and create classes • Makes it easier to pass functions as parameters • Not needed in Ruby to invoke methods • Makes DSLs cleaner, easier to write and read • You cannot pass a method just by name; use method(:foo) • DSLs in non-Ruby languages look far uglier, and look like the original language, not a new one 30
  • 31.
    Explicit return •In Ruby, the value of the final line evaluated is the value of the method. We often don't say "return" • In Python, if you don't say "return", then your method returns None • I don't see an advantage to Python's behavior 31
  • 32.
    Attributes vs. methods • In Ruby, object state is private, and access is all done through methods. • Want to access data? Write a getter or setter • Or use attr_*, and Ruby will write them for you • In Python, object state is public • Getters and setters are discouraged • Want the logic of a getter or setter? Use a "property," which invokes a method when you access an attribute 32
  • 33.
    In other words • Ruby tries to make data look like methods • Method calls are the fundamental form of inter-object communication • Python tries to make methods look like data • Attributes are open, and thus there is less need for methods to access data • Besides, attributes exist in a single namespace 33
  • 34.
    Object model •In Ruby, the object model emphasizes methods and inheritance of those methods • What are your methods, and what are your superclass's methods? • In Python, the object model emphasizes attributes and "inheritance" of those attributes • What attributes are defined on an object, and what are define on its class? 34
  • 35.
    What is hardto learn? • Each object model leads to something that is hard for people to understand • In Ruby, you have to understand singleton classes (aka eigenclasses) • In Python, you have to understand how attributes work, including attribute scoping rules 35
  • 36.
    Multiple inheritance vs. include/extend • Python: Multiple inheritance is OK, if you do it right • Ruby: You won't get it right. Use modules!. • The inheritance tree is very easy to figure out • Modules allow for mixins, the only good reason for multiple inheritance 36
  • 37.
    for loops vs.Enumerable • In Ruby, we want to iterate over everything • Implement #each in your class • include Enumerable • Now you get map, select, and many other methods 37
  • 38.
    for loops vs.Enumerable • In Python, we also want to iterate over everything • We do that with "for" loops and other global constructs (e.g., comprehensions) • Our object plug into these constructs by implementing the iteration protocol 38
  • 39.
    list.sort's return type • Python's, list.sort returns None, not the list • In Ruby, we almost always return an object from a method, so that we can chain the method calls. 39
  • 40.
    Comprehensions • Pythonhas comprehensions: [str(x) for x in range(5)] [x*x for x in range(5)] [line.split(":")[0] for line in open('/etc/passwd')] 40
  • 41.
    Sets and dicts • Set comprehensions {word.strip() for word in open('/usr/share/dict/words')} • Dictionary comprehensions {line.split(":")[0] : line.split(":")[2] for line in open('/etc/passwd') if line.startswith("#")} 41
  • 42.
  • 43.
    Ruby is moreconsistent • In Ruby, we use the block syntax everywhere (0..4).map {|n| n.to_s} (0..4).map {|n| n * n} File.open('/etc/passwd').readlines. map {|line| line.split(":")[0]} 43
  • 44.
    The Ruby version Hash[File.open('/etc/passwd'). readlines. select {|line| line[0] != '#'}. map {|line| line.split(":")}. map {|row| [row[0], row[2]]} ] • Longer, but more consistent 44
  • 45.
    Easy metaprogramming •Metaprogramming is fun and easy in Ruby • Python permits it, but discourages such things • Most of the time, use decorators 45
  • 46.
    46 Oscar Felix (Python) (Ruby)
  • 47.
    你们有问题吗? יש לכםשאלות? (Do you have any questions?) reuven@lerner.co.il @reuvenmlerner http://lerner.co.il/ 47