Live data from Hacker News

Clever code is probably the worst code you could write (2023)

read.engineerscodex.com

91–100 of 204 posts

Re: Clever code is probably the worst code you could write (2023)

#91
post #74

Earlier quoted context omitted.

Call me crazy, but I find the second example more readable. The first example is long line and you have to go back and forth to understand it. The second example is a single top down pass.

I’m sure I’m biased, since I code mainly in Python. List/dict comprehensions read the same to me as the longer form, just more concisely. This can be taken too far, and you can wind up with horribly obtuse one-liners that are just awful.

I write and maintain code in a bunch of languages. Rust has risen to the first place, C is the close second followed by C++ and Python.

All of the languages except C have similar iterator-based stuff that let you write one liners and often with lambdas. I dislike them all. They give way too much leeway and encourage many developers to try to prove how clever they are.

Once you have to debug the code containing them, all of the complexity of the syntactic sugar comes crashing down on you. The debugger starts jumping to weird places, sometimes even optimized out parts of the standard libraries while for loops usually stay debugable.

Re: Clever code is probably the worst code you could write (2023)

#92
post #54

Earlier quoted context omitted.

This comment makes no sense. You dismissed the C# code, and then wrote the same thing in Rust, but with an extra non-conceptually-meaningful boilerplate step. May as well ask, "where did x come from, and why are you so sure you can iter().sum() it?" C# has generic types, so yes, C# arrays of numbers have a Sum method. https://stackoverflow.com/questions/2419343/how-to-sum-up-an... Don't make bold dismissive comments…

The C# code ends up relying on LINQ, it's interesting how many C# programmers don't even think about that, either anything they work on already uses LINQ or they just reflexively bring it in everywhere they write C# You'll see that a few of those SO comments actually say they're relying on LINQ to make that work. The array type doesn't have such a method itself. So, in reality although many C# programmers will think…

There is nothing wrong with System.Linq just like there's nothing wrong with Rust's std::iter::Iterator. If anything, this makes writing Rust use the existing muscle memory if you have C# experience and vice versa.

The performance profile of LINQ, while much maligned, has been steadily improving over the years and, in the example of Sum itself, you actually do want to use it because it will sum faster than open-coded loop[0].

I do have grievances regarding LINQ still - my (non-negotiable) standpoint is that Roslyn (C# compiler) must lower non-escaping LINQ operations to open-coded loops, inline lambdas at IL level and similar, making it zero-cost - .NET (IL compiler/runtime) provides all the tools necessary to match what Rust's zero-cost-ish iterator expressions offer and there just needs to be more political will in the Roslyn teams to do so. Because of this, I'm holding my breath waiting for DistIL[1] to be production-ready which does just that.

[0]: https://github.com/dotnet/runtime/blob/main/src/libraries/Sy...

[1]: https://github.com/dubiousconst282/DistIL

(I don't understand what you mean by "it won't compile", because it will, in most cases System.Linq namespace is already referenced anyway, either through global usings or at the top of the file)

Re: Clever code is probably the worst code you could write (2023)

#93
post #24

I would argue that what constitutes clever code varies a lot by language. There's always a "cleverness" threshold where being able to read or refactor the code becomes harder, but this threshold isn't universal. Python in particular makes it very easy to be too clever, since its extremely rigid syntax was designed specifically to discourage it, but it ended up giving the user the necessary tools to be clever anyway,…

What would qualify as clever Python? These kind of broad and vague statements make me wonder if I am guilty..

For a simple example, I think the walrus operator (:=) could be considered clever. I like it, and use it, but the fact that you can declare a variable, store a value in it, and then perform actions depending on its value, all in one line, gives me pause.

    if (foo := bar()) is not None:
        baz(foo)
Whereas the traditionally accepted Python method of dealing with this would be EAFP:

    try:
        foo = bar()
        baz(foo)
    except AttributeError:
        # handle exception

Re: Clever code is probably the worst code you could write (2023)

#94
post #65
post #10

Earlier quoted context omitted.

We now have return std::reduce(x.begin(), x.end()); Which is a little cleaner and is even faster (compiler is free to do the additions in any order). https://en.cppreference.com/w/cpp/algorithm/reduce - it looks like even the `accumulate` example can be made simpler with `std::plus`. I prefer the `reduce` option for a number of reasons, but understand why someone might not.

>the `accumulate` example can be made simpler with `std::plus` Accumulate, surprisingly enough, accumulates by default: return accumulate(x.begin(), x.end(), 0);

Just make sure you're accumulating integers and not doubles!

Re: Clever code is probably the worst code you could write (2023)

#95
post #10
post #4

I also find that, in C++, int sum = 0; for (int i = 0; i is a lot easier to understand than return std::accumulate(x.begin(), x.end(), 0, [](int a, b) {return a + b;}); Yet, the latter is considered more correct and better, with static analysis like cppcheck telling you to use the latter. It does have many advantages, like no mutable variables lying around, but gee it is annoying to read.

We now have return std::reduce(x.begin(), x.end()); Which is a little cleaner and is even faster (compiler is free to do the additions in any order). https://en.cppreference.com/w/cpp/algorithm/reduce - it looks like even the `accumulate` example can be made simpler with `std::plus`. I prefer the `reduce` option for a number of reasons, but understand why someone might not.

> and is even faster (compiler is free to do the additions in any order)

Is that actually true? I'm not even sure how hypothetically removing ordering requirements would help you extract performance, let alone any compilers that could do anything with that today. Unless the standard library were to auto-parallelize the reduction, but I doubt they'd do that because the overhead of starting threads would be quite costly for anything but the absolute largest ranges since C++ doesn't have a thread pool sitting idly for you (not to mention that the docs for the function don't mention any thread safety requirements for the BinaryOp and Init which would be required for any such optimization).

Re: Clever code is probably the worst code you could write (2023)

#96
post #16

This is true, but in code reviews and such, it often boils down to familiarity above anything else, like someone preferring names = [] for record in records: names.append(record["name"]) to names = [record["name"] for record in records] Now, I might say something if I saw this: import operator names = list(map(operator.itemgetter("name"), records)) Seems a bit unidiomatic given that list comprehensions are in the lan…

I’m convinced that the only reason the operator library exists is to provide inputs for functools, which itself is mostly there to pretend that you’re a functional programmer.

…but I do kinda like map().

Re: Clever code is probably the worst code you could write (2023)

#97
post #4

I also find that, in C++, int sum = 0; for (int i = 0; i is a lot easier to understand than return std::accumulate(x.begin(), x.end(), 0, [](int a, b) {return a + b;}); Yet, the latter is considered more correct and better, with static analysis like cppcheck telling you to use the latter. It does have many advantages, like no mutable variables lying around, but gee it is annoying to read.

C++ makes this (and many other things!) needlessly painful. In C# it is just return numbers.Sum();

Same for Rust.

Re: Clever code is probably the worst code you could write (2023)

#98

Kernighan's Law: Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.

Unless you got dumber between writing and debugging, it more likely means that it takes twice as long (or even more if you haven't touched it in a bit). It's unlikely that Kernighan meant it takes someone twice as smart to figure out what you were doing as that would be a nonsensical interpretation (someone twice as smart may not be able to figure out what the stupid person is trying to do in the first place if the code written was nonsensical).

Re: Clever code is probably the worst code you could write (2023)

#99
post #10

Earlier quoted context omitted.

We now have return std::reduce(x.begin(), x.end()); Which is a little cleaner and is even faster (compiler is free to do the additions in any order). https://en.cppreference.com/w/cpp/algorithm/reduce - it looks like even the `accumulate` example can be made simpler with `std::plus`. I prefer the `reduce` option for a number of reasons, but understand why someone might not.

> and is even faster (compiler is free to do the additions in any order) Is that actually true? I'm not even sure how hypothetically removing ordering requirements would help you extract performance, let alone any compilers that could do anything with that today. Unless the standard library were to auto-parallelize the reduction, but I doubt they'd do that because the overhead of starting threads would be quite costl…

I think relaxing the ordering requirement let's you use simd something like this (semi-pseudo code)

  (a, b, c, d) = (0, 0, 0, 0);
  for(int i = 0; i 

Re: Clever code is probably the worst code you could write (2023)

#100
post #32
post #10

Earlier quoted context omitted.

We now have return std::reduce(x.begin(), x.end()); Which is a little cleaner and is even faster (compiler is free to do the additions in any order). https://en.cppreference.com/w/cpp/algorithm/reduce - it looks like even the `accumulate` example can be made simpler with `std::plus`. I prefer the `reduce` option for a number of reasons, but understand why someone might not.

That's terrible! The main operation, addition, is completely hidden magic! But the completely trivial calls to .begin() and .end() are explicit! Why would I want to add by default?

> The main operation, addition, is completely hidden magic

the main operation is reduction which is fairly basic computer science and taught in any non-BS curriculum - https://en.wikipedia.org/wiki/Reduction_operator (or https://en.wikipedia.org/wiki/Fold_(higher-order_function) which is the standard way to introduce this concept ; check in particular the table showcasing all the implementations in various languages). The standard reduction for a set of numbers to a number that is likely going to be the very first example in your textbook is addition.

Post reply on HN