4 ms·
I agree tooling makes a huge difference but I specifically said this with the understanding that you're using C# with Visual Studio. Some stuff will be easier i
by dataflow 4y ago
I agree tooling makes a huge difference but I specifically said this with the understanding that you're using C# with Visual Studio. Some stuff will be easier in C#, but a lot of other stuff just isn't as easy as in Python.
At the risk of setting up a strawman for people to punch down, try comparing how easy it is to do the equivalent of something like this in C#, and feel free to use as much IDE magic as you'd like:
x = [t[1] for t in enumerate(range(1, 50, 4)) if t[0] % 3 == 0][2:]
Was it actually easier?
There's a million other examples I could write here, but I'm hoping that one-liner will be sufficient for illustration purposes.
- eterm 4y agoHere's a one liner in c# for that: Enumerable.Range(1,50).Where((x,i) => i % 4 == 0).Where(e => e % 3 == 0).Skip(1).Select(e => e+4) Okay, so you might consider that last e+4 cheating and against the spirit, but I couldn't be bothered to spend money upgrading my linqpad to support the latest .net with Enumerable.Chunk which makes taking two at a time easier for the first part. Edit: more in spirit: Enumerable.Range(1,50).Where(e => e % 4 == 0 && e % 3 == 0).Skip(1).Select(e => e + 1)
- dataflow 4y agoNah that part I'm not worried about. The "cheating" is omitting the rest of the line. What you really needed was: var y = Enumerable.Range(1, 50).Where((x, i) => i % 4 == 0).Where(e => e % 3 == 0).Skip(1).Select(e => e + 4).ToArray(); Compare that against: y = [t[1] for t in enumerate(range(1, 50, 4)) if t[0] % 3 == 0][2:] It's almost twice as long, and doesn't exactly make up for it with readability either.
- eterm 4y agoIt's not "twice as long" in any syntactic sense, and readability is easily fixed: Enumerable.Range(1,50) .Where(e => e % 4 == 0 && e % 3 == 0) .Skip(1) .Select(e => e + 1) That's very understandable, it's clear what it does, and if your complaint is that dotnet prefers to name expressions like Skip rather than magic syntax, we can disagree on what make things readable and easy to maintain.
- dataflow 4y agoIt's literally "twice as long" syntactically. 120 vs. 67 characters. And again, you keep omitting the rest of the line. (Why?) What you should've written in response was: var y = Enumerable.Range(1,50) .Where(e => e % 4 == 0 && e % 3 == 0) .Skip(1) .Select(e => e + 1) .ToArray(); Compare: y = [t[1] for t in enumerate(range(1, 50, 4)) if t[0] % 3 == 0][2:] And (again), my complaint isn't about LINQ or numbers or these functions in particular. This is just a tiny one-liner to illustrate with one example. I could write a ton more. There's just stuff Python is better at, there's other stuff C# is better at, that's just a fact of life. I switch between them depending on what I'm doing.
- eterm 4y agoThe ToArray is unneccessay, it's much more idiomatic dotnet to deal with IEnumerable all the way through. The only meaningful difference in lengths is that C# doesn't have an Enumable.Range(start, stop, increment) overload but it's easy enough to write one, and then it'd be essentially the same length.
- dataflow 4y ago"Unnecessary"? You can't just change the problem! I was asking for the equivalent of some particular piece of code using a list, not a different one using a generator. Sometimes you want a generator, sometimes you want an array. In either language.
- eterm 4y agoThis is a silly argument, you're asking for a literal translation of a pythonic problem without allowing the idioms from the other languages. If you were actually trying to solve the problem in dotnet, you'd almost certainly structure it as the Queryable result and then at the very end after composing run ToList, or ToArray or consume in something else that will enumerate it. We can also shorten it further to: Enumerable.Range(1, 50) .Where(e => e % 12 == 1) .Skip(2) .ToList() Now even including the ToList it's now just four basic steps: Range, Filter, Skip, Enumerate. Those are the very basics, all one line if wanted. It doesn't get much more basic than that, and I'd still argue it's easier for someone new to programming to see what's going on in the C# than the python example. edit: realised the maths simplifies it even further.
- dmitriid 4y agoWhat you're missing is that C# example works on any Enumerable. And it's very hard to explain how damn important and impressive this is without trying it first. Yes, it's more verbose, but I can swap that initial array for a List, or a collection, or even an external async datasource, and my code will not change. It will be the same Select.Where....
- dataflow 4y ago> What you're missing I'm not missing it. > is that C# example works on any Enumerable. And it's very hard to explain how damn important and impressive this is without trying it first. Believe me I've tried (by which I mean used it a ton). I'm not a newbie to this. C# is great. Nobody was saying it's unimportant or unimpressive or whatever. > Yes, it's more verbose, but I can swap that initial array for a List, or a collection, or even an external async datasource, and my code will not change Excellent. And when you want that flexibility, the verbosity pays off. When you don't, it doesn't. Simple as that.
- dmitriid 4y ago> Excellent. And when you want that flexibility, the verbosity pays off. When you don't, it doesn't. Simple as that. It's rarely as simple as that. For example, this entire conversation started with "At the risk of setting up a strawman for people to punch down, try comparing how easy it is to do the equivalent of something like this". And this became a discussion of straw men :) Because I could just as easily come up with "replace a range of numbers with data that is read from a database or from async function that then goes through the same transformations", and the result might not be in Python's favor.
- Jtsummers 4y agoIf I understand dataflow's example correctly you don't need the Select at the end: var x = Enumerable.Range(1,50) .Where((num, index) => num % 4 == 1 && index % 3 == 0) .Skip(2) .ToArray(); That computes the same thing as their Python snippet: [25,37,49]. Of course, what this is actually computing is whether the number is congruent to 1 modulo 4 and 3 so it was a weird example, but here's how you'd really want to write it (since a number congruent to 1 modulo 4 and 3 is the same as being congruent to 1 module 12): var x = Enumerable.Range(1,50) .Where(num => num % 12 == 1) .Skip(2) .ToArray(); Rewriting that Python example to be a bit clearer for a proper one-to-one comparison: y = [t for t in range(1, 50, 4) if t % 3 == 1][2:] That enumerate wrapper was unnecessary. I don't recall a way, in LINQ, to generate only every 4th number in a range, but I also haven't used C# in a few years so my memory is rusty on LINQ anyways.
- dataflow 4y ago> num % 12 > That enumerate wrapper was unnecessary. I'm surprised you didn't go all the way and just write x = [25, 37, 49] and tell me the rest of the code was unnecessary!
- Jtsummers 4y agoI mean, was it necessary? Your original Python expression was pretty obfuscated for such a simple calculation.
- dataflow 4y agoAre you actually suggesting I didn't realize I could've written x = [25, 37, 49], or what? Surely the point of the example wasn't "find the optimal way to calculate that particular list of numbers"?
- Jtsummers 4y agoNo, I'm suggesting that your original example was a great example of obfuscated Python. Even supposing that you wanted to alter the total number of values generated and the number of initial values to skip, you're doing unnecessary work and made it more convoluted than necessary: def some_example(to_skip=2, total_count=3): return [n * 12 + 1 for n in range(to_skip, to_skip+total_count)] There you go. Change the variable names that I spent < 1 second coming up with and that does exactly the same thing without the enumeration or discarding values. In a thread on how computer speed is wasted on unnecessary computation, it seems silly that you're arguing in favor of unnecessary work and obfuscated code.
- radicalbyte 4y agoThere's very little difference between the two as long as you're using modern versions of both and add your own functions to fill any API gaps and are using type hinting properly in Python. My C# tends to be "larger" because I use more vertical whitespace and pylint is rather opinionated.. :) Where you can complain about C# - and I do - is where you're having to write (or work with) code which has been force to stick to strict architectural and style standards. That makes code-bases which are very hard to understand for newbies and are verbose. On the flip side, once you start doing anything even slightly interesting with Python you run into the crappy package management. The end result of which is lots of frustration getting projects working and a lot of time wasted on administration vs work.