Hacker News new | ask | show | jobs
by layer8 394 days ago
I agree that it’s borderline pedantic for this simple code, but I also find it an obvious code smell, contradicting the “as simple as it gets”.

If you consistently deduplicate code that is supposed to do the same and evolve the same, then any duplicated code sticks out as a statement of “this isn’t the same”, and in the present case it then makes you wonder what is supposed to be different about both cases. In other words, such code casts doubt on one’s own understanding, raising the question whether one might be overlooking an important conceptual reason for why the code is being kept duplicated. So in that sense I disagree that the duplicated version is more readable, because it immediately raises unanswered questions.

About possible performance reasons, those need an explanatory comment, exactly for the above reason. And also, if performance reasons warrant complicating the code, then it isn’t “as simple as it gets” any more. I was commenting because I disagreed with that latter characterization.

2 comments

I agree it's a code _smell_. But a "smell" doesn't mean that something is necessarily wrong, just that there's a clue that it might be wrong.

> in that sense I disagree that the duplicated version is more readable

I didn't say it is, I agreed it's _less_ readable. I said it's trading off readability for 8 bytes of memory at runtime.

> If you consistently deduplicate code that is supposed to do the same and evolve the same, then [...]

I agree with all this. I'm not saying to consistently go for the deduplicated approach (I don't think anyone would say that), I'm saying it's a reasonable trade-off in this specific case (each branch is still trivial, and the code won't evolve much if at all).

> About possible performance reasons, those need an explanatory comment, exactly for the above reason.

Agreed.

> if performance reasons warrant complicating the code, then it isn’t “as simple as it gets” any more. I was commenting because I disagreed with that latter characterization.

Also agreed.

To some, the current way is more readable than yours, though. It is much more explicit, and that often is a good thing.
I disagree that it’s more explicit. The case distinction and the loop and the puts are exactly the same in both code variants. You can replace the ternary operator by an if if that’s bothering you, that wasn’t the point of the change. The point is to first determine what should be output repeatedly, and then to output it, because the output logic is independent from what is being output (in particular, `yes` and `yes y` should be guaranteed have identical behavior). I don’t really see what’s non-explicit about that. Rather to the contrary, it makes it explicit that the output logic is intended to be independent from what is being output.
How about:

  for (;;) {
    if (argc > 1)
      puts(argv[1]);
    else
      puts("y");
  }
?

You said "it’s about duplicating logic that should inherently be the same", but that is exactly how it is more explicit, by having this duplication. I assume your problem is with the two "puts()"?

Your proposal is a bit better than the original, although it still duplicates the puts (imagine a variant where you’d want to handle I/O errors), and some will be bothered by the fact that the same unchanging condition is being retested in each loop iteration (the compiler may even warn about it).

But still, I don’t see why you wouldn’t first name what you want to output before starting the outputting. If anything, I’d place the whole output loop in a separate function and have two calls to that function. Nevertheless, it’s even better to express in code the fact that the program doesn’t want to make a distinction between a literal “y” and an argument “y”, by consolidating them into the same variable.

Another way to do this would be to have a static default argument array containing the “y”, and for example having:

    if (argc <= 1) { argv = default_argv; }
    for (;;) { puts(argv[1]); }
This would make explicit the fact thst the argument-less invocation is merely a shortcut for an invocation with an argument and doesn’t otherwise provide any new or different behavior.

Though I think the separate variable (what) is clearly preferable.

I have made the decision to use your "what" method many times before, but in this particular case I do not see the reason to do that, and perhaps this is what I have an issue with. There are many cases in which I would definitely use "what".
That's a whole lot less efficient than both other options, the condition will be checked at every loop, that's not cheap
Oh, I know. :P