News for hackers. Stuff that matters.
Re:Tidy First? by kazinator on Thursday January 11, 2024 @04:00PM (#38958998)
I don't favor single return per function myself, but in C code bases where that was the norm, I liked being able to add a debug print in one place which logs the return value.

  DEBUG("%s (%s) -> %d", __func__, str_arg, ret);
  return ret;
Single return doesn't necessarily mean nested ifs; it can be linear.

  bool success = true;

  if (condition(arg1)) {
    success = try_that(arg2);
  }

  if (success && condition2(arg3)) {
    success = other_thing(arg2);
  }

  ...

  return success;

Resource acquisition:

  widget_t *w = widget_create(arg);
  gadget_t *g = w ? gadget_create(w, arg2) : 0;
  char *gncopy = g ? strdup(gadget_name(g));

  if (gncopy) {
    // we must have g and w */
  }
Early returns can cause bugs; they can be premature. The coder though that if a certain condition is true, none of the other cases matter. And may be that was true, but now some of the cases (perhaps new ones) do matter. Someone wrote code to handle them, but didn't notice it's not reached because of that early return.
Re:Tidy First? by aulin on Friday January 12, 2024 @12:22AM (#38964209)
You can define your guard clauses as macros and have them always log a warning and still have your debug log before the final return. See e.g. g_return_if_fail/reached and g_return_val_if_fail/reached in glib/gmessages.h.

Early returns can definitely cause bugs, but here we're talking about basic sanity checks and argument validation, not about program logic. Their purpose is if any of those checks fail we are in a very bad state and there's no point on entering the function at all.