That's the wrong question to ask in a language debate. The question should be "This thing I can do in language X, how would I do it best in language Y, and how do they compare in tradeoffs?"
I've seen Rubyists complain about blocks a number of times. I've also seen complaints about how Python isn't truly object oriented because not everything is an object (false, actually) and because "len" is a function instead of a method (true technically, but len itself is actually a generic function that uses various OO protocols to determine the answer), though I haven't seen this in some years now.
In reality Ruby and Python are so close to each other on the grand scale of languages in the world that you can barely slide a piece of paper between them... the syntaxes are pretty different but the capabilities are almost identical.
list
.map (el) ->
el * 2
.filter (el) ->
el % 2 == 0
I suppose in this case a list comprehension would work too: list = [el * 2 for el in list if el % 2 == 0]
... but as these things get more complex, inline functions become really useful.It's also nice for various DSL purposes, e.g. unit tests with Mocha
it 'should be able to multiply a number', ->
a = 2
b = 3
(product a, b).should.eql 6
Which in Python would become def test():
a = 2
b = 3
assert product(a, b) == 6
it('should be able to multiply a number', test)
Probably doesn't look that impressive, but once you're used to them from other languages, it gets to be really frustrating to not have them in Python.You also start noticing that Python has a couple of features that are actually entirely unnecessary if only you'd have multiline inline functions. For example, you could do away with decorators and `with` blocks.
view = authenticate (req, res) ->
res.send 'hello world'Python's got a lot more capacity for "DSLs" than it may immediately seem. Writing "it.shouldBeEqual(product(2, 3))(6)" would be quite easy in Python, actually; it's got all sorts of overloads and you can return all sorts of excitingly overloaded values. You don't see it because it isn't considered "Pythonic", not because Python can't do that.
(And I'm with Python on this. Those "fluent" APIs spend way too much effort being cutesy and verbose and not enough effort being simple, transparent, and composable. It looks good in the common case but when you write good test code it stops looking so good when you're writing map(it.shouldBe.eq, testTable), and the fact that the cutesy "fluent" style takes even a baby step in the direction of discouraging anything like that is an immediate disqualification in my book. Oh, don't try to defend it by saying you can still do the map I said... I've got enough experience in such things myself to know that it's actually a bigger problem than I'm making it out to be, not a smaller one.)
function definition: (define (f x) (+ x x)) => (define f (lambda (x) (+ x x)))
variable binding: (let ((x 1) (y 2)) (+ x y)) => ((lambda (x y) (+ x y)) 1 2)
delayed evaluation: (delay (display "foo")) => (lambda () (display "foo"))
and lots more...
But they also sometimes are convenient when you have a function or procedure that expects the same as one of its parameters, but said function doesn't already exist, and there isn't a simple composition of higher-order (functions that take or return functions) functions that does what you want.
For example, say you wanted to multiply a list of numbers by their squares (this is in Racket):
(define (sqrmult n) (foldr (lambda (x y) (* (sqr x) (sqr y))) 1 (stream->list (in-range 1 n))))
See you don't have to name the function?
Having to do "def promise1_success" ... "def promise1_error" ... etc all the way up through 5 promises is a pain.
For event-emitter like things, it's also great to have anonymous functions.
For example, in nodejs, you might have reader.on('data', function(chunk) {}); .... You gain no further insight into what that function does if you have "def handle_reader_data" and then use it once there. There are many cases where you don't need the function name for clarify, and it just clutters the current scope to have it not be anonymous.
Code is also easier to follow if functions like that, used once only as a callback, are immediately defined where they are used, not lines above. When reading code that has a named function above, I'd have to skim the function the first time, see it used, and then trace back through it above knowing what was calling it.