Hacker News new | past | comments | ask | show | jobs | submit login

You might want to familiarize yourself with how errno works.

It is not used for reporting. Rather, various functions in C and POSIX return an indication that some exceptional situation has occurred. Then errno holds a value which classifies the cause of that situation. It doesn't report the error.

(In the case of portable ISO C, we can't even depend on that; we must set errno to zero before calling most library functions. If that function fails, then if errno is nonzero, it has a value pertaining to that function.)

Some newer functions in POSIX return the errno value, like pthread_mutex_lock. That makes sense when the return value has no other purpose like "bytes processed" or whatever. The errno values are positive, so they combine poorly with in-band signaling.

Anyway, optimizing is possible based on the return value: like putting the expected success case into the hot code path or whatever.




Thank you, I'm aware how errno works. C has been able to return structs for the last 30 years, so returning a pair of value+error code is no big issue even in C.

Optimizing errno is so easy that many compilers by default do not even update errno for many math functions because it hopelessly destroy any chance of vectorizing and aggressive optimizations.


Your idea would seriously uglify code. If we want the function's result and the error, we have to capture the return value in an object. If we just do

  if (library_function(arg).result < 0) ..
we have lost the errno. For the complete analysis, we must now do:

  struct error;

  error = library_function(arg);

  // test error.result; if bad, work with error.num
Yes we have had struct returns (proper, on-stack ones) for more than 30 years, which means we could have had API's like this for 30 years.

I agree that errno for math functions isn't such a great fit. It's much better suited for I/O and resource management.


To be fair, the issue of ergonomics is an artifact of C only. In a language with proper sum types (or as I like to think of them, "better enums"), the pattern would look more like this:

    match library_function(arg) {
      Ok(num) => // success
      Err(errno) => // failure
    }
But since C doesn't have proper sum types, we have to approximate this pattern with things like errno or returned structs.


yes, the syntax is not great, but it is not really worse than errno. Especially because you can initialize the error object at declaration point and, as you pointed out, you would otherwise need to zero errno:

  struct error res = library_function(arg);
  if (res.result)
  {
     // use res.errno
     ...
  }
Also remember the whole thread is about improving the syntax for this sort of stuff. C could take (another) page from C++:

  auto [result, errno] = library_function(arg);
  if (result == -1)
  {
     // use errno ...
  }




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: