← Back to context

Comment by TiredOfLife

1 month ago

Obligatory https://castle-engine.io/modern_pascal

> To return a value from a function, assign something to the magic Result variable. You can read and set the Result freely, just like a local variable.

I'm torn about which is clearer, that magic variable style or assigning to the function name as one does in VBScript. I guess the magic variable makes refactoring dirty fewer lines

I also have mixed feelings about golang's `func Doit() (result int, err error)` syntax. To quote another platform, "there should be one, and preferably only one, obvious way to do it"

  • I'll often use `result` as the return value in other languages, largely because I learned it in Delphi 25 years ago. It doesn't have the automatic return value semantics elsewhere, so you also need `return result` or whatever, but it's crystal clear what the intent is. I prefer it for that reason alone.

    • That’s what I do too, but it never occured to me that I got it from Delphi. Makes perfect sense :)

  • `Result` is clearer given that in Pascal, a function name by itself in any other context is a function invocation (with no arguments). That is, you then have this kind of stuff:

      type PInteger = ^Integer;
      var X: Integer;
    
      function Foo: PInteger;
      begin
        Foo := @X;
        Foo^ := 123;
      end; 
    

    The first assignment here is assigning to the magic result variable, while the second one recursively invokes the function and dereferences the returned pointer to assign through it. This is technically not ambiguous (since you can never have a naked function call on the left side of the assignment, unlike say C++), but it's a subtle enough distinction for human readers. No such problem with `Result`, obviously, which is presumably why it was one of the things that Delphi added since day 1.

  • > I'm torn about which is clearer, that magic variable style or assigning to the function name as one does in VBScript.

    That's also "old style" Pascal, and still supported by Free Pascal (even though the compiler gives you a warning for doing it!).

  • >I also have mixed feelings about golang's `func Doit() (result int, err error)` syntax. To quote another platform, "there should be one, and preferably only one, obvious way to do it"

    Isn't it basically equivalent to an anonymous tuple which is automatically deconstructed on assignment?

    • To the novice reader in golang, it was an unexpected "wait, where did these symbols come from?" because I wasn't used to being able to look after the function signature for variable names, and that's doubly true for symbol names that didn't come from caller data

      I'm sure this solved some Google-y problem but for my tastes it is just needlessly confusing since I have never met a programmer who needed help creating local variables and that's got to be infinitely true now that AI gonna take all our jobs

      > Isn't it basically equivalent to an anonymous tuple which is automatically deconstructed on assignment?

      Your comment brought up an interesting point: a certain audience may also think those names appear in the caller's scope because they're part of the function's published signature but are an implementation detail

          func Doit() (result int, err error) {
              return 123, nil
          }
      
          func main() {
              // a, b := Doit()
              // fmt.Printf("In reality %d %+v\n", a, b)
              Doit()
              fmt.Printf("Uh-huh %d %+v\n", result, err)
          }
          ./fred.go:13:32: undefined: result
          ./fred.go:13:40: undefined: err
      
      

      I also just realized they're one of the places where golang doesn't emit a compile error for unused variables (as in the example above). Now I extra hate it

          func Doit() (result int, err error) {
              result = 123
              return 456, nil
          }

  • For glance reading code, a predictable variable name or return keyword is a lot easier imo.

    • Note that both are possible in Delphi and FreePascal - the intrinsic procedure `Exit(X)` is the equivalent of C `return`.