[Proposal] function "return" optional keyword.

The difference between issuing return embedded in multiple locations to reduce verbosity is actually slightly more than extra verbosity it is actually a different execution path.

In my last example (Scalaish). The last and only expression in the function is the whole match case - it terminates at the end of the function.

  def f2(input: Integer) : Integer = {
    input match {
        case _ if input > 10 => 10
        case _ if input < 0 => 0
        case _ => input
    }
  }

Whereas if you sprinkle in returns as such, you are actually changing the execution path:

  def f2(input: Integer) : Integer = {
    input match {
        case _ if input > 10 => return 10 <— function terminates here
        case _ if input < 0 => return 0 <— function terminates and here
        case _ => return input <— <— function terminates and here
    }
  }

A move towards spaghetti like code.

Now if you were to add an extra expression like using an intermediate value.

  def f2(input: Integer) : Integer = {
    let x = input match {
        case _ if input > 10 => 10 // no longer terminates here
        case _ if input < 0 => 0 // no longer terminates here
        case _ => input // no longer terminates here
    }
    x /2 // or return x/2
  }

You would have had to go back and modify the original execution path with all the embedded returns which can also be a source of unwanted defects if one is missed (in larger functions).

···

On 2015-12-21, at 3:29:27, Radosław Pietruszewski <radexpl@gmail.com> wrote:

I honestly don’t have a problem with having to say `return` inside functions. That’s not necessarily a -1, but I’m reluctant to say +1 when _even I_ don’t really have the problem with extra verbosity.

*However*, as others pointed out, having to type `return` is a bit tiring in the context of a computer property’s “get”:

var twiceSomething: Int { self.something * 2 }

— Radek

On 19 Dec 2015, at 14:30, Craig Cruden via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

When writing short functional code in a function it would be nice if the return keyword were an optional keyword.

Just return the last evaluated expression.

i.e.

    func flipFunc<T, U>(arg1: T, arg2: U) -> (U, T) {
        (arg2, arg1)
    }

The keyword return would still be there for breaking out of a function.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

I have to agree with everything Ilya has mentioned in her response.

It comes down to readability. Omit the "return" keyword from a function and points that the function returns become hard to see. The optional "return" keyboard in Ruby is one of the few features of Ruby that I genuinely dislike for this reason. Of course, Ruby makes it more difficult because it doesn't type methods.

Cheers,
-Patrick

···

On Dec 20, 2015, at 7:11 AM, ilya via swift-evolution <swift-evolution@swift.org> wrote:

-1 on inferred return type and omitting return with func

Both features are actually available in the language as-is, just not with the func keyword:

let someInferredFunction = { _ in 5} // () -> Int

When teaching Swift we actually teach func + return keywords together, they make it easy to see all possible return paths from a function.

And we recommend using func instead of a closure when there is a multiline body with control statements. Having implicit return in that case hurts readability. For example, out of three possible return points within this function only one is not marked with return:

func f(input: Int) -> Int {
    if input > 10 {
        return 10
    }
    if input < 0 {
        return 0
    }
    input
}

+1 on omitting return from var {} declaration, those methods look like closures and will often be one-liners.

On Sun, Dec 20, 2015 at 5:29 AM, Craig Cruden via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
I looked at the discussion and it looked like they were discussion two things combined.
   - inferred return type (on function signature)
   - and omitting return on the return.

I agree with Chris on the fact that the function should have the type of return specified on the signature and not inferred since it is useful for API documentation to know that ahead of time on a strongly typed language.

What is not necessary is actually forcing people to type return “x” on the last line - since “return” is rather redundant and clutter for those people of a functional programming paradigm point of view.

On 2015-12-20, at 4:15:15, Stephen Christopher via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

The discussion I was remembering, comment courtesy of Chris:
Apple Developer Forums

(linked from Apple Developer Forums)

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

Having returns all over the place in the middle of the code already is sloppy to my eyes, I prefer to try at all cost to avoid spaghetti like code.

The downside of Swift not having everything as a function/expression - or at least other replacements for them is it tends to encourage spaghetti code like the example you are posting. I also tend to dislike compound/nested if’s where possible sometimes breaking stuff down into other functions scooped within functions.

Hence for my example I am going to use the Scala match (which is for pattern matching — i.e. more than just a switch) with guards. _ = match everything / def is func.

  def f(input: Integer) : Integer = {
    input match {
      case _ if input > 10 => 10
      case _ if input < 0 => 0
      case _ => input
    }
  }

The downside of Scala is that it rides on top of the jvm and I would prefer something that compiled using llvm. Two things that I would like to see for me to be able to replace a jvm solution for server code is clean functional code where you did not have to either do let x then return at the end or random “returns” in the middle of code and of course a nice jdbc (interface standard for SQL databases rather than relying on vendor specific driver code) like standard SQL database interface [which is out of scope for evolution].

···

On 2015-12-20, at 19:11:09, ilya <ilya.nikokoshev@gmail.com> wrote:

-1 on inferred return type and omitting return with func

Both features are actually available in the language as-is, just not with the func keyword:

let someInferredFunction = { _ in 5} // () -> Int

When teaching Swift we actually teach func + return keywords together, they make it easy to see all possible return paths from a function.

And we recommend using func instead of a closure when there is a multiline body with control statements. Having implicit return in that case hurts readability. For example, out of three possible return points within this function only one is not marked with return:

func f(input: Int) -> Int {
    if input > 10 {
        return 10
    }
    if input < 0 {
        return 0
    }
    input
}

+1 on omitting return from var {} declaration, those methods look like closures and will often be one-liners.

On Sun, Dec 20, 2015 at 5:29 AM, Craig Cruden via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
I looked at the discussion and it looked like they were discussion two things combined.
   - inferred return type (on function signature)
   - and omitting return on the return.

I agree with Chris on the fact that the function should have the type of return specified on the signature and not inferred since it is useful for API documentation to know that ahead of time on a strongly typed language.

What is not necessary is actually forcing people to type return “x” on the last line - since “return” is rather redundant and clutter for those people of a functional programming paradigm point of view.

On 2015-12-20, at 4:15:15, Stephen Christopher via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

The discussion I was remembering, comment courtesy of Chris:
Apple Developer Forums

(linked from Apple Developer Forums)

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

In my experience, early returns usually reduce spaghetti and it is why I’m a huge fan of guard since it encourages this pattern. In an effort to return as early as possible, my conditions usually coalesce into small nuggets of logic that all terminate with a return which makes them really easy to identify and it seems to reduce the nesting depth of statements. When stepping through code in the debugger, it’s easy to spot a problem, too, if it hits a return I didn’t expect rather than weaving down a bunch of conditional code and maybe going into one branch, skipping over another, etc. all in an effort to reach the "one true return" at the end.

l8r
Sean

···

On Dec 21, 2015, at 7:31 AM, Craig Cruden via swift-evolution <swift-evolution@swift.org> wrote:

The difference between issuing return embedded in multiple locations to reduce verbosity is actually slightly more than extra verbosity it is actually a different execution path.

In my last example (Scalaish). The last and only expression in the function is the whole match case - it terminates at the end of the function.

  def f2(input: Integer) : Integer = {
    input match {
        case _ if input > 10 => 10
        case _ if input < 0 => 0
        case _ => input
    }
  }

Whereas if you sprinkle in returns as such, you are actually changing the execution path:

  def f2(input: Integer) : Integer = {
    input match {
        case _ if input > 10 => return 10 <— function terminates here
        case _ if input < 0 => return 0 <— function terminates and here
        case _ => return input <— <— function terminates and here
    }
  }

A move towards spaghetti like code.

Now if you were to add an extra expression like using an intermediate value.

  def f2(input: Integer) : Integer = {
    let x = input match {
        case _ if input > 10 => 10 // no longer terminates here
        case _ if input < 0 => 0 // no longer terminates here
        case _ => input // no longer terminates here
    }
    x /2 // or return x/2
  }

You would have had to go back and modify the original execution path with all the embedded returns which can also be a source of unwanted defects if one is missed (in larger functions).

On 2015-12-21, at 3:29:27, Radosław Pietruszewski <radexpl@gmail.com> wrote:

I honestly don’t have a problem with having to say `return` inside functions. That’s not necessarily a -1, but I’m reluctant to say +1 when _even I_ don’t really have the problem with extra verbosity.

*However*, as others pointed out, having to type `return` is a bit tiring in the context of a computer property’s “get”:

var twiceSomething: Int { self.something * 2 }

— Radek

On 19 Dec 2015, at 14:30, Craig Cruden via swift-evolution <swift-evolution@swift.org> wrote:

When writing short functional code in a function it would be nice if the return keyword were an optional keyword.

Just return the last evaluated expression.

i.e.

    func flipFunc<T, U>(arg1: T, arg2: U) -> (U, T) {
        (arg2, arg1)
    }

The keyword return would still be there for breaking out of a function.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Well, it’s debatable if this would be simpler considering you’d introduce a new syntax. However I agree that inferred return type would be great.

If we can do:

var aProperty = 10

It would be nice to be able to do

var anotherProperty { foo * 2 }

— Radek

···

On 21 Dec 2015, at 08:52, ilya <ilya.nikokoshev@gmail.com> wrote:

For those simple computed var cases I wonder if we could use a simpler definition, inferring the type:

var twiceSomething => something * 2

On the other hand, it's better to specify types for names that can be visible outside of current scope explicitly. So may be the getter declared via this syntax should always be private.

On Sun, Dec 20, 2015 at 23:29 Radosław Pietruszewski <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
I honestly don’t have a problem with having to say `return` inside functions. That’s not necessarily a -1, but I’m reluctant to say +1 when _even I_ don’t really have the problem with extra verbosity.

*However*, as others pointed out, having to type `return` is a bit tiring in the context of a computer property’s “get”:

var twiceSomething: Int { self.something * 2 }

— Radek

On 19 Dec 2015, at 14:30, Craig Cruden via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

When writing short functional code in a function it would be nice if the return keyword were an optional keyword.

Just return the last evaluated expression.

i.e.

    func flipFunc<T, U>(arg1: T, arg2: U) -> (U, T) {
        (arg2, arg1)
    }

The keyword return would still be there for breaking out of a function.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

A guard is an interesting idea as it is really just saying to not perform the function if.

Of course a lot of the cases you are guarding against is where a value is null/nil and would have caused an abend if passing a null.

Now with options though if you have one option -> map -> new Option you would not necessarily have the same issue (not saying never).

···

On 2015-12-21, at 22:36:19, Sean Heber <sean@fifthace.com> wrote:

In my experience, early returns usually reduce spaghetti and it is why I’m a huge fan of guard since it encourages this pattern. In an effort to return as early as possible, my conditions usually coalesce into small nuggets of logic that all terminate with a return which makes them really easy to identify and it seems to reduce the nesting depth of statements. When stepping through code in the debugger, it’s easy to spot a problem, too, if it hits a return I didn’t expect rather than weaving down a bunch of conditional code and maybe going into one branch, skipping over another, etc. all in an effort to reach the "one true return" at the end.

l8r
Sean

On Dec 21, 2015, at 7:31 AM, Craig Cruden via swift-evolution <swift-evolution@swift.org> wrote:

The difference between issuing return embedded in multiple locations to reduce verbosity is actually slightly more than extra verbosity it is actually a different execution path.

In my last example (Scalaish). The last and only expression in the function is the whole match case - it terminates at the end of the function.

def f2(input: Integer) : Integer = {
   input match {
       case _ if input > 10 => 10
       case _ if input < 0 => 0
       case _ => input
   }
}

Whereas if you sprinkle in returns as such, you are actually changing the execution path:

def f2(input: Integer) : Integer = {
   input match {
       case _ if input > 10 => return 10 <— function terminates here
       case _ if input < 0 => return 0 <— function terminates and here
       case _ => return input <— <— function terminates and here
   }
}

A move towards spaghetti like code.

Now if you were to add an extra expression like using an intermediate value.

def f2(input: Integer) : Integer = {
   let x = input match {
       case _ if input > 10 => 10 // no longer terminates here
       case _ if input < 0 => 0 // no longer terminates here
       case _ => input // no longer terminates here
   }
   x /2 // or return x/2
}

You would have had to go back and modify the original execution path with all the embedded returns which can also be a source of unwanted defects if one is missed (in larger functions).

On 2015-12-21, at 3:29:27, Radosław Pietruszewski <radexpl@gmail.com> wrote:

I honestly don’t have a problem with having to say `return` inside functions. That’s not necessarily a -1, but I’m reluctant to say +1 when _even I_ don’t really have the problem with extra verbosity.

*However*, as others pointed out, having to type `return` is a bit tiring in the context of a computer property’s “get”:

var twiceSomething: Int { self.something * 2 }

— Radek

On 19 Dec 2015, at 14:30, Craig Cruden via swift-evolution <swift-evolution@swift.org> wrote:

When writing short functional code in a function it would be nice if the return keyword were an optional keyword.

Just return the last evaluated expression.

i.e.

   func flipFunc<T, U>(arg1: T, arg2: U) -> (U, T) {
       (arg2, arg1)
   }

The keyword return would still be there for breaking out of a function.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Also since the example rewrite is a single line function it could be rewritten as:

  def f2(input: Integer) : Integer = input match {
    case _ if input > 10 => 10
    case _ if input < 0 => 0
    case _ => input
  }

Even with the overkill of pattern matching it — it still is easy to understand what is being returned without forcing the use of “return” all over the place.

···

On 2015-12-20, at 22:30:28, Craig Cruden <ccruden@novafore.com> wrote:

Having returns all over the place in the middle of the code already is sloppy to my eyes, I prefer to try at all cost to avoid spaghetti like code.

The downside of Swift not having everything as a function/expression - or at least other replacements for them is it tends to encourage spaghetti code like the example you are posting. I also tend to dislike compound/nested if’s where possible sometimes breaking stuff down into other functions scooped within functions.

Hence for my example I am going to use the Scala match (which is for pattern matching — i.e. more than just a switch) with guards. _ = match everything / def is func.

  def f(input: Integer) : Integer = {
    input match {
      case _ if input > 10 => 10
      case _ if input < 0 => 0
      case _ => input
    }
  }

The downside of Scala is that it rides on top of the jvm and I would prefer something that compiled using llvm. Two things that I would like to see for me to be able to replace a jvm solution for server code is clean functional code where you did not have to either do let x then return at the end or random “returns” in the middle of code and of course a nice jdbc (interface standard for SQL databases rather than relying on vendor specific driver code) like standard SQL database interface [which is out of scope for evolution].

On 2015-12-20, at 19:11:09, ilya <ilya.nikokoshev@gmail.com <mailto:ilya.nikokoshev@gmail.com>> wrote:

-1 on inferred return type and omitting return with func

Both features are actually available in the language as-is, just not with the func keyword:

let someInferredFunction = { _ in 5} // () -> Int

When teaching Swift we actually teach func + return keywords together, they make it easy to see all possible return paths from a function.

And we recommend using func instead of a closure when there is a multiline body with control statements. Having implicit return in that case hurts readability. For example, out of three possible return points within this function only one is not marked with return:

func f(input: Int) -> Int {
    if input > 10 {
        return 10
    }
    if input < 0 {
        return 0
    }
    input
}

+1 on omitting return from var {} declaration, those methods look like closures and will often be one-liners.

On Sun, Dec 20, 2015 at 5:29 AM, Craig Cruden via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
I looked at the discussion and it looked like they were discussion two things combined.
   - inferred return type (on function signature)
   - and omitting return on the return.

I agree with Chris on the fact that the function should have the type of return specified on the signature and not inferred since it is useful for API documentation to know that ahead of time on a strongly typed language.

What is not necessary is actually forcing people to type return “x” on the last line - since “return” is rather redundant and clutter for those people of a functional programming paradigm point of view.

On 2015-12-20, at 4:15:15, Stephen Christopher via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

The discussion I was remembering, comment courtesy of Chris:
Apple Developer Forums

(linked from Apple Developer Forums)

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution