[Pitch] Trigate function calls for inout arguments

The beginning of a line of code often states a variable to which assignment is occurring. This means that once you know which variable has the wrong value, a quick scan down the left side of the code enables you to find where it is being assigned. Unfortunately inout functions spoil this: even though the ampersand in the function call should alert you to the fact that the variable is being altered, this will be somewhere over on the right side of the code rather than lined up beneath the assignee variables.

Conceptually a function has three gates: an in gate (the argument(s) which affect the function), an out gate (the return value or tuple of values which is affected by the function) and the inout gate (inout argument(s) which both affect the function and are affected by it). There is no good reason for the in gate and the inout gate to rub shoulders with each other, and I believe it has happened because computer functions were modelled after maths functions, which only have two gates.

I propose that inout arguments in function calls should optionally have their own argument list which appears in brackets before the function name. This would allow them to be stacked up on the left side of the screen beneath the assignments. This would be optional where the function is called, and would have no effect on the function definition. I believe that if all inout arguments were either separate on the left or mingling on the right, there should be no confusion: some inout arguments on the left while some were on the right would not be allowed.

Example:

Definition (unchanged):

func myFunction(inA:Int, ioB: inout Int, inC: Int, ioD: inout Int) -> Int

Existing style call (still to be allowed):

let result = myFunction(inA:43, ioB: &B, inC: 97, ioD: &D)

Trigate style call

let result =
(ioB: &B,
ioD: &D)myFunction(inA: 43, inC: 97)

What kind of problem will be solved by this proposition?

Firstly, it depends on where inout parameter are located in arguments list. You can place all inout params in left side,

What kind of confusion do you mean? Personally I've never felt some kind of confusion about inout parameters and have never heard about some sort of confusion from my development teams.

I've scanned some codebases. Most functions have 1 inout parameter.
On order of magnitude less of functions have 2 arguments where only one is inout.

There are rare situations when function have 2 inout args, like func decryptBlowfishBlock(l: inout UInt32, r: inout UInt32) in CryptoSwift.

There are individual cases like

fileprivate func addDoneButtonOnKeyboard(inputAccessoryView: inout UIView?, target: Any?, action: Selector?) {
  let doneToolbar = ...
  doneToolbar.barStyle = .default
  ...
  inputAccessoryView = doneToolbar
}

extension UITextField {
  public func addDoneButtonOnKeyboard() {
    UICoreKit.addDoneButtonOnKeyboard(inputAccessoryView: &inputAccessoryView, target: self, action: #selector(done))
  }
}

which seem to have no difficulties with understanding.

What you propose here is a gigant changing in how function call look likes, it need to update tons of compiler tooling like syntax parsers, autocomplete, name mangling etc., but motivation is not clear.

4 Likes