Why Python doesn't need blocks
stupidpythonideas.blogspot.com
stupidpythonideas.blogspot.com
"But the complexity of any proposed solution for this puzzle is immense, to me: it requires the parser (or more precisely, the lexer) to be able to switch back and forth between indent-sensitive and indent-insensitive modes, keeping a stack of previous modes and indentation level. Technically that can all be solved (there's already a stack of indentation levels that could be generalized). But none of that takes away my gut feeling that it is all an elaborate Rube Goldberg contraption."
source: http://www.artima.com/weblogs/viewpost.jsp?thread=147358
EDIT: This was from an earlier proposal in 2006.
I really like blocks, but Python deliberately makes it harder to support those in return for not needing scope delimiters in the majority of code that isn't using blocks. It seems like a reasonable choice to me.
(And yes, not all one liners need it. I know.)
And list comprehensions seems like a kludge from a lack of real lambdas (map). So that is an extra concept.
Edit: Ruby doesn't have closures?!
Edit 2: 2nd paragraph of the linked article: "In Ruby, Objective-C, and C, functions are not first-class objects, they don't capture closures, and they can't be defined inline." For Ruby, that don't claim there are no closures at all. Got it.
You don't see the pattern often, as it's far less idiomatic than passing procs as a block, but you can do it.
Also, def is an expression in recent versions of Ruby. I don't remember exactly which version introduced it, but def returns the method that it created.
They added that in 2.1 Well, it was always an expression... in Ruby, every statement is an expression. But it always used to return nil. Now it returns the symbol of the method name. Still not as good as returning a method object, but since you can easily get the method object from the symbol, in practice there's no difference.
While blocks are nice to have, I've yet to see a good proposed syntax for them in Python.
Sure, but then again not all trade-offs make the right trade, err, off.
>It may be the right trade-off for some users and the wrong trade-off for others.
Well, then it matters how big are those groups relative to each other, and perhaps which one does something that's more important with the language and more tied to its core principles.
TIL that PHP is even scarier than I thought.
Anything utilizing an indent block must be a statement by the nature of the Python grammar, and since lambdas pretty much require returning a value (the new lambda) to be useful (and are thus expressions), they cannot be modeled as statements in Python, and therefore can't utilize indent blocks.
This is definitely an oddity of the Python grammar, where statements vs. expressions are entangled into how Python models indent blocks. Statements can contain expressions but expressions cannot contain statements.
Compare to Haskell, an everything-is-an-expression language which still supports indent sensitivity and multiline lambdas.
Guido just chose a wacky way to implement an indent-sensitive grammar.
As a lisper I could easily point my finger at ruby blocks and point out they're more complicated than just always using a function, but the fact is, in practice, it just doesn't matter. Ruby blocks cover 95% of the cases you hit in a pretty way, and when they don't you can still use lambdas!
Now macros, those are a better solution to what blocks, but it's a 95% solution, so I've stopped caring.
That's what's so nice about how Ruby does it; you don't need to understand any of that to use blocks. As you learn the language, you learn those things, but none of them are required to get started.
I disagree. Blocks are the fundamental building blocks (!) of various constructs that are derived from them. They're 'thinner' than lambdas, procs and methods. Blocks alone are only part of a system, which, together with binding allows one to build lambdas, iteration constructs, and various other features. Comparing them head-on to functions or lambdas therefore makes no sense. For example, where Python has 'hardcoded' generator expressions, a Ruby developer can leverage blocks to make his own generators. The same goes for features such as with, which are syntactically defined in Python, but which are customary to simply implement with blocks in Ruby. Combining instructions such as next and continue with yield return values and arguments, along with rebinding allows one to define new constructs and syntaxes without paying the price of Lisp's purity (which basically mandates that the language is made of sexprs).
Of course Python actually does have blocks (lambda), they're just very limited, so it's a strange article none-the-less and to a non-Python user come across as a bit of a hack so that you aren't constantly passing method pointers around. But maybe that's just me.
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.
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.
This is, to me, the core of the problem.
> The Promises/A spec from CommonJS defines Promise.then as taking three (optional) callbacks: fulfilledHandler, errorHandler, and progressHandler. The code above is passing two of them at once.
Shoehorning things from different realms (e.g desperately trying to write JS in Ruby or vice-versa) is not a good idea.
Instead of either:
db.select_one(sql, thingid)
.then((proc {|rowset| rowset[0]['foo'}), (proc {|err| log_error(err)}))
or: db.select_one(sql, thingid)
.then {|rowset| rowset[0]['foo'}
.then(nil) {|err| log_error(err)}
Why not do: db.select_one(sql, thingid)
.then {|rowset| rowset[0]['foo'}
.else {|err| log_error(err)}
.each {|whatever| the_progress(callback_is)}
Also, method(:log_error) will happily turn the method into a proc.This last case is actually extremely important. Contrary to what the author claims, functions and methods are first class in Ruby. The problem is that in Ruby's grammar an identifier without parentheses is a method call if that identifier does not resolve to a variable. Therefore, you cannot refer to an existing function by its name, merely because it would resolve to a call.
Therefore the difference between those is purely syntactic:
Python Ruby
foo method(:foo)
foo() foo
Also, this[0] explains how &:to_i works, which can be leveraged with great success, should one implement the promise class in a sufficiently idiomatic way (turning the above log_error reference into &:log_error)[0]: http://ablogaboutcode.com/2012/01/04/the-ampersand-operator-...
For example, Smalltalk blocks have been "upgraded" to closures in most dialects (and not implementing them as closures in the first place was not a choice of semantics, but one of implementation simplicity).
Also, Swift closures are the same as Objective-C blocks.
+(void)logMe: (void (^)(void))block
{
NSLog(@"object of class: %@",[(id)block class]);
}
Called from Swift with a closure: func applicationDidFinishLaunching(aNotification: NSNotification?) {
logger.logMe( { } );
}
Results in: 2014-06-30 19:55:37.973 SwifTest[94782:303] object of class: __NSMallocBlock__
So much ado about nothing?Then I went back to a ruby project, and realised - the language I used to adore kinda sucks, because it's _so_ un-functional.
What an odd appeal to authority...