4 ms·
I argue: - The list comprehension is ever slightly more readable. (Small Positive) - It is a bit faster to write the code for the Python variant. (Small Posit
by thornewolf 2y ago
I argue:
- The list comprehension is ever slightly more readable. (Small Positive)
- It is a bit faster to write the code for the Python variant. (Small Positive)
So this would be a small positive when using Python.
Furthermore, I believe there is this "small positive" trade-off on nearly every aspect of Python, when compared to Go. It makes me wonder why someone might prefer Go to Python in almost any context.
Some common critiques of Python might be:
- Performance in number crunching
- Performance in concurrency
- Development issues in managing a large code base
I believe the ecosystem is sufficiently developed that Numpy/Numba JIT can address nearly all number crunching performance, Uvicorn w/ workers addresses concurrency in a web serving context, ThreadPool/ProcessPool addresses concurrency elsewhere, and type hints are 90% of what you need for type safety. So where does the perceived legitimacy of these critiques come from? I don't know.
- maccard 2y ago> The list comprehension is ever slightly more readable. I disagree - it's terse to the point of being hard to parse, particularly when you get smart ones like: [x for x in t if x not in s] > It is a bit faster to write the code for the Python variant. Code should be written to be read. Saving a few keystrokes vs time spent figuring out the `not in in not with` dance gives the the edge to Golang here. It's "high context" > - Performance in number crunching > - Performance in concurrency And "performance in all other areas". See the thread last week about massive speedups in function calls in python where it was still 5-10x slower than go. > So where does the perceived legitimacy of these critiques come from? I don't know. It's pretty hard to discuss it when you've declared that performance isn't a problem and that type annotations solve the scalability of development problem.
- laserlight 2y agoLuckily, we are writing Python, not Go, so we can use variable names with more than one letter: [word for word in sentence if word not in bannedWords] Suddenly, nothing is hard to parse.
- bb88 2y agoI do think people should tend to be more verbose with variable names, in general. And since it's python, use snake case to add faux white space to help the eyes parse the statement.
- archargelod 2y agoI still believe Python comprehensions have confusing structure and in real code I've seen it's 10x worse with 5+ expressions packed in a single line. I much prefer a Nim's style of list comprehensions: let a = collect: for word in wordList: if word notin bannedWords: word let b = collect(for x in list: x) It's still very terse, but, more importanly, it's the same syntax as a regular `for loop`. It has the structure, where in Python complex comprehensions look like a "keyword soup".
- dpkirchner 2y agoThis is my (current) favorite list comprehension: https://github.com/huggingface/datasets/blob/871eabc7b23c27d677bc06ae2cc1ec3a2a04b10f/src/datasets/data_files.py#L382 https://github.com/huggingface/datasets/blob/871eabc7b23c27d... Someone was feeling awfully clever that day. (Not that I'm not occasionally guilty myself.)
- neonsunset 2y agoRust: let results = foo .into_iter() .filter(|s| s.contains("banned")) .collect::<Vec<&str>>(); C#: var results = foo .Where(s => s.Contains("banned")) .ToArray(); Convenient, easy to understand and fast.
- maccard 2y agoI think Rusts terseness shows here - I think C#'s approach is the best. Also, if you don't use `.ToArray()`, you still have an IEnumerable which is very usable.
- School-Cotton 2y agoAlso true in Rust. You don't have to use `collect` at the end and you still get an iterator. let results = foo .into_iter() .filter(|s| s.contains("banned"))
- didntcheck 2y agoAnd I think Kotlin would just be val results = foo.filter { "banned" in it} Though I'm not sure I'm a fan of it eagerly finishing with a List. If you chained several operations you could accidentally be wasting a load of allocations (with the solution being to start with foo.asSequence() instead)
- neonsunset 2y agoOf course. This was just to illustrate the point, whether to snapshot/collect a sequence or not is another matter entirely. It just goes to show that idiomatic and fast* iterator expressions is something that modern general-purpose PLs are ought to have. * I know little about performance characteristics of Kotlin but assume it is subject to behaviors similar to Java as run by OpenJDK/GraalVM. Perhaps similar caveats as with F#?
- maccard 2y agoUnfortunately Kotlin fails very, very hard on the "iteration speed" side of things. The compilation speed is so unbelieveably slow, and it suffers very very much from the "JVM Startup time" problem. If it were an order of magnitude faster to compile I'd consider it.