Pyright: Static type checker for Python
github.com
github.com
I think they're clearly writing this for vscode, right? I hope they are at least. Having spent the last decade and half writing Python code, I have completely stopped enjoying writing Python code (even typed Python) because of how good TypeScript and the VSCode typescript experience is. It doesn't even sort of compare.
At this point I just want pretty much the same thing that happened to JS to happen to Python: For MS to make a Python superset with good type hinting (not the atrocious pep484 syntax) which compiles down to Python.
… and wasm. Which compiles down to Python and wasm.
from typing import TypeVar
T = TypeVar('T')
in every module where you want to parametrize a type.
(not sure how that works with 3.6+'s unevaluated annotations. that's what my linter thinks)also callable types are really ugly... this:
Callable[[Foo, Bar], Baz]
vs something like `(Foo, Bar) -> Baz` is just yuckputting constraints on a type is pretty ugly too iirc, i think it looks something like
F = TypeVar(bound=Foo)
def bar(a: F, b: F) -> F: ...
hacking type annotations into the language's existing syntax is hard :(If you have a function that takes `(Foo, Bar) -> Baz`, What you really have is a function that takes in a FoobarBazifier.
So name your function-interface:
FoobarBazifier = Callable[[Foo, Bar], Baz]
def my_func(cb: FoobarBazifier) -> Baz:
...
This is pythonic, in the same way that preferring named functions over lambdas (and therefore not having a single character lambda syntax) is pythonic. Its controversial and people dislike it, but it is nice.It also has the side effect of letting you Subclass the interface if you want to (via NewType), so that if you have multiple functions that match the same signature but fulfill different interfaces, you can name the interfaces differently and use them in different places.
Java mostly enforces this because you have to define an explicit interface and class for your callbacks (or you did until java 8), this is essentially the same thing, but with 1 line of boilerplate instead of 25 across 3 files.
- Imports everywhere. Even basic types (list, dict, set) have to be imported
- Basic types don't share the same casing as the actual types they represent (Set vs set, Dict vs dict, List vs list)
- Awful support for enums.
- Syntax is generally ugly. Typescript got everything right; it's intuitive, clear, and scales pretty well even for complex types. I'd be happy if they just copied typescript syntax.
- Types have a runtime impact.
Do you mind expanding on this, and what could be done differently?
x: float = 1.0
instantiate?Complicated closures are often more idiomatically as classes where the aggregate type would be a class member.
If you are just calling the enclosed function then of course this does not happen. Compare:
def mytype():
print("!")
return dict()
def closure():
def enclosed(x: mytype()):
pass
return enclosed
print("Calling the closure")
for i in range(10):
closure()
print("Calling the enclosed")
f = closure()
for i in range(10):
f(0)
Note that using closures is almost always faster in Python than classes, because accesses to enclosed variables are done through offsets instead of attribute lookup (this gap has been somewhat closed, but is still significant in some cases; arguably almost all of these cases indicate that you are using either the wrong language, or the wrong implementation). So adding overhead to closures can be a somewhat valid reason to avoid using these annotations.Reading and writing types should be fast, agile, easy and effortless. Only way to acheive that is having it as close the usage as possible
Althought now annotations don't have a runtime cost anymore since the y are lazily evaluated.
* https://github.com/Microsoft/vscode-postgresql * https://github.com/dbcli/mssql-cli
Only issue I see immediately is it does not use the default sys.path that the vs-code-configured python interpreter uses, so it cannot resolve some of the packages I'm using.
But overall, very nice.
There's also soutaro/steep[2] which looks really promising and is available now.
[0]: https://sorbet.run
[1]: https://www.youtube.com/watch?v=uFFJyp8vXQI (slides: https://sorbet.run/talks/StrangeLoop2018)
ed: to the degree that the man himself is adamantly against them in his language (except as perf hints) https://bugs.ruby-lang.org/issues/9999#note-13
See also mypy's recent blog post on plugins (which are also used for supporting Python 3.7's dataclasses, which are quite dynamic as well): http://mypy-lang.blogspot.com/2019/03/extending-mypy-with-pl...
If I compare that experience to when I switched from JS to TypeScript, it's like night and day. TypeScript is designed to work well with development tools and already existing libraries, while Python's static types feels designed by someone who never worked with static types while completely ignoring code patterns used in existing libraries.
I know which of those environments I would prefer... it's not node. It makes total sense for VS Code though, so fair enough.
I could understand if the goal was "to easily run within VS Code".
Can anybody explain to me why people seem to prefer using unsafe and interpreted/slow languages (Python, Ruby, Javascript... which is only fast now because companies have invested millions on it) and then spend a ton of resources writing "type checkers" for these inherently unsafe languages (Typescript, Pyre, Pyright) Why don't they simply use languages that are already safe and fast by design? (Rust, OCaml...)
I'm not going to spend years reimplementing that same logic in some other language. I'm going to build on top of it. Maybe I'll need to make changes to some of the underlying code.
Better tooling - which is exactly what type checkers are - makes my life much, much easier and makes me much more productive.
Besides, all these languages exist for a reason - you choose the tool appropriate for the problem. "safe and fast" does not make a language automatically better for a problem.
This means that it’s extremely risky to build things in hipster languages because the pool from which you can hire is extremely small. It also means you’ll have to spend a lot of money building tools and libraries that are “just” available in more popular languages.
On top of that, most companies don’t need to scale things to the point that Netflix does, and even if you do, PHP was good enough to run Facebook before PHP got fast, Python was good enough to run Reddit, Node is good enough to run Netflix and Ruby was good enough to run Github.
I mean, why would you ever chose Rust for your project from a business/management perspective? To save a few bucks on iron while increasing your development costs by hundreds of thousands and making vacant positions impossible to be filled?
On the flip side, why would you bother joining a hipster language as a developer? Right now 35% of the jobs in my country are for C#, another 35% is for JAVA, 25% of them are for PHP or Python, the remaining 5% is for every other language but typically c/c++ for robotics. JavaScript/typescript is involved in quite a lot of the positions, but almost no one is doing a JS backend. There isn’t a single OCalm or Rust position available in my entire country. I’m not sure there has ever been a Rust related position.
Management doesn’t care about technical reasons, and it never will. Developers tend to go where the jobs are, even if they have hobby projects somewhere else.
Maybe Rust will somehow manage to break through, Python did after all. But I think Python had a huge amount of help from being the replacement for JAVA at many universities. I don’t see that happening for Rust.
On the other hand, that’s very likely because every one of us had been doing either JAVA or C# for 15+ years before we started doing anything serious in dynamic languages.
So from a technical perspective I think dynamic languages are equal, maybe even better. From a management perspective though, you have to consider what happens when you hire a developer who didn’t grow up with static types.
Python and Javascript have different standout attributes but it comes back to the same key point: most people building regular apps/sites/products care primarily about building something functional as fast as possible.
It would make sense that productivity would be a primary concern in the earlier stages when it's not yet known whether a product idea is viable.
But type safety might become a consideration later as the development team becomes bigger, the codebase becomes more complex, and production reliability becomes an important consideration.
No one should be surprised when the "language/framework for non-programmers" results in a codebase that was clearly made by non-programmers.
I haven’t seen anyone call Ruby/Rails a "language/framework for non-programmers". Nobody asserts that someone can or should try to build a professional-grade app or site without having a solid understanding of programming fundamentals.
It’s just a matter of what you optimise for.
Rails makes sense in startup land, where it’s more likely that not that what you’re building won’t turn out to be popular, so it’s best to test the concept as fast as possible to avoid wasting any more time than you need to.
You can easily rebuild in other languages if you’re lucky enough that scale, performance and maintainability become major problems. I’ve seen that happen at several companies including Twitter and Airbnb, and it makes perfect sense.
OCaml is kind of but still not as fast as Ruby for me at least.
I spent a lot of time learning Haskell and Scala and I'm still learning. And they never caught up with ruby on rails in terms of velocity for me.
One big thing is about the feedback loop. Typesafe so what? Type is type, it's not either value or business invariant. I'm not convinced as long as you're not writing proofs in dependent-type languages like Idris. So, I still prefer REPL that I can sure about in no time, and watching tests every 0.1s after I change the code.
One can say interpreted languages are optimized for developing because when you change the code, it can be just run once -- there's no point of compiling it because in the next second you'll be changing it.
And compiled languages are optimized for the runtime, because it's compiled it's ready to be run many times.
Of course, there are JIT for interpreted languages and interpreted static-typed languages, but Haskell REPL is still pretty slow compared to Slime. And for Rails, you can actually touch anything runtime entity in the console.
Types are proofs in OCaml as well, you don't need dependent types to have Curry-Howard correspondence. You could even prove stuff in Java. And you can ensure invariants with types in OCaml well enough.
No modern type system gives you runtime gaurantees (c++, Java, rust all erase in various ways).
Interfaces are more clear.
What do you mean by interfaces?
But then this is an argument that I don't have much time for and too much time has been spent on it already. Lets just say that if there are many major companies that felt the need to invest in a type system for a popular languages that don't have one, then there might be something too it.
I'd say python is about as popular as Java and so I don't see companies investing a bunch of money to make Java programmers more comfortable when they could just hire an army of Python developers if they wanted to. I just think they see value in the static analysis that types provide. Read about why Facebook added types to PHP they don't mention your hypothesis.
I don't mind programming in languages with dynamic type systems. I find it just as fun. But I do think its easier when there is a way to easily keep track of the type of thing being operated on. I mean the data is what is actually being operated on, the more I can tell about the data from reading the code the better. The most difficult systems I have ever worked on were the ones where unshaped globs of data were being shuffled around in hash tables and heterogeneous sequences. I would always have to use the debugger to find out what was going on at a given point. The code was dispatching on value and type. It was rough.
If the statically typed language is compiled to a dynamic language, you will lose most of the performance gains too, for example Dart is almost like JavaScript-with-static-typing, but it's twice as fast because the compiler can actually make use of the static types.
I also think static typing bolted on to a dynamic higher level languages do push you into an object oriented paradigm. And I think the language becomes uglier with annotations. And it makes people lazy so they name things x, y, z because the type annotation fills in the rest. But who cares about syntactic preferences, code readability and naming things :) The real reason you use static typing is to catch bugs ... But the best way to catch bugs is to understand the code, and have many people read it. When I see less good programmers the workflow goes something like this:
-I want to do foo ... autocomplete ... fooBaz, fooBar, fooFoo ... hmm, what can I do with foo ... autocomplete ... foo.bar sounds like what I need, it takes a baz, new Baz() ... damnit how do I get rid of this null exception ...
I did what you suggested and looked up why Facebook created Hack, from a release post (1): "but still spend time looking up mundane method names in documentation"
They don't have time to read and understand code. :P I sometime jokingly say "the code is the documentation". Jokingly because I know that is unacceptable, but I most of the time actually do mean it. :P
"We didn’t want to slow the PHP workflow, so we came up with a new approach to reconcile instantaneous feedback with type safety."
They addressed one of the issues with a compile step, eg slower feedback loop.
1: https://code.fb.com/developer-tools/hack-a-new-programming-l...
Where does it say that. It actually says the opposite quite clearly if you cared to post the whole quote and not just what supports what you would like it to.
> They addressed one of the issues with a compile step, eg slower feedback loop.
Can you explain to me how faster feedback from static types that they, a concept which the article reiterates again and again, leads to a slower feedback loop. Clearly the article and many more like it say that the feedback loop actually speeds up with static analysis since you don't have to run the code to get the feedback.
I'm not sure if you actually want to objectively reason.
[this part contains sarcasm] If you read between the lines in the article, and I've read it in other Facebook articles too (between the lines), understanding code is a problem for Facebook, it's against their principle of "go fast and break things". Good that they are not into the self driving cars business :P [/this part contains sarcasm]
Traditional web development is a bit different from traditional development with long compile times. In PHP for example, the code is evaluated on the go, for every request. Development goes like this: Make change in .php file, (upload the file), reload the browser to see what happened. If you add a type-checker between, before they see what happened, it will slow down the development process. This is how static types and type checking slows down development by adding a compilation step. Facebook claim they fixed it, but it's still a concern that need to be addressed when adding static types to other interpreted languages.
I do acknowledge that tooling allows you to see type errors directly in the editor/IDE before you reload the browser. You can however get that without static typing, via inference. (type annotation do make building such tool easier). It's however likely that the bug would be discovered during the manual or automatic testing anyway, so you have to evaluate if the added complexity to dev-ops from changing the language to add static typing, and adding a compilation step, is actually worth it.
Or to rephrase an old proverb:
Real php developers do it on production only.
the designer of the stanza language has a good writeup on why stanza uses optional types: http://lbstanza.org/optional_typing.html
AIUI, this was basically a one-person effort for a long time, but the project is now growing.
But also look at MyPy's internal MyPyC if you want something that uses type information for some speedups.
[0]news.ycombinator.com/item?id=19473944
> Pyright is typically 5x or more faster than mypy and other type checkers that are written in Python. It is meant for large Python source bases. It can run in a “watch” mode and performs fast incremental updates when files are modified.