Torn in two - Pythonist

Reference:
http://blade.nagaokaut.ac.jp/cgi-bin/vframe.rb/ruby/ruby-talk/178606

I'm a recent convert myself. I was convinced by this blog that I found via
O'Reilly:
http://www.oreillynet.com/ruby/blog/2006/01/bambi_meets_godzilla.html

I will finish a project at work, where I use a powerful, pre-existing Python
interface to a C++ library. Then, sadly, I'm done with Python (as soon as
Ruby2.0 is out, fixing some annoyances).

The best place to look is The Ruby Way. There is a 20-page appendix for
Python converts, and another for Perl. Also read the 50 pages of Chapter 1,
especially the gotchas under "Things to Remember". That's really all you
need, coming from either Python or Perl. (It will take some time to
understand blocks and continuations, but you don't have to use them.)

There is a list of some differences with Python in [ruby-talk:*01528*] *ruby
<=> python*
http://blade.nagaokaut.ac.jp/cgi-bin/vframe.rb/ruby/ruby-talk/1528

By far, the biggest gotcha is that 0 does not equal false. Another is that
some mutating functions return nil when they change nothing, so you get
unexpected exceptions from strung-together expressions like:
  foo().gsub!().bar()

The number of similarities is amazing, partly because Ruby and Python borrow
from similar sources, and sometimes each other. E.g.

  * raise RuntimeError, msg
  * yield
  * def/class
  * for i in list
  * [1,2,3]
  * *args (and keyword args in Ruby2.0)
  * default function parameters
  * '.' for method calls

I've put together my own table of some differences. Semicolons indicate
related lines. Otherwise, separate statements represent other ways to do the
same thing. (Hopefully, the HTML formatting works.)

  Python
Ruby
  type(42) -> <type 'int'>
42.class -> Fixnum
  1e6
1.0e6
type(1e6) -> <type 'float'>
1.0e6 # not 1.e6

1.0e6.class -> Float
  "Hello, %s" %(name)
'Hello, %s' %s(name)
type('') -> <type 'str'>
"Hello, #{name}" # not single quotes

''.class -> String
  "Hello\\backslash \n newline"
'Hello\\backslash \n no newline'
  print func(x)
puts func x
puts(func(x))
puts func(x)
puts(func x)
  a = 4
A = 5
a = 4 # lower case
  class C: pass
class c: pass
class C end # upper case
  NOT_CONST = 5;
NOT_CONST = 6
CONST = 5;
CONST = 6 -> warning (upper case)
  var
global: $var
instance: @var
classvar: @@var
  None
nil
  False, None,
[], {}, 0, ''
false, nil, FALSE, NIL # all others are true
  arr = []
arr = list()
arr = ()
arr = tuple()
arr = []
arr = Array.new
# no tuples, but ...
arr = [1,2,3].freeze
  assoc_arr = {}
assoc_arr = dict()
assoc_arr = {}
assoc_arr = Hash.new
  a = {};
a[42] -> IndexError
a = {};
a[42] -> nil
a = Hash.new(2001);
a[42] -> 2001;
a.keys -> []
  if x:
  do_something()
elif y:
  do_something_else()
else:
  do_anything()
if x # no colons
  do_something
elsif # Note spelling
  do_something_else
else
  do_anything
end # Must have

do_something if x # no 'end' here
  while x and y:
  do_something
while x and y
  do_something
end

begin
  do_something
end while false
# Here, do_something occurs once!
# (Matz deprecates this usage.)

do_something while false
# Here, do_something never happens.
  result = os.popen(command).read()
result = `#{command}`
results = IO.popen(command, 'r').gets
  re.compile(stuff)
Regexp.new(stuff)
/stuff/
%r{stuff}
  regex.search(s)
s ~= regex
# returns position
# Note: 0 is not false
  return x
return x
x # 'return' is not needed
  class Dog(Animal, Friend):
  normal = 0
  def __init__(self):
    self.happiness = Dog.normal
  def wag(self, speed):
      self.happiness = speed
class Dog < Animal
  @@normal = 0
  def initialize()
    @happiness = @@normal
  end
  def wag(speed)
    @happiness = speed
  end
end
  try:
  try:
    do_it()
  finally:
    undo_it()
except RuntimeError, exception:
  print exception
except:
  print "Unexpected"
else:
  print "No exception raised."
begin
  do_it()
rescue RuntimeError => exception
  puts exception
rescue exc
  puts "Unexpected", exc
else
  puts "No exception raised."
ensure
  undoit()
end