Add an implicit return nil if function reaches end before return explicitly called

I believe Swift should no longer require an explicit return on all functions and instead do an implicit nil return if the function reaches the end of its control flow and has an optional return type.

This could be useful to keep code clean and compact, by only having to write code for cases that our function handles and just returning nil otherwise automatically.

Consider:

func toInt(string : String?) -> Int?
{
  if let s = string
  {
    return s.intValue
  }

  //Make this return implicitly happen instead of requiring it.
  //return nil
}

This also very much goes along with the implicit return within a guard statement that I have seen proposed. Here:

func toInt(string: String?) -> Int?
{
  guard let s = string else {
     //this could be implicitly returned using the same logic, since the guard means we have reached the end of our code path without returning
    //return nil
  }
  return s.toInt()
}

These methods could be re-written as so:

This could allow us to write the examples below much cleaner
func toInt(string : String?) -> Int?
{
  if let s = string
  {
    return s.toInt()
  }
}

func toInt(string: String?) -> Int?
{
  guard let s = string else {}
  return s.toInt()
}

// it would be even cooler if we could omit the else {} and make them not it return by default. But that’s another thing all together
func toInt(string: String?) -> Int?
{
  guard let s = string
  return s.toInt()
}

Thanks for reading my first post to the Swift open source discussion board!
-Logan

I thought of this myself at one point, but I looked at a list of other languages to see if they did it and, if so, how much it actually improved anything.

The only language I could find that I have experience in which does this outside of closures was Bash shell scripting, and there wasn’t much to judge there because return doesn’t even mean the same thing in a shell script that it does in most programming languages. Nonetheless, it felt weird to me; lack of a return statement has always been for void functions ("there’s nothing *to* return").

Adding this to Swift would create a lot of confusing cases - if the return type is already Optional, can I then write "return" instead of "return nil" for places in the control flow that need to return without falling off the closing brace? If it isn’t, do I have to make it Optional, or will the compiler do that for me? If it does it for me, will it add a second level of Optional to the first one? ('cause while "Int??" (for example) might have uses, there are almost certainly better ways to express it.) Which of these options for behavior will be the least confusing? How do I tell the compiler "Don’t do that, warn me/error instead", especially when returning Optionals already? If I have to annotate functions I want explicit errors for, do I have to effectively put back a different form of the very @warn_unused_result attribute we just finally got rid of needing for the common case? How does this interact with error handling, especially in the presence of closures and "rethrows"? How does this interact with the implicit return from closures, and do closures now get the same semantics? Does "{}" in function type context now implicitly mean "{ ()->Void? in return nil }"? And if so, how can that change be justified given that it will change the semantics of many closures (workitems for DispatchQueue.async() come to mind) to be effectively wrong? If that isn’t the effect, how do you resolve the confusion developers will experience when they try to mix the enclosing function’s implicit return with a closure’s? What defines a function’s exit point for the purposes of the implicit return? The "end" of a function isn’t always where it seems to be. Can this be expressed reasonably by SIL in its current form without adding considerable extra logic to the compiler? Would this save enough code (a single, fairly short line per function) to justify so massive a semantic change, especially given that it violates the expectations of almost every language Swift typically replaces (C, C++, Objective-C, C#, Java, Perl, PHP, Python, Ruby, just to name a few)?

Ultimately I don’t feel like this would add anything but confusion to the language; couldn’t your example be rewritten as "func toInt(string: String?) -> Int? { return string?.intValue }"? Optional chaining would usually solve such cases more cleanly in my experience.

-- Gwynne Raskind

···

On Jun 22, 2016, at 14:44, Logan Sease via swift-evolution <swift-evolution@swift.org> wrote:

I believe Swift should no longer require an explicit return on all functions and instead do an implicit nil return if the function reaches the end of its control flow and has an optional return type.

This could be useful to keep code clean and compact, by only having to write code for cases that our function handles and just returning nil otherwise automatically.

Consider:

func toInt(string : String?) -> Int?
{
  if let s = string
  {
    return s.intValue
  }

  //Make this return implicitly happen instead of requiring it.
  //return nil
}

This also very much goes along with the implicit return within a guard statement that I have seen proposed. Here:

func toInt(string: String?) -> Int?
{
  guard let s = string else {
     //this could be implicitly returned using the same logic, since the guard means we have reached the end of our code path without returning
    //return nil
  }
  return s.toInt()
}

These methods could be re-written as so:

This could allow us to write the examples below much cleaner
func toInt(string : String?) -> Int?
{
  if let s = string
  {
    return s.toInt()
  }
}

func toInt(string: String?) -> Int?
{
  guard let s = string else {}
  return s.toInt()
}

// it would be even cooler if we could omit the else {} and make them not it return by default. But that’s another thing all together
func toInt(string: String?) -> Int?
{
  guard let s = string
  return s.toInt()
}

Thanks for reading my first post to the Swift open source discussion board!
-Logan

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

1 Like

So this particular construct is one that comes from the ruby language.
In Ruby, you don’t explicitly have to return at all, but rather your last statement will always return by default.
I am NOT advocating this exactly for swift… I get that it could lead to errors and confusion.

But here is my logic:
If the function returns an optional, this basically means that it may not return something. So then, why require the function to call a return explicitly at the end of the function?
Instead, I believe if we reach the end of the function and a return has not been called, we should implicitly return nil… because logically, we are not returning anything, so requiring the function to explicitly return seems redundant.

···

On Jun 22, 2016, at 5:31 PM, Gwynne Raskind <gwynne@darkrainfall.org> wrote:

I thought of this myself at one point, but I looked at a list of other languages to see if they did it and, if so, how much it actually improved anything.

The only language I could find that I have experience in which does this outside of closures was Bash shell scripting, and there wasn’t much to judge there because return doesn’t even mean the same thing in a shell script that it does in most programming languages. Nonetheless, it felt weird to me; lack of a return statement has always been for void functions ("there’s nothing *to* return").

Adding this to Swift would create a lot of confusing cases - if the return type is already Optional, can I then write "return" instead of "return nil" for places in the control flow that need to return without falling off the closing brace? If it isn’t, do I have to make it Optional, or will the compiler do that for me? If it does it for me, will it add a second level of Optional to the first one? ('cause while "Int??" (for example) might have uses, there are almost certainly better ways to express it.) Which of these options for behavior will be the least confusing? How do I tell the compiler "Don’t do that, warn me/error instead", especially when returning Optionals already? If I have to annotate functions I want explicit errors for, do I have to effectively put back a different form of the very @warn_unused_result attribute we just finally got rid of needing for the common case? How does this interact with error handling, especially in the presence of closures and "rethrows"? How does this interact with the implicit return from closures, and do closures now get the same semantics? Does "{}" in function type context now implicitly mean "{ ()->Void? in return nil }"? And if so, how can that change be justified given that it will change the semantics of many closures (workitems for DispatchQueue.async() come to mind) to be effectively wrong? If that isn’t the effect, how do you resolve the confusion developers will experience when they try to mix the enclosing function’s implicit return with a closure’s? What defines a function’s exit point for the purposes of the implicit return? The "end" of a function isn’t always where it seems to be. Can this be expressed reasonably by SIL in its current form without adding considerable extra logic to the compiler? Would this save enough code (a single, fairly short line per function) to justify so massive a semantic change, especially given that it violates the expectations of almost every language Swift typically replaces (C, C++, Objective-C, C#, Java, Perl, PHP, Python, Ruby, just to name a few)?

Ultimately I don’t feel like this would add anything but confusion to the language; couldn’t your example be rewritten as "func toInt(string: String?) -> Int? { return string?.intValue }"? Optional chaining would usually solve such cases more cleanly in my experience.

-- Gwynne Raskind

On Jun 22, 2016, at 14:44, Logan Sease via swift-evolution <swift-evolution@swift.org> wrote:

I believe Swift should no longer require an explicit return on all functions and instead do an implicit nil return if the function reaches the end of its control flow and has an optional return type.

This could be useful to keep code clean and compact, by only having to write code for cases that our function handles and just returning nil otherwise automatically.

Consider:

func toInt(string : String?) -> Int?
{
  if let s = string
  {
    return s.intValue
  }

  //Make this return implicitly happen instead of requiring it.
  //return nil
}

This also very much goes along with the implicit return within a guard statement that I have seen proposed. Here:

func toInt(string: String?) -> Int?
{
  guard let s = string else {
     //this could be implicitly returned using the same logic, since the guard means we have reached the end of our code path without returning
    //return nil
  }
  return s.toInt()
}

These methods could be re-written as so:

This could allow us to write the examples below much cleaner
func toInt(string : String?) -> Int?
{
  if let s = string
  {
    return s.toInt()
  }
}

func toInt(string: String?) -> Int?
{
  guard let s = string else {}
  return s.toInt()
}

// it would be even cooler if we could omit the else {} and make them not it return by default. But that’s another thing all together
func toInt(string: String?) -> Int?
{
  guard let s = string
  return s.toInt()
}

Thanks for reading my first post to the Swift open source discussion board!
-Logan

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

So this particular construct is one that comes from the ruby language.
In Ruby, you don’t explicitly have to return at all, but rather your last
statement will always return by default.
I am NOT advocating this exactly for swift… I get that it could lead to
errors and confusion.

But here is my logic:
If the function returns an optional, this basically means that it may not
return something.

() and nil are not the same.

So then, why require the function to call a return explicitly at the end of

the function?
Instead, I believe if we reach the end of the function and a return has
not been called, we should implicitly return nil… because logically, we are
not returning anything, so requiring the function to explicitly return
seems redundant.

You are returning nil, which isn't "not returning anything." Notice also
that you must write `return nil` and not just `return`.

···

On Tue, Jun 28, 2016 at 12:10 PM, Logan Sease via swift-evolution < swift-evolution@swift.org> wrote:

> On Jun 22, 2016, at 5:31 PM, Gwynne Raskind <gwynne@darkrainfall.org> > wrote:
>
> I thought of this myself at one point, but I looked at a list of other
languages to see if they did it and, if so, how much it actually improved
anything.
>
> The only language I could find that I have experience in which does this
outside of closures was Bash shell scripting, and there wasn’t much to
judge there because return doesn’t even mean the same thing in a shell
script that it does in most programming languages. Nonetheless, it felt
weird to me; lack of a return statement has always been for void functions
("there’s nothing *to* return").
>
> Adding this to Swift would create a lot of confusing cases - if the
return type is already Optional, can I then write "return" instead of
"return nil" for places in the control flow that need to return without
falling off the closing brace? If it isn’t, do I have to make it Optional,
or will the compiler do that for me? If it does it for me, will it add a
second level of Optional to the first one? ('cause while "Int??" (for
example) might have uses, there are almost certainly better ways to express
it.) Which of these options for behavior will be the least confusing? How
do I tell the compiler "Don’t do that, warn me/error instead", especially
when returning Optionals already? If I have to annotate functions I want
explicit errors for, do I have to effectively put back a different form of
the very @warn_unused_result attribute we just finally got rid of needing
for the common case? How does this interact with error handling, especially
in the presence of closures and "rethrows"? How does this interact with the
implicit return from closures, and do closures now get the same semantics?
Does "{}" in function type context now implicitly mean "{ ()->Void? in
return nil }"? And if so, how can that change be justified given that it
will change the semantics of many closures (workitems for
DispatchQueue.async() come to mind) to be effectively wrong? If that isn’t
the effect, how do you resolve the confusion developers will experience
when they try to mix the enclosing function’s implicit return with a
closure’s? What defines a function’s exit point for the purposes of the
implicit return? The "end" of a function isn’t always where it seems to be.
Can this be expressed reasonably by SIL in its current form without adding
considerable extra logic to the compiler? Would this save enough code (a
single, fairly short line per function) to justify so massive a semantic
change, especially given that it violates the expectations of almost every
language Swift typically replaces (C, C++, Objective-C, C#, Java, Perl,
PHP, Python, Ruby, just to name a few)?
>
> Ultimately I don’t feel like this would add anything but confusion to
the language; couldn’t your example be rewritten as "func toInt(string:
String?) -> Int? { return string?.intValue }"? Optional chaining would
usually solve such cases more cleanly in my experience.
>
> -- Gwynne Raskind
>
>
>
>> On Jun 22, 2016, at 14:44, Logan Sease via swift-evolution < > swift-evolution@swift.org> wrote:
>>
>> I believe Swift should no longer require an explicit return on all
functions and instead do an implicit nil return if the function reaches the
end of its control flow and has an optional return type.
>>
>> This could be useful to keep code clean and compact, by only having to
write code for cases that our function handles and just returning nil
otherwise automatically.
>>
>>
>> Consider:
>>
>> func toInt(string : String?) -> Int?
>> {
>> if let s = string
>> {
>> return s.intValue
>> }
>>
>> //Make this return implicitly happen instead of requiring it.
>> //return nil
>> }
>>
>>
>>
>> This also very much goes along with the implicit return within a guard
statement that I have seen proposed. Here:
>>
>> func toInt(string: String?) -> Int?
>> {
>> guard let s = string else {
>> //this could be implicitly returned using the same logic,
since the guard means we have reached the end of our code path without
returning
>> //return nil
>> }
>> return s.toInt()
>> }
>>
>>
>> These methods could be re-written as so:
>>
>> This could allow us to write the examples below much cleaner
>> func toInt(string : String?) -> Int?
>> {
>> if let s = string
>> {
>> return s.toInt()
>> }
>> }
>>
>> func toInt(string: String?) -> Int?
>> {
>> guard let s = string else {}
>> return s.toInt()
>> }
>>
>> // it would be even cooler if we could omit the else {} and make them
not it return by default. But that’s another thing all together
>> func toInt(string: String?) -> Int?
>> {
>> guard let s = string
>> return s.toInt()
>> }
>>
>>
>> Thanks for reading my first post to the Swift open source discussion
board!
>> -Logan
>>
>>
>> _______________________________________________
>> 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

Python and Ruby do this, and it definitely comes handy.

For example if you have optional return type and your function needs to do some work, and in other cases it needs to return nil.

You would avoid "return nil" statement at the end of your function.

I get that this saves a bit of typing/reading, but it certainly doesn't help readability imho. That said, I hate strongly dislike implicit returns in every language I've used that has them, so I'm pretty biased!

We are returning something though, we're returning nil. If you call a function asking for the first element of an array that is even, but the array is empty, the function doesn't not answer the question, it says 'nothing', and that should be clearly written in the function's code.

1 Like

Hi @Mirko and @Pampel, please don't resurrect threads from 2016.
cc @John_McCall

1 Like

Sorry @xwu I was searching for this feature in Swift forum, and found this old thread.
I thought its better to resurrect old thread and show interest if somebody already asked for the same feature, no pun intended. Feel free to let me know if there is a better way.

@Pampel there are many features in Swift language that don't help readability, but shorten the code, and this is completely acceptable for me. Single line return statement without return keyword is one great example of this.

Regarding example code that would benefit from the "implicit nil return," check out the following computed property:

    var roleAndCompany: String? {
        if let role = role, let company = company {
            return "\(role) @ \(company)"
        } else if let role = role {
            return role
        } else if let company = company {
            return "@ \(company)"
        } else {
            return nil
        }
    }

Yes, start a new thread and quote the relevant parts of threads you found. No need to bump old threads, especially threads that are over 7 years old.

1 Like

@anon9791410 I wasn't sure about official stance either, but I started a new thread anyway (as suggested by @Jon_Shier and @xwu) as an evolution pitch here:

Lets continue discussion about my proposal there. Thanks! :slight_smile:

How to determine if thread is too old to resurrect:

The forum UI itself asks users making the first post trying to resurrect an old post to think again. We are investigating whether the language in that interface can be made more assertive on the point rather than a "hey, just so you know...," but it is not some surprise sprung on users after they post.

Users don't need to look for any criteria or read any links to know about this etiquette because it is presented as part of the UI at the point of pressing "Reply," and there can be no doubt that the forum has "adopted an official stance" when the logic is literally configured in the software itself.

So again, for the benefit of people replying after the thread has been resurrected and therefore don't see the message as a UI element: please stop posting to this thread. I don't know how to make this sound less like a suggestion or invitation to debate the policy here. The threads aren't being auto-locked after some specific elapsed time since we believed we could trust users to respect clear but firm exhortations and apply their best judgment in the gray areas, but if every old thread morphs into a debate about how "official" it is that it's too old, then clearly we need to revisit whether that trust is misplaced.

Again cc'ing @John_McCall to lock.

As the initial poster of this thread, I greatly appreciate its resurrection :) if you start a new thread please post a link to it here so I can follow it. I’d be stoked if there’s enough support of this tiny tweak to introduce a SIP and would be happy to help.

  • Logan