This post originated from an RSS feed registered with Python Buzz
by Jake Cutter.
Original Post: Functions versus blocks
Feed Title: Convince me to use Python
Feed URL: http://convincemetousepython.blogspot.com/atom.xml
Feed Description: Learning to love Python...one day at a time...
In response to my last thread, someone answered with the following: A problem I have with Ruby is that it has been infected with the same "everything must be in a class" nonsense that Java has. OOP is great, but sometimes having free-standing functions are more useful, especially functions that can be be applied to unrelated classes. "len" is a good example of this - because len is a function and not a method you can do things like this:
If 'len' was a method you would only be able to do this if all the objects that you want to take the length of inherited the 'len' method from a common base class (or mixin, in Ruby). This goes against the whole idea of duck typing.So in this Python example, if I'm understanding it (and my Python studies) correctly, len is simply a reference to the function "object" that encapsulates logic that determines the length of something. Here's the official definition from the Python docs:
len(s): Return the length (the number of items) of an object. The argument may be a sequence (string, tuple or list) or a mapping (dictionary).
Ok, so the logic contained in the function object pointed to be the reference "len" gives us the ability to determine the length of a string, tuple, list or dictionary. Great.
Why though is this any better than Ruby? To do the same thing in Ruby, you'd do something like:
So in the Python version, len is a builtin function that is passed to map...in Ruby, I simply create a block and pass it to map.
Perhaps the poster didn't realize you can use rescue in this way? It allows you to call length on *any* object and returns nil if that method exists. You could also do:
I'm sure one performs better than the other under the sheets, but I haven't tested to verify.
Is Ruby's approach better than Python? In this simplistic example, probably not. However, I think that Ruby's block syntax is more explicit and indicates meaning at the point of usage. Let's say I wanted to do more than just return length...what if I wanted to do some type checking as well?
In Python, I'd have to create a method first to wrap the desired functionality:
def conditional_len(obj): if isinstance(obj, list): return len(obj) else return None
a = [1, [2, 3], 4] map(a, conditional_len)
In Ruby, it's (IMO) more obvious what we're trying to accomplish:
a = [1, [2, 3], 4] a.map do |one| if one.is_a? Array return a.length else return nil end
So I'm not sure I follow the argument here. Why exactly is Python's way advantageous compared to Ruby's? Can anyone shed some light?