Hacker News new | ask | show | jobs
by nothrabannosir 2293 days ago
What always annoyed me about C is that it has all the tools to simulate something approaching this, save for some purely syntactical last-mile shortcomings. We can already return structs; if only there were a way to neatly define a function returning an anonymous struct, and immediately destructure on the receiving end. Something like:

  #include <stdio.h>

  struct { int err; char c; } myfunc() {
    return { 0, 'a' };
  }

  int main(int argc, const char *argv[]) {
    { int err; char c; } = myfunc();
    if (err) {
      // handle
      return err;
    }
    printf("Hello %c\n", c);

    return 0;
  }
This is (semantically) perfectly possible today, you just have to jump through some syntactic hoops explicitly naming that return struct type (because among others anonymous structs, even when structurally equivalent, aren't equivalent types unless they're named...). Compilers could easily do that for us! It would be such a simple extension to the standard with, imo, huge benefits.

Every time I have to check for in-band errors in C, or pass a pointer to a function as a "return value", I think of this and cringe.

4 comments

You can write that in C++17 with only slightly different syntax (and it is actually really nice for being C++):

  #include <stdio.h>
  #include <tuple>

  std::tuple<int, char> myfunc() {
    return { 0, 'a' };
  }

  int main(int argc, const char *argv[]) {
    auto [ err, c ] = myfunc();
    if (err) {
      // handle
      return err;
    }
    printf("Hello %c\n", c);

    return 0;
  }
You may be interested in tagged unions. A struct with an enum and a Union. You can switch on the enum.

More stuff like this in https://pdfs.semanticscholar.org/31ac/b7abaf3a1962b27be9faa2...

Sounds like you'd like Go, which works this way.
Which is a strictly inferior and botched way to go about it, especially since golang was designed from scratch.
> We can already return structs

AFAIK, no? You can return a pointer to a struct, and you can pass whole structs as arguments, but not, IIRC, return them from functions.

EDIT: Apparently you can, sort of, but not portably; how exactly it is defined to work depends on the compiler, and each compiler might define it differently. This means that if you’re using a library which returns a struct and your program use a different C compiler than the library used when it was compiled, your program will not work. I.e. there is no one defined stable ABI for functions returning structs.

Therefore I think it’s reasonable to regard it as impossible in practice.

Structs are values and you can return them like any value (or use them as parameters).

I'm not sure what you mean about compilers.

Xe is conflating compilers and calling conventions a bit. The way that structure types are returned varies by calling convention, as indeed do a lot of other things. Mismatched calling conventions leads to problems.

But structure type return values are well specified for most calling conventions, and quite a number of compilers support explicitly specifying the calling convention for mixed-language or mixed-compiler situations.

* http://jdebp.uk./FGA/function-calling-conventions.html

Many calling conventions apparently use a method for returning structs which is inherently non-thread-safe.

Also from that link:

> 32-bit cdecl calling convention

> For return values of structure or class type, there is wide incompatibility amongst compilers. Some make the return thread-safe, by breaking compatibility with the 16-bit cdecl calling convention. Some retain compatibility, at the expense of their 32-bit cdecl calling convention not being thread-safe. The ones that break compatibility don't all agree with one another on how to do so.

Oh, I get it.

This is mostly not a practically relevant issue. (Nor are pre-K&R compilers relevant, although something like this could arise among modern compilers.) As far as oddball situations go, it's far from the thorniest to deal with - it doesn't even involve C++.