The examples in the article appear to mainly revolve around numerical calculations, so I suspect the target audience is people doing scientific computing who need to "break out" into a compiled mode for heavy CPU calculations (similar to numba or even Julia) from time to time when their calculations aren't vectorisable.
I've noticed a split between the needs of software engineers on the one hand, who need expressive abstractions to manage systems of extensive rather than intensive complexity, and scientific programmers or model-builders on the other hand, who are much more likely to just use the primitives offered by their language or library as their needs revolve around implementing complicated algorithms.
Yes, it does static checks at compile time. The only thing that we do at runtime (imperfectly right now, eventually perfectly) are array/list bounds checks, integer overflow during arithmetic or casting and such. Those checks would only run in Debug and ReleaseSafe modes, but not in Release mode. So for full performance, you choose the Release mode. For 100% safe mode, you would need to use ReleaseFast.
- does it deal with the unholy amounts of dynamism of Python? Can you call getattr, setattr on random objects? Does eval work? Etc. Quite a few Python packages use these at least once somewhere...
It deals with it by not allowing it. We will support as much as we can, as long as it can be robustly ahead of time compiled to high performance code. The rest you can always use just via our CPython "escape hatch". The idea is that either you want performance (then restrict to the subset that can be compiled to high performance code) or you don't (then just use CPython).
If you have some ideas how to best communicate this, let me know.
The best approach that I know right now is to say that we support a strict subset of Python, and if it compiles, it will be fast. The rest of Python you have to call explicitly and it will be slow and you get a CPython dependency in the binary that we generate, but you can do it. That way there is a clear distinction what gets compiled via our compiler into high performance machine code and what gets dispatched via CPython (it will eventually get "compiled", but it will just call CPython).
Two questions come to my mind:
- presumably, since it is compiled, it does static checks on the code? How many statically-detectable bugs that are now purely triggered at runtime can be eliminated with LPython?
- does it deal with the unholy amounts of dynamism of Python? Can you call getattr, state on random objects? Does eval work? Etc.