
Python as a declarative programming language (2017) - akashtndn
https://www.benfrederickson.com/python-as-a-declarative-programming-language/
======
mlthoughts2018
I was sad that Cython was only given a fleeting nod at the end and numba
wasn’t even mentioned. I might even go so far as to say that Cython is the
most user-friendly way to write new _pure C programs_ that there is. If you’re
about to write some greenfield project in C, seriously consider using Cython,
even if you have no desire for any Python entrypoints in the final product.
Numba as well is quite impressive: between jitclass, deferred_type, and
facilities to target GPUs, it’s crazy how much speedup you can get with little
extra code.

Overall I think people don’t clearly state the speed trade-off Python
presents. Everyone focuses on the “40 times slower” part and nobody points out
that “equivalent program in C++” is a glib false equivalence, because a truly
equivalent program would have to offer all the same run-time dynamic type
manipulation and nearly arbitrarily modifiable object instances involved.

What Python really proposes is this: “I’ll give you 100x more flexibility in
exchange for 40x worse performance for certain classes of operations.”

Don’t want the 40x slowdown? Das cool. Code around it by using extension
modules that let you specify homogeneously typed contiguous memory arrays (or
bare metal structs like with ctypes or numba’s jitclass), or let you bypass
CPython overhead because e.g. you know you don’t need the flexibility offered
by the data model looking up a generic python function to call for an __add__
operation, and instead you can arrange for a GIL-releasing call to a pure C
function. And so on.

I guess my point is that the story should be “look what Python gives you” and
then “this flexibility had a cost.”

But instead it always feels more like, “this C pseudocode for this tight
algorithm looks superficially similar to Python syntax for that algorithm ...
but oh boy look how much slower Python is!” —- which, apart from a possible
surprise when you have never looked into Python before, should be of interest
to badically no one.

~~~
dkersten
> a truly equivalent program would have to offer all the same run-time dynamic
> type manipulation and nearly arbitrarily modifiable object instances
> involved.

In actual production code, I rarely need this though. I mean, sure, for
framework code, but in C++ I can do quite a lot with the standard library and
templates. Sure it’s not so runtime flexible as Python, but for normal
production code, I’ve rarely found it necessary. Don’t get me wrong, I
absolutely prefer Python for most of the use cases that it’s conmonly used
for, but I don’t agree quite agree that the quoted text above matters for most
uses.

> What Python really proposes is this: “I’ll give you 100x more flexibility in
> exchange for 40x worse performance for certain classes of operations.”

Have you used a recent version of C++? I think the 100x might have been true
15 years ago, but, while Python has a lot, lot more runtime flexibility,
modern C++ is a pretty productive environment, without sacrificing
performance.

I’m not arguing that Python isn’t more flexible, especially at runtime, or
that it’s not more productive. Of course it is. But you’re paying a
performance premium for it and I don’t think the productivity gap is as large
as the performance gap anymore.

With all that said, I do agree with your overall message. Python gives you
productivity and flexibility and it’s important to focus on that rather than
performance and, as you say, Cython gives you options when you do need
performance. But the difference between Python and C++ nowadays, for normal
production code, isn’t that huge anymore in my opinion.

Of course, there are plenty of reasons to prefer Python though: fantastic web
frameworks and batteries included libraries, fantastic community, fantastic
documentation to name a few.

~~~
mlthoughts2018
I won’t be able to address all the points. But in my experience, C++ has been
going in the wrong direction in terms of simplicity or productivity. Modern
C++ is drastically more complicated and riddled with deep esoterica. The
flexibility benefit modern Python gives is probably more like 1000x, further
mitigating many cases when there are concerns about the
flexibility/performance trade-off.

Just for one example about what I mean with modern C++: <
[https://bitbashing.io/std-visit.html](https://bitbashing.io/std-visit.html)
>.

This example is relevant because you mentioned you feel you never need
Python’s flexibility in the day to day. But in Python (much like in many
functional languages), the entire idea of the visitor pattern can be boiled
down to map() —- just one function call! If you want to specialize this for
your own data type, you can very easily implement the iterator protocol, often
simple __iter__, __getitem__, and __next__, which themselves could use e.g.
numba to iterate some homogeneously typed tree class with pure C performance
characteristics, or a sum type (like with Cython fused types) as in the
std::visit example, etc.

The point is that the data model’s flexibility makes this trivial, rather than
convoluted. In the cases when I’d care about this pattern, it would be no
contest that Python offers hugely improved productivity.

So it’s not just naive flexibilty of modifying object instances, but the
bigger picture of flexibility in the data model overall.

~~~
cpitman
> The flexibility benefit modern Python gives is probably more like 1000x

If true, that would mean that a 1 year C++ project could be done in 2 hours,
and a 10 year project in half a week.

~~~
mlthoughts2018
Development time is not the same as flexibility, particularly because, as
others have pointed out in comments, the lack of flexibility in C++ usually
manifests itself by the choice to exclude huge swaths of feature sets.

I see this Python advantage meaning in C++ I have to give up more
possibilities if I want to restrict myself to a subset whose complexity can be
reasonably managed.

Just think of how often people even suggest C++ without exceptions. This is a
mark of inflexibility that people view the complexity cost of these techniques
as too high, and so must write code that intentionally cannot use them (and so
you have to contort even more to imitate their intended behaviors).

This is a much more important thing than mere developer time, which is a
shallow way to look at it.

------
andybak
I've always been a fan of Django's "Declarative for most stuff. Procedural
when you need it" approach. Models and forms are a good example but it
permeates the whole framework. It's largely an case of favouring composition
over inheritance combined with sensible defaults but it feels declarative for
the common cases.

~~~
dkersten
I agree, I think this is a good approach. Common things should be super quick
and easy, but when you need to go further, it should get out of the way.

------
orf
Python is a great language for this kind of super-glue code. The pure
tensorflow snippets are rarely run in isolation, and python makes retrieving,
loading and munging data pretty simple when you tap into its rich ecosystem of
scientific and utility packages.

Python has always been about dipping down to C when needed - just look at the
various stdlib features like namedtuple and lru_cache that had optimized C
versions introduced once the python versions were deemed useful and
performance critical.

A commenter below seems outraged about the torch->pytorch change, but really
the GitHub contributions and adoptions for each speak for themselves

------
Animats
Where's the "declarative" part here? It's common to do number crunching in
NumPy with Python as the control layer. But the Python code is imperative.

~~~
joshuamorton
Numpy is declarative in the sense that it is vectorized.

~~~
Animats
?

~~~
joshuamorton
Instead of explicitly writing loops, you decalre an operation like add, and it
is looped over a vector for you.

~~~
Animats
That's just application. "Do this to all that stuff". Imperative, but possibly
parallel.

------
myWindoonn
For faster Python, try PyPy. It's very compatible, very fast for many
workloads, and has been constantly receiving interesting new work for over a
decade.

------
magicalhippo
First I saw of this was about 9 years ago, with
[https://fenicsproject.org/](https://fenicsproject.org/)

The Python "front-end" allows you to write something which looks very much
like the math you're trying to solve. When evaluated, the Python code
generates specialized C++ code for a Python module which is in turn compiled
and linked back in, and then the C++ code is executed producing the results.

Guess this is old news now but I was pretty blown away by it back then.

------
plg
tldr: Vectorize your code. Good advice not just for Python but other
interpreted languages like MATLAB and R.

