|
Sure! Broadly speaking, I think Python emphasizes a combination of features that lead to code that isn't very composable or decoupled, but without the error-checking benefits you might get in a language like Scala. For example, consider implementing complex rational numbers. If you have a complex number type, and a rational number type, it should be relatively easy to combine them. Julia does this with literally 11 lines of code in Rational.jl, and 0 lines of code in Complex.jl . In Python, this is extremely difficult, to the point that nobody does it – you would need to restructure the class hierarchy, and you can't do that without access to both. Another example is the lack of extension methods. For example, if you want to add a bit of functionality to a string or a sqlalchemy engine, you can either add functions (which have a different syntax) or inherit and follow the awful "MyString" pattern. Python chose to emphasize list comprehensions over map + filter. The problem with that is that you now have syntax that doesn't generalize to other collections, especially custom collections. Some patterns like async/await, decorators, and with syntax encourage hardcoding decisions when writing a function, as opposed to when using it. This makes your functions less flexible and means you have to write more of them. E.g. consider Julia's do-block syntax[1], which is very similar to Python's with but based on function composition and far more general as a result. Or compare Julia's @spawn to Python's async/await. [1]: https://docs.julialang.org/en/v1/manual/functions/#Do-Block-... |
It's really not difficult; yes, it's more verbose, sure.
> Python chose to emphasize list comprehensions over map + filter. The problem with that is that you now have syntax that doesn't generalize to other collections, especially custom collections.
Python has map/filter/reduce and they work fine. Comprehensions (and genexps) are more concise and cleae for 95% of use cases, I find, so I think the right choice was made there, though I do think people do tend to reach for them sometimes when map, filter, and friends are more appropriate.
> consider Julia’s do-block syntax[1], which is very similar to Python's with
It's more similar to Ruby’s block notation than Python with; it constructs an anonymous function and passes it to another function being called. It is true that with multiline lambdas at all, much less a convenience notation for passing them to other functions, with notation would be superfluous.
> Or compare Julia’s @spawn to Python’s async/await.
Why? They solve different problems. @spawn is equivalent to Python’s concurrent.futures.submit, and it’s buddy fetch() is concurrent.futures.Future.result(). Python has had those longer than it has async/await.