4 ms·
Sounds like Go. ;) This is a cheeky remark, but I use Python and Go, and Go very much feels like an improved Python in most ways. Especially when it comes to st
by weberc2 7y ago
Sounds like Go. ;) This is a cheeky remark, but I use Python and Go, and Go very much feels like an improved Python in most ways. Especially when it comes to static analysis, build tooling, distribution, performance, etc. In particular, I love that there are no venvs, pipenvs, virtualenvs, pyenvs, wheels, eggs, setuptools, easy_installs, etc.
- timothycrosley 7y agoI hate the fact that you may be right, because I really don't like Go in many ways: - I hate it's module system and package eco-system story. - I don't like its syntax. - I don't like its error handling. - I'd much prefer gradual typing. - I want to maintain the ability to use interactive interpreters. - I don't like the fact that instead of being community driven it is Google driven. But, anecdotally, I see go being used as a second language to Python more than anything else and at an ever accelerating rate.
- weberc2 7y agoThese are all fair points. I really enjoy Python, but there are too many things I fight with on a regular basis that simply aren’t issues in Go. It could be so much better if (1) there was a better type system (mypy is unnecessarily shoehorned into the syntax and still very broken—can’t even express recursive types like JSON), (2) a good way to constrain the dynamism so performance could be improved, and (3) a better environment/package management and distribution story (so far pantsbuild.org and PEX files are the best I’ve found). Then there are a long tail of more minor issues, like async/await vs goroutines, real parallelism, etc.
- timothycrosley 7y ago> type-system I agree, but if you for instance look at the TypeScript comparison sub-thread, you'll see that all the issues with both the syntax and implementation of the type-system are being aggressively resolved, and likely will all be so by 3.9. > Good way to constrain the dynamism so performance could be improved Couldn't agree more! > environment I find poetry a joy to use. If you want to bypass venvs all together, there's a lot of work to make that a reality, such as https://github.com/David-OConnor/pyflow https://github.com/David-OConnor/pyflow. > packaging Python in 3.5 added complete zip app support, which has improved this dramatically from my perspective. Extended by things like shiv https://github.com/linkedin/shiv https://github.com/linkedin/shiv make it fairly complete. > async/await This is interesting to me. I prefer async/await in general, because it has become a standard across programming languages and I find it really easy to reason about. I also find channels to be too widely seen as a cure-all, when the only study so far has shown they actually led to an increase bug count. But I don't discount the value of real-parallelism, and am glad to see that Python has been pushing harder on that lately, with things like subshells that allow bypassing the GIL on a single thread.
- weberc2 7y ago> I agree, but if you for instance look at the TypeScript comparison sub-thread, you'll see that all the issues with both the syntax and implementation of the type-system are being aggressively resolved, and likely will all be so by 3.9. I'm happy to hear that; hopefully the efforts really do address these issues well. > I find poetry a joy to use. If you want to bypass venvs all together, there's a lot of work to make that a reality, such as https://github.com/David-OConnor/pyflow https://github.com/David-OConnor/pyflow. I'll have to check those out, but one inherent problem is that even if these tools really do solve my pain points, adopting them means I'm leaving my org on a relatively small island, isolated from the Python community. If these really are the holy grail, why isn't the broader Python community adopting them? Please don't take this as me looking for something wrong--whatever Python build tool I use, I'll eventually need support and there's a lot to be said for having a thriving community that has almost always run into my exact problem before. > Python in 3.5 added complete zip app support, which has improved this dramatically from my perspective. Extended by things like shiv https://github.com/linkedin/shiv https://github.com/linkedin/shiv make it fairly complete. We're currently using this via pex. It mostly works, but we still run into problems occassionally (system dependencies, for example). Figuring out how to integrate these tools into the broader build process is another problem to solve--we're using `pants` which supports pex out of the box, but we're running into lots of bugs or other problems. I'll keep an eye on shiv. > This is interesting to me. I prefer async/await in general, because it has become a standard across programming languages and I find it really easy to reason about. I also find channels to be too widely seen as a cure-all, when the only study so far has shown they actually led to an increase bug count. But I don't discount the value of real-parallelism, and am glad to see that Python has been pushing harder on that lately, with things like subshells that allow bypassing the GIL on a single thread. My biggest issues with async/await are (1) every package needs an async variant (async boto, async docker, etc etc). We work around this by running them in a thread pool executor, and I think that works, but I don't know if I'm holding the GIL unnecessarily and causing performance issues (fundamentally difficult to diagnose). This is roughly the "what color is my function" problem. (2) it's really easy to starve the event loop by calling into something that transitively makes a sync call or otherwise just does a lot of CPU-heavy work. We've run into both kinds in production and they've been really hard to troubleshoot (because the requests that time out often aren't the ones that are actually causing the problems). (3) dynamic typing means it's super easy to forget to await things. Tests should catch this, but we find ourselves writing tests _just_ to catch this (e.g., we now write tests for entrypoints that _just_ `await lib_function(params)`; we would normally not write tests for such simple functions, but now we have to). Static typing is the right way to solve this and mypy does, but mypy has too many other issues (at the moment) for our org. One substantial criticism of goroutines is that they're less safe than async/await because you need to make sure the code you're running is threadsafe. I appreciate this criticism, but I think it's the right tradeoff for Go's performance aspirations (another great high-performance alternative is Rust's borrow checker, but that's the wrong tradeoff for Go's developer productivity aspirations).
- ledauphin 7y agoGo may "feel" like Python, but it's almost nothing like Python in actual practice. It's not dynamic (and doesn't even have generics), and its error handling is dramatically different.
- weberc2 7y agoIt _is_ like Python in practice (I use both languages all the time). That’s largely why you see it used in many of the same places as Python. It has dynamic features by way of interface{}, which is every bit as “generic” as what Python has to offer. :) But yes, the error handling is different—values vs exceptions.
- qtplatypus 7y agoI am of the view that interface{} is the worst of both worlds with regards to static/dynamic typing. Dynamically typed languages typically have type coercion and structures that make dealing with vars with unknown types easy. However golang doesn't have that. So you get the danger of a dynamic language without the features that make powerful.
- weberc2 7y agoGo has those features in the reflect package (so as far as I know, Go is just as powerful as Python), but you’re right that they aren’t easy to use. If you do use them, it’s quite clear, and will be addressed in code review so you don’t have nearly as many dynamic typing bugs as Python—it’s not anywhere close. Very dynamic code shouldn’t be easy; the happy path should encourage clear, simple code. By encouraging people to stay on the happy path, their code is more performant, maintainable, etc and it keeps the average code quality quite high across the ecosystem.
- qtplatypus 7y agoIt is rare that I have had problems with dynamic typing errors in P* languages. I am of the view that that dynamic code should be one of two things. 1) Super easy. That way doing it right is trivial. 2) Impossiblely difficult so the only people who are doing it can be trusted to do it right. To me go falls between those two. It’s real easy to say interface{} (indeed it is more difficult to make a non empty interface) but doing it in a way that is safe isn’t easy. I don’t think expressive power is the point here. As they are both compleate languages. More it is an issue of what trade offs and comprises have been made.
- nine_k 7y agoWhat Go adds in tooling and performance, it takes away in expressivity. What takes 3 lines in Python, takes 10-30 on Go.
- weberc2 7y agoYeah, but typically only locally. Like using a for loop instead of a list comprehension, or handling errors. So more keystrokes, but in most cases not more complexity. In some cases (generic programming), Python really is more expressive, but those ~5% of cases aren’t worth the tooling/perf/maintainability tradeoffs most of the time.
- nine_k 7y agoIt depends. Code reviewers glazing over copy-pasted boilerplate blocks can more easily lose track of the whole, and miss an error which is obvious when the whole is expressed in 10 lines. There is some optimal range of expressive density for comfortable use by humans. APL or K likely above that level, and Go feels below it, not as low as COBOL, but still.
- weberc2 7y agoThe opposite is true in my experience. Most of that boilerplate is brackets and indentation, which visually frame the interesting bits, drawing your eye to them. This is, of course, subjective, but I use both regularly and at worst this is not a problem for Go.
- joshuamorton 7y agoThe problem here is that there is boilerplate at all. There shouldn't be. Boilerplate distracts from what is actually going on. I can generally identify code smells from the shape of python code (like, blur all the text so I can't read the words, and the shape of the blocks tells me everything I need), I can't do the same in go, because there's so much more indentation and visual stuff happening, and most of it (boilerplate error handling) isn't interesting.