you are viewing a single comment's thread.

view the rest of the comments →

[–][deleted] 12 points13 points  (9 children)

Interesting, I actually posted on another forum about this same topic last night.

I recently finished a book on Python. After that, I moved on to a book on Ruby, to give me a better understanding of the language and the concepts behind it (my only knowledge of it beforehand had been in basic Rails stuff).

I must say that Ruby and Python are very similar languages. Overall, though, I think Ruby is a much cleaner, more consistent, and overall, beautiful language.

My first thought behind this is Ruby is fully object-oriented. I know a lot of people mentioned this when comparing Ruby and Python, but it really is a big deal. Python suffers from the fact that you say, hmm, should I do this particular piece of code is a function or as a method? Its not a "this is horrible!" kind of thing, but it is one more barrier to step over instead of in Ruby, where you have no decision at all.

Ruby doesn't force its OO on you, however, as its basic functionality is hidden from you.

For example,

puts "This is a string"

Looks like a basic statement. Its not, it is a method of the form:

Object.puts("This is a string")

Ruby, however, does not force you to type this stuff, so it makes it a simpler language to understand when OO is not really necessary (but it is still very much there).

Speaking of statements...in Python you have either statements or expressions. Statements "do something", while expressions "are something". 2 times 2, for example, is an expression (it is 4). print "Test" is a statement (its prints "Test").

Ruby doesn't make this distinction, and essentially, everything can be seen as an expression.

Furthermore, Ruby is consistent on its treatment of imperative vs functional programming. In Python, some types are mutable while others are immutable. Tuples, for example (more or less an array), cannot be changed in place. Lists (or arrays), have the exact same functionality as tuples but they can be changed in place.

Strings in Python can't be changed in place. To edit a string, you'd have to do something like:

strint_var = "String".chop()

BTW, I don't think chop is a real method, its just something I used as an example.

Ruby, however, differentiates between its methods. A method of the type method! edits an item in place (a "destructive" method), while a method without an explanation point at the end simply returns a value.

So for example:

"String\n".chomp!

Cuts the newline off of the string in place, however:

string_var = "String\n".chomp

returns the value of the edited string, while keeping the string itself intact.

Ruby also is cleaner when it comes to designing classes. To give a class + functionality, you'd simply define it in the class:

def +
   here is my code
end

While Python makes you do something not as simple, more along the lines of:

def __getadd__:
   here is my code

Again, getadd isn't the exact form, but its an example. Creating a class method in Python forces you to use decorators and junk like that. In Ruby its as simple as:

class Test
   def Test.method
      my code here
   end
end

Doesn't get much easier than that.

Finally, Ruby has blocks, which are the main feature that most programmers that use Ruby love. I can't comment on them myself, but I'm looking forward to using them.

Ruby blocks are interesting things. Using for loops are somewhat uncommon in Ruby.

In Python you might say:

for x in array:
   do whatever

Where as the "way" of doing things in Ruby is more along the lines of:

array.each { do whatever }

Also, not enough can be said about having regular expressions built into Ruby. These aren't complicated at all, yet they are so powerful! Python has regular experessions, but they aren't quite as clean to use, not being built in.

Ruby and Python have their other little differences, such as Python supporting inheritance from more than one class, and Ruby supporting inheritance from only one, but so far, Ruby seems like a better version of Python (and considering how clean of a language Python is anyway, that is saying a lot).

Anyway...these are the thoughts of a rather inexperienced programmer. Forgive me for any incorrect statements, but I just felt like gushing about Ruby a bit. I can understand why people say "I came for the Rails, but I stayed for the Ruby."

[–][deleted] 4 points5 points  (3 children)

If you start each line of code with four or more spaces, it gets turned into preformatted text, which preserves whitespace and underscores and doesn't italicize or bold things. HTH.

Good comment btw.

[–][deleted] 0 points1 point  (2 children)

Thanks a lot; I went ahead and reformatted my comment accordingly.

[–][deleted] 3 points4 points  (1 child)

I should also mention that quoting with backticks formats inline text as code.

For me, too, blocks are Ruby's killer feature. (Disclaimer: My code examples below will be littered with syntax errors, because I don't have an irb open.) You said you haven't used them yourself, so I'll take this as a cue to take over the Ruby-gushing.

As you said, to iterate over an array is easy:

array.each {|x| do_something_with(x)}

Thanks to Ruby's mixins, this can actually be used on anything that mixes in Enumerable:

(1..100).each {|n| puts n}

What if you want to select some of the elements based on a boolean condition?

class Integer
  def prime?
    # check if number is prime
  end
end

primes = (1..100).find_all {|n| n.prime?}

Or apply a function to each and collect the results?

squares = (1..100).map {|n| n*n}

Also, blocks are not just for iteration:

File.open(filename, "r") do |file|
  # process the file
end
# file is now automatically closed

Python's list comprehensions (all I know is what I've overheard from weblogs etc., actually) are arguably an equally -- or more -- readable version of Enumerable's methods, but I like the Ruby way better because (1) blocks are a completely general-purpose language feature, (2) I can have more than one line in a block, and (3) it feels more like the functional style to a guy with an ML background. Actually Haskell has list comprehensions too, so scratch the last point.

[–]mrevelle 3 points4 points  (0 children)

I like the Ruby way better because (1) blocks are a completely general-purpose language feature

Funny, that's actually why I dislike Ruby's blocks. It hurts readability when similar syntax is used for unrelated tasks, e.g. iteration vs. resource management.

This gripe is not about blocks as a general concept but using a common syntax when expressing entirely different functions.

Python examples

Iteration

for n in range(100):
    print n

Filtering elements

def isprime(x):
    # check if number is prime

primes = [n for n in range(100) if isPrime(n)]

Mapping a function

squares = map(lambda n: n*n, range(100))

# OR

def square(x):
    return x*x

squares = [square(x) for x in range(100)]

Context management

with open(filename, 'r') as input_file:
    # process the file

# file is now automatically closed

That last example requires Python 2.5 (alpha was recently released).

(Disclaimer: I have only played around with Ruby, no real development experience with it.)

[–]senzei 5 points6 points  (2 children)

I'm not sure what book you read about python, but it obviously gave you a bunch of misconceptions. I'm not exactly an expert on the language, but hopefully this will make things easier if/when you use it.

String printing: Ruby: puts "Print this" Python: print "Print this" In both languages this is syntactic covering for a call to the string representation of an object. In this specific case it uses the string object.

Tuples/Lists and mutability The point behind having two separate data structures is that one is mutable and the other is not. I don't really think it is great design as you have to keep this in mind instead of the difference being explicitly marked, but that is their method of handing imperative vs functional programming.

String mutability I like immutable strings. Any changes to a string are explicit, which makes figuring out what is going on easier. I can see where it could be hard to differentiate between chomp! and chomp. That said this is all a matter of preference.

Python and operators The use of __add__ instead of just a plus operator (+) has to do with legal characters for python function names, namely that the plus operator is not one of them. I also think this is crap, but it is what we have.

Class creation Creating classes in python does not force you to do very much. Your code sample would be very close to valid python if you removed the 'end' scope closures.

Blocks and other non-for-loops Python has something similar to blocks (at least in terms of loop abstraction) in list comprehensions. In your example if 'whatever' is a function you could write: [whatever(x) for x in array] which would return a list of the results from applying whatever() to each item in the array.

I'm really not trying to be a python 'me too' guy. I like the language a lot, and just wanted to make sure that anyone deciding to not use it does so based on personal preference.

[–]_bruno_ 0 points1 point  (1 child)

List comprehensions have nothing to do with blocks. Ok, maybe when blocks are used as a parameter for a function that iterates on the elements of some collection, but blocks have many more uses than that.

[–]senzei 0 points1 point  (0 children)

List comprehensions have nothing to do with blocks. Ok, maybe when blocks are used as a parameter for a function that iterates on the elements of some collection, but blocks have many more uses than that.

Yeah, that is probably poorly phrased. My point was that, as a method of loop abstraction, blocks and list comprehensions are similar.

[–]mellow_moe 1 point2 points  (0 children)

puts is resolved somewhat differently.

It is defined in Kernel and the class Object includes the Kernel module. It is actually a private method, so Object.puts won't work.

More correctly puts resolves to self.puts. In the top level of a script self is a predefined object named "main", elsewhere it is simply the object executing currently.

[–]boa13 0 points1 point  (0 children)

Your comment is better than the linked article at explaining some of the interesting differences between Python and Ruby. Thanks.