Move placement of 'throws' statement


(thislooksfun) #1

Hello Swifters,

I've been writing a lot more Swift code recently, and I have found that the default placement of the 'throws' declaration is often confusing, especially to those of us switching from languages where the type of errors thrown is explicitly defined (like Java)

For example,
// This is pretty clear, this can throw an error
func foo() throws
{ ... }

// Also pretty clear, this returns a String
func bar() -> String
{ ... }

// Confusing. Does this throw a String? Does it return a String? Does it do both?
// I personally keep reading this as 'this can throw a String'
func baz() throws -> String

// Equivalent code in Java (not a model, just for clarification of why the above is confusing)
String baz() throws StringFormatException
I therefore suggest either tweaking the syntax around, or moving, the `throws` keyword to avoid this confusion.

Some ideas I've had:
// Add a comma to separate them
func baz() throws, -> String

// Move `throws` to the end
func baz() -> String throws

// Change it to a prefix modifier (like `mutating`)
throwing func baz() -> String
I'm still not sold on any of the above syntaxes, but I would love to hear your feedback.

This would affect existing code, but it would be a fairly small change that would result in very large readability improvements, especially for newcomers, and especially for those coming for a language such as Java.

-thislooksfun (tlf)


(David Sweeris) #2

Does `throws` affect the actual return type? That is, is the size of the returned data different between "func foo() -> Int8" and "func foo() throws -> Int8"? If so, the "throws" is quite literally part of the return type and the current syntax reflects that. If not, I think I'd probably be in favor of that last "prefix modifier" suggestion with either "throwing" or "@throwing" (depending on the exact semantics of the "@" part — I'm a bit unclear on that detail)... probably... maybe... I'll have to think about it some more.

- Dave Sweeris

···

On Dec 26, 2016, at 09:38, thislooksfun via swift-evolution <swift-evolution@swift.org> wrote:

Hello Swifters,

I've been writing a lot more Swift code recently, and I have found that the default placement of the 'throws' declaration is often confusing, especially to those of us switching from languages where the type of errors thrown is explicitly defined (like Java)

For example,
// This is pretty clear, this can throw an error
func foo() throws
{ ... }

// Also pretty clear, this returns a String
func bar() -> String
{ ... }

// Confusing. Does this throw a String? Does it return a String? Does it do both?
// I personally keep reading this as 'this can throw a String'
func baz() throws -> String

// Equivalent code in Java (not a model, just for clarification of why the above is confusing)
String baz() throws StringFormatException
I therefore suggest either tweaking the syntax around, or moving, the `throws` keyword to avoid this confusion.

Some ideas I've had:
// Add a comma to separate them
func baz() throws, -> String

// Move `throws` to the end
func baz() -> String throws

// Change it to a prefix modifier (like `mutating`)
throwing func baz() -> String
I'm still not sold on any of the above syntaxes, but I would love to hear your feedback.

This would affect existing code, but it would be a fairly small change that would result in very large readability improvements, especially for newcomers, and especially for those coming for a language such as Java.

-thislooksfun (tlf)


(Dave Abrahams) #3

Hello Swifters,

I've been writing a lot more Swift code recently, and I have found
that the default placement of the 'throws' declaration is often
confusing, especially to those of us switching from languages where
the type of errors thrown is explicitly defined (like Java)

For example,
// This is pretty clear, this can throw an error
func foo() throws
{ ... }

// Also pretty clear, this returns a String
func bar() -> String
{ ... }

// Confusing. Does this throw a String? Does it return a String? Does it do both?
// I personally keep reading this as 'this can throw a String'
func baz() throws -> String

// Equivalent code in Java (not a model, just for clarification of why the above is confusing)
String baz() throws StringFormatException
I therefore suggest either tweaking the syntax around, or moving, the
`throws` keyword to avoid this confusion.

Some ideas I've had:
// Add a comma to separate them
func baz() throws, -> String

// Move `throws` to the end
func baz() -> String throws

I agree that reads much better.

···

on Mon Dec 26 2016, thislooksfun <swift-evolution@swift.org> wrote:

// Change it to a prefix modifier (like `mutating`)
throwing func baz() -> String
I'm still not sold on any of the above syntaxes, but I would love to hear your feedback.

This would affect existing code, but it would be a fairly small change
that would result in very large readability improvements, especially
for newcomers, and especially for those coming for a language such as
Java.

-thislooksfun (tlf)

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

--
-Dave


(thislooksfun) #4

As far as I know, `throws` only affects whether or not the code must be marked with a `try` statement, the actual return type/value is unchanged (since it would be unreached if an error was thrown).

-thislooksfun (tlf)

···

On Dec 26, 2016, at 1:18 PM, David Sweeris <davesweeris@mac.com> wrote:

On Dec 26, 2016, at 09:38, thislooksfun via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Hello Swifters,

I've been writing a lot more Swift code recently, and I have found that the default placement of the 'throws' declaration is often confusing, especially to those of us switching from languages where the type of errors thrown is explicitly defined (like Java)

For example,
// This is pretty clear, this can throw an error
func foo() throws
{ ... }

// Also pretty clear, this returns a String
func bar() -> String
{ ... }

// Confusing. Does this throw a String? Does it return a String? Does it do both?
// I personally keep reading this as 'this can throw a String'
func baz() throws -> String

// Equivalent code in Java (not a model, just for clarification of why the above is confusing)
String baz() throws StringFormatException
I therefore suggest either tweaking the syntax around, or moving, the `throws` keyword to avoid this confusion.

Some ideas I've had:
// Add a comma to separate them
func baz() throws, -> String

// Move `throws` to the end
func baz() -> String throws

// Change it to a prefix modifier (like `mutating`)
throwing func baz() -> String
I'm still not sold on any of the above syntaxes, but I would love to hear your feedback.

This would affect existing code, but it would be a fairly small change that would result in very large readability improvements, especially for newcomers, and especially for those coming for a language such as Java.

-thislooksfun (tlf)

Does `throws` affect the actual return type? That is, is the size of the returned data different between "func foo() -> Int8" and "func foo() throws -> Int8"? If so, the "throws" is quite literally part of the return type and the current syntax reflects that. If not, I think I'd probably be in favor of that last "prefix modifier" suggestion with either "throwing" or "@throwing" (depending on the exact semantics of the "@" part — I'm a bit unclear on that detail)... probably... maybe... I'll have to think about it some more.

- Dave Sweeris


(Derrick Ho) #5

I personally do not see anything wrong with its current placement.

It may be there because it was based on an existing cocoa pattern from
objective-c

- (NSString *)bazWithError:(NSError **)error { ... }

Because objective c could only return one thing, using pointer-to-pointer
was needed to deliver more than one.

When swift came along it became this...

func baz(error: NSErrorPointer) -> String

The style felt old-fashioned and was replaced with throw.

func baz() throws -> String

The evolution is consistent. The pattern is familiar. I think we should
keep the placement of throw as it is.

···

On Mon, Dec 26, 2016 at 9:38 AM thislooksfun via swift-evolution < swift-evolution@swift.org> wrote:

Hello Swifters,

I've been writing a lot more Swift code recently, and I have found that the
default placement of the 'throws' declaration is often confusing,
especially to those of us switching from languages where the type of errors
thrown is explicitly defined (like Java)

For example,

// This is pretty clear, this can throw an error

func foo() throws

{ ... }

// Also pretty clear, this returns a String

func bar() -> String

{ ... }

// Confusing. Does this throw a String? Does it return a String? Does
it do both?

// I personally keep reading this as 'this can throw a String'

func baz() throws -> String

// Equivalent code in Java (not a model, just for clarification of why
the above is confusing)

String baz() throws StringFormatException

I therefore suggest either tweaking the syntax around, or moving, the
`throws` keyword to avoid this confusion.

Some ideas I've had:

// Add a comma to separate them

func baz() throws, -> String

// Move `throws` to the end

func baz() -> String throws

// Change it to a prefix modifier (like `mutating`)

throwing func baz() -> String

I'm still not sold on any of the above syntaxes, but I would love to hear
your feedback.

This would affect existing code, but it would be a fairly small change that
would result in very large readability improvements, especially for
newcomers, and *especially* for those coming for a language such as Java.

-thislooksfun (tlf)

_______________________________________________

swift-evolution mailing list

swift-evolution@swift.org

https://lists.swift.org/mailman/listinfo/swift-evolution


(Karl) #6

I agree that this could do with revision. It looks particularly ugly when you’re dealing with throwing closures.

Recently I had a signature like:

public func scan(length: File.ByteOffset.Stride?,
                     by frameSize: File.ByteOffset.Stride,
                     with handler: (_ range: Range<File.ByteOffset>, _ data: UnsafeRawBufferPointer) throws -> Bool) throws -> File.ByteOffset.Stride

It can get difficult to parse the signature towards the end. Marking the handler and function as throwing closer to the beginning would make it more readable IMO. One thing it allows me to do more easily is to remove the spaces around the arrow for the closure parameter (just a little thing which I find helps me read the trailing closure/return type more quickly).

public throwing func scan(length: File.ByteOffset.Stride?,
                                         by frameSize: File.ByteOffset.Stride,
                                         with handler: throwing (_ range: Range<File.ByteOffset>, _ data: UnsafeRawBufferPointer)->Bool) -> File.ByteOffset.Stride

- Karl

···

On 26 Dec 2016, at 18:38, thislooksfun via swift-evolution <swift-evolution@swift.org> wrote:

Hello Swifters,

I've been writing a lot more Swift code recently, and I have found that the default placement of the 'throws' declaration is often confusing, especially to those of us switching from languages where the type of errors thrown is explicitly defined (like Java)

For example,
// This is pretty clear, this can throw an error
func foo() throws
{ ... }

// Also pretty clear, this returns a String
func bar() -> String
{ ... }

// Confusing. Does this throw a String? Does it return a String? Does it do both?
// I personally keep reading this as 'this can throw a String'
func baz() throws -> String

// Equivalent code in Java (not a model, just for clarification of why the above is confusing)
String baz() throws StringFormatException
I therefore suggest either tweaking the syntax around, or moving, the `throws` keyword to avoid this confusion.

Some ideas I've had:
// Add a comma to separate them
func baz() throws, -> String

// Move `throws` to the end
func baz() -> String throws

// Change it to a prefix modifier (like `mutating`)
throwing func baz() -> String
I'm still not sold on any of the above syntaxes, but I would love to hear your feedback.

This would affect existing code, but it would be a fairly small change that would result in very large readability improvements, especially for newcomers, and especially for those coming for a language such as Java.

-thislooksfun (tlf)

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


(Georgios Moschovitis) #7

Indeed,
func baz() throws -> String
is confusing. I do prefer these two alternatives:
// Move `throws` to the end
func baz() -> String throws

// Change it to a prefix modifier (like `mutating`)
throwing func baz() -> String
I think I prefer the first one (throws at the very end).

I wouldn’t mind this source-breaking change.


(Anton Zhilin) #8

This proposal should be reviewed as a part of “typed throws” proposal, with
the original PR <https://github.com/apple/swift-evolution/pull/68> prepared
by David Owens.

Typed throws won’t change anything about how many types can be thrown. Only
one type/protocol will be specified in the function type. You will still be
able to specify throws Error by default, but in the cases, where API
authors put some effort in their error handling, these APIs will be
self-documented and undoubtably easier to work with. In many cases, one can
at least specify some existential error type, which will be
domain-specific, and still better than what we have now.

I feel like Swift, together with Rust, can change current overall mess in
error handling across many programming languages by providing not only
syntax, but also semantics and guidelines. Swift errors, unlike exceptions,
require dealing with them immediately. If one cannot deal with the error,
but error details can be useful on hier levels of abstraction (for actually
solving the problem, not logging), he still should put some work into
wrapping the error, leaving only important details and preparing them for
most conventient access.

On syntax, I feel like this is the obvious one:

func convert(_: String) -> Int throws IntegerConversionError

Basically, we say that the function can either return an Int, or throw an
IntegerConversionError. (Side note: yes, not NumericConversionError, if we
want the API to both provide most detailed information when we need it, and
express the range of possible errors for a particular function through the
type system. However, one can also create hierarchies of error protocols to
aid in abstraction—both abstraction and preciseness are important.)

But can we make a step even further? One can say that the function returns
“either Int or an error”. Rust users blame Swift for creating syntax sugar
for everything—maybe we can live without it this time? Look at it this way:
we already have a deep support for Optional<T> in the language. It’s so
seamless, many people don’t even *realize* they work with Optional<T>. Can
we make working with a standard enum Result<T, E> this simple?

We can even leave current syntax in place, just T throws E will be a sugar
for Result<T, E>. Methods of error handling described in this manifesto
<https://github.com/apple/swift/blob/master/docs/ErrorHandling.rst> will be
represented, respectively, by Optional, Result, and fatalError, with all of
them defined in the standard library—isn’t that reasonable?


(Micah Hainline) #9

I'd prefer the placement at the very end, I do think it would improve readability, especially when taking closures as parameters and returning closures. However, I don't think the value would be worth the cost of breaking existing code. At the least if this were to go forward I would think we'd want both styles to work even if one was preferred or the other was deprecated.

···

On Dec 26, 2016, at 12:41 PM, Derrick Ho via swift-evolution <swift-evolution@swift.org> wrote:

I personally do not see anything wrong with its current placement.

It may be there because it was based on an existing cocoa pattern from objective-c

- (NSString *)bazWithError:(NSError **)error { ... }

Because objective c could only return one thing, using pointer-to-pointer was needed to deliver more than one.

When swift came along it became this...

func baz(error: NSErrorPointer) -> String

The style felt old-fashioned and was replaced with throw.

func baz() throws -> String

The evolution is consistent. The pattern is familiar. I think we should keep the placement of throw as it is.

On Mon, Dec 26, 2016 at 9:38 AM thislooksfun via swift-evolution <swift-evolution@swift.org> wrote:
Hello Swifters,

I've been writing a lot more Swift code recently, and I have found that the default placement of the 'throws' declaration is often confusing, especially to those of us switching from languages where the type of errors thrown is explicitly defined (like Java)

For example,
// This is pretty clear, this can throw an error

func foo() throws

{ ... }

// Also pretty clear, this returns a String

func bar() -> String

{ ... }

// Confusing. Does this throw a String? Does it return a String? Does it do both?

// I personally keep reading this as 'this can throw a String'

func baz() throws -> String

// Equivalent code in Java (not a model, just for clarification of why the above is confusing)

String baz() throws StringFormatException
I therefore suggest either tweaking the syntax around, or moving, the `throws` keyword to avoid this confusion.

Some ideas I've had:
// Add a comma to separate them

func baz() throws, -> String

// Move `throws` to the end

func baz() -> String throws

// Change it to a prefix modifier (like `mutating`)

throwing func baz() -> String

I'm still not sold on any of the above syntaxes, but I would love to hear your feedback.

This would affect existing code, but it would be a fairly small change that would result in very large readability improvements, especially for newcomers, and especially for those coming for a language such as Java.

-thislooksfun (tlf)

_______________________________________________

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


(thislooksfun) #10

I agree that the current form is better than the old way, but a lot of Swift's syntax is based around trying to be friendly for new programmers (remember removal of ++ and --?), and the form `x throws -> y` reads a lot like `x can throw y`, since the arrow is pointing between the two. I just would like some way to make it explicitly clear to those who have not had years of experience with Swift that `throws` is a standalone modifier.

-thislooksfun (tlf)

···

On Dec 26, 2016, at 12:41 PM, Derrick Ho <wh1pch81n@gmail.com> wrote:

I personally do not see anything wrong with its current placement.

It may be there because it was based on an existing cocoa pattern from objective-c

- (NSString *)bazWithError:(NSError **)error { ... }

Because objective c could only return one thing, using pointer-to-pointer was needed to deliver more than one.

When swift came along it became this...

func baz(error: NSErrorPointer) -> String

The style felt old-fashioned and was replaced with throw.

func baz() throws -> String

The evolution is consistent. The pattern is familiar. I think we should keep the placement of throw as it is.

On Mon, Dec 26, 2016 at 9:38 AM thislooksfun via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Hello Swifters,

I've been writing a lot more Swift code recently, and I have found that the default placement of the 'throws' declaration is often confusing, especially to those of us switching from languages where the type of errors thrown is explicitly defined (like Java)

For example,
// This is pretty clear, this can throw an error

func foo() throws

{ ... }

// Also pretty clear, this returns a String

func bar() -> String

{ ... }

// Confusing. Does this throw a String? Does it return a String? Does it do both?

// I personally keep reading this as 'this can throw a String'

func baz() throws -> String

// Equivalent code in Java (not a model, just for clarification of why the above is confusing)

String baz() throws StringFormatException
I therefore suggest either tweaking the syntax around, or moving, the `throws` keyword to avoid this confusion.

Some ideas I've had:
// Add a comma to separate them

func baz() throws, -> String

// Move `throws` to the end

func baz() -> String throws

// Change it to a prefix modifier (like `mutating`)

throwing func baz() -> String

I'm still not sold on any of the above syntaxes, but I would love to hear your feedback.

This would affect existing code, but it would be a fairly small change that would result in very large readability improvements, especially for newcomers, and especially for those coming for a language such as Java.

-thislooksfun (tlf)

_______________________________________________

swift-evolution mailing list

swift-evolution@swift.org <mailto:swift-evolution@swift.org>

https://lists.swift.org/mailman/listinfo/swift-evolution


(Lucas Neiva) #11

I'd prefer the placement at the very end, I do think it would improve readability, especially when taking closures as parameters and returning closures. However, I don't think the value would be worth the cost of breaking existing code. At the least if this were to go forward I would think we'd want both styles to work even if one was preferred or the other was deprecated.

I personally do not see anything wrong with its current placement.

It may be there because it was based on an existing cocoa pattern from objective-c

- (NSString *)bazWithError:(NSError **)error { ... }

Because objective c could only return one thing, using pointer-to-pointer was needed to deliver more than one.

When swift came along it became this...

func baz(error: NSErrorPointer) -> String

The style felt old-fashioned and was replaced with throw.

func baz() throws -> String

The evolution is consistent. The pattern is familiar. I think we should keep the placement of throw as it is.

Hello Swifters,

I've been writing a lot more Swift code recently, and I have found that the default placement of the 'throws' declaration is often confusing, especially to those of us switching from languages where the type of errors thrown is explicitly defined (like Java)

For example,
// This is pretty clear, this can throw an error

func foo() throws

{ ... }

// Also pretty clear, this returns a String

func bar() -> String

{ ... }

// Confusing. Does this throw a String? Does it return a String? Does it do both?

// I personally keep reading this as 'this can throw a String'

func baz() throws -> String

// Equivalent code in Java (not a model, just for clarification of why the above is confusing)

String baz() throws StringFormatException
I therefore suggest either tweaking the syntax around, or moving, the `throws` keyword to avoid this confusion.

Some ideas I've had:
// Add a comma to separate them

func baz() throws, -> String

// Move `throws` to the end

func baz() -> String throws

// Change it to a prefix modifier (like `mutating`)

throwing func baz() -> String

I'm still not sold on any of the above syntaxes, but I would love to hear your feedback.

This would affect existing code, but it would be a fairly small change that would result in very large readability improvements, especially for newcomers, and especially for those coming for a language such as Java.

-thislooksfun (tlf)

_______________________________________________

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

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

···

On 26 Dec 2016, at 19:53, Micah Hainline via swift-evolution <swift-evolution@swift.org> wrote:

On Dec 26, 2016, at 12:41 PM, Derrick Ho via swift-evolution <swift-evolution@swift.org> wrote:
On Mon, Dec 26, 2016 at 9:38 AM thislooksfun via swift-evolution <swift-evolution@swift.org> wrote:


(Lucas Neiva) #12

I like "throwing" as a prefix. It's reads well and fits very nicely with "mutating".

Remembering where to put the keyword for is also easier if it's at the beginning, where it fits grammatically as "throwing func".

···

On 26 Dec 2016, at 19:53, Micah Hainline via swift-evolution <swift-evolution@swift.org> wrote:

I'd prefer the placement at the very end, I do think it would improve readability, especially when taking closures as parameters and returning closures. However, I don't think the value would be worth the cost of breaking existing code. At the least if this were to go forward I would think we'd want both styles to work even if one was preferred or the other was deprecated.

On Dec 26, 2016, at 12:41 PM, Derrick Ho via swift-evolution <swift-evolution@swift.org> wrote:

I personally do not see anything wrong with its current placement.

It may be there because it was based on an existing cocoa pattern from objective-c

- (NSString *)bazWithError:(NSError **)error { ... }

Because objective c could only return one thing, using pointer-to-pointer was needed to deliver more than one.

When swift came along it became this...

func baz(error: NSErrorPointer) -> String

The style felt old-fashioned and was replaced with throw.

func baz() throws -> String

The evolution is consistent. The pattern is familiar. I think we should keep the placement of throw as it is.

On Mon, Dec 26, 2016 at 9:38 AM thislooksfun via swift-evolution <swift-evolution@swift.org> wrote:
Hello Swifters,

I've been writing a lot more Swift code recently, and I have found that the default placement of the 'throws' declaration is often confusing, especially to those of us switching from languages where the type of errors thrown is explicitly defined (like Java)

For example,
// This is pretty clear, this can throw an error

func foo() throws

{ ... }

// Also pretty clear, this returns a String

func bar() -> String

{ ... }

// Confusing. Does this throw a String? Does it return a String? Does it do both?

// I personally keep reading this as 'this can throw a String'

func baz() throws -> String

// Equivalent code in Java (not a model, just for clarification of why the above is confusing)

String baz() throws StringFormatException
I therefore suggest either tweaking the syntax around, or moving, the `throws` keyword to avoid this confusion.

Some ideas I've had:
// Add a comma to separate them

func baz() throws, -> String

// Move `throws` to the end

func baz() -> String throws

// Change it to a prefix modifier (like `mutating`)

throwing func baz() -> String

I'm still not sold on any of the above syntaxes, but I would love to hear your feedback.

This would affect existing code, but it would be a fairly small change that would result in very large readability improvements, especially for newcomers, and especially for those coming for a language such as Java.

-thislooksfun (tlf)

_______________________________________________

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

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


(Daniel Leping) #13

IMO, considering "throws" is a modifier of function/method and determines
how the function can be called (another good example is mutating) the
logical approach would be to make things consistent and move everything
either to the beginning or to the end of declaration.

As long as "throws" is the only modifier at the end it's very logical to
move it to the beginning and rename to "throwing". It feels like "throws"
at the end is rather a legacy, probably from other languages and was a
_default_ way of thinking at the time of initial implementation.

I personally can live with both, though for the sake of consistency it
should be moved to the beginning.

···

On Tue, 27 Dec 2016 at 6:00 thislooksfun via swift-evolution < swift-evolution@swift.org> wrote:

As far as I know, `throws` only affects whether or not the code must be
marked with a `try` statement, the actual return type/value is unchanged
(since it would be unreached if an error was thrown).

-thislooksfun (tlf)

On Dec 26, 2016, at 1:18 PM, David Sweeris <davesweeris@mac.com> wrote:

On Dec 26, 2016, at 09:38, thislooksfun via swift-evolution < > swift-evolution@swift.org> wrote:

Hello Swifters,

I've been writing a lot more Swift code recently, and I have found that
the default placement of the 'throws' declaration is often confusing,
especially to those of us switching from languages where the type of errors
thrown is explicitly defined (like Java)

For example,

// This is pretty clear, this can throw an error

func foo() throws

{ ... }

// Also pretty clear, this returns a String

func bar() -> String

{ ... }

// Confusing. Does this throw a String? Does it return a String? Does it do both?

// I personally keep reading this as 'this can throw a String'

func baz() throws -> String

// Equivalent code in Java (not a model, just for clarification of why the above is confusing)

String baz() throws StringFormatException

I therefore suggest either tweaking the syntax around, or moving, the
`throws` keyword to avoid this confusion.

Some ideas I've had:

// Add a comma to separate them

func baz() throws, -> String

// Move `throws` to the end

func baz() -> String throws

// Change it to a prefix modifier (like `mutating`)

throwing func baz() -> String

I'm still not sold on any of the above syntaxes, but I would love to hear
your feedback.

This would affect existing code, but it would be a fairly small change
that would result in very large readability improvements, especially for
newcomers, and *especially* for those coming for a language such as Java.

-thislooksfun (tlf)

Does `throws` affect the actual return type? That is, is the size of the
returned data different between "func foo() -> Int8" and "func foo() throws
-> Int8"? If so, the "throws" is quite literally part of the return type
and the current syntax reflects that. If not, I *think* I'd probably be
in favor of that last "prefix modifier" suggestion with either "throwing"
or "@throwing" (depending on the exact semantics of the "@" part — I'm a
bit unclear on that detail)... probably... maybe... I'll have to think
about it some more.

- Dave Sweeris

_______________________________________________

swift-evolution mailing list

swift-evolution@swift.org

https://lists.swift.org/mailman/listinfo/swift-evolution


(Tony Allevato) #14

One thing to keep in mind is that, if I recall correctly, some members of
the core team have expressed a desire to enhance `throws` by letting users
list the specific error types that a function can throw. If that is
something that might happen in the future, moving the `throws/throwing` to
the front would add a significant amount of noise before the function name.

···

On Mon, Dec 26, 2016 at 10:29 PM Karl via swift-evolution < swift-evolution@swift.org> wrote:

I agree that this could do with revision. It looks particularly ugly when
you’re dealing with throwing closures.

Recently I had a signature like:

public func scan(length: File.ByteOffset.Stride?,
                     by frameSize: File.ByteOffset.Stride,
                     with handler:
(_ range: Range<File.ByteOffset>, _ data: UnsafeRawBufferPointer) throws -> Bool) throws -> File.ByteOffset.Stride

It can get difficult to parse the signature towards the end. Marking the
handler and function as throwing closer to the beginning would make it more
readable IMO. One thing it allows me to do more easily is to remove the
spaces around the arrow for the closure parameter (just a little thing
which I find helps me read the trailing closure/return type more quickly).

public throwing func scan(length: File.ByteOffset.Stride?,
                                         by
frameSize: File.ByteOffset.Stride,
                                         with handler: throwing
(_ range: Range<File.ByteOffset>, _ data: UnsafeRawBufferPointer)->Bool)
-> File.ByteOffset.Stride

- Karl

On 26 Dec 2016, at 18:38, thislooksfun via swift-evolution < > swift-evolution@swift.org> wrote:

Hello Swifters,

I've been writing a lot more Swift code recently, and I have found that
the default placement of the 'throws' declaration is often confusing,
especially to those of us switching from languages where the type of errors
thrown is explicitly defined (like Java)

For example,

// This is pretty clear, this can throw an error
func foo() throws
{ ... }

// Also pretty clear, this returns a String
func bar() -> String
{ ... }

// Confusing. Does this throw a String? Does it return a String? Does it do both?
// I personally keep reading this as 'this can throw a String'
func baz() throws -> String

// Equivalent code in Java (not a model, just for clarification of why the above is confusing)
String baz() throws StringFormatException

I therefore suggest either tweaking the syntax around, or moving, the
`throws` keyword to avoid this confusion.

Some ideas I've had:

// Add a comma to separate them
func baz() throws, -> String

// Move `throws` to the end
func baz() -> String throws

// Change it to a prefix modifier (like `mutating`)
throwing func baz() -> String

I'm still not sold on any of the above syntaxes, but I would love to hear
your feedback.

This would affect existing code, but it would be a fairly small change
that would result in very large readability improvements, especially for
newcomers, and *especially* for those coming for a language such as Java.

-thislooksfun (tlf)

_______________________________________________
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


(Karl) #15

Maybe we can let the compiler use documentation comments for type-checking. Currently you can do:

/// does something
///
/// - returns: Something cool
///
/// - throws:
/// - `MyError.Something` if a certain thing happens
/// - `POSIXError` if something goes horribly wrong
///
func doSomething() throws -> Int

I would prefer if we found some way to integrate that stuff in to the compiler. I mean, you would probably want to document why the errors get thrown anyway, and it’s better than clobbering up the function signature.

Maybe it seems weird to have the compiler look inside comments (especially if the set of thrown errors becomes a resilience-breaking part of the function), but why not? Swift’s documentation comments are just another source of structured data, and the compiler already understands them at a superficial level.

Just saying, there are options.

···

On 27 Dec 2016, at 07:55, Tony Allevato <tony.allevato@gmail.com> wrote:

One thing to keep in mind is that, if I recall correctly, some members of the core team have expressed a desire to enhance `throws` by letting users list the specific error types that a function can throw. If that is something that might happen in the future, moving the `throws/throwing` to the front would add a significant amount of noise before the function name.

On Mon, Dec 26, 2016 at 10:29 PM Karl via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
I agree that this could do with revision. It looks particularly ugly when you’re dealing with throwing closures.

Recently I had a signature like:

public func scan(length: File.ByteOffset.Stride?,
                     by frameSize: File.ByteOffset.Stride,
                     with handler: (_ range: Range<File.ByteOffset>, _ data: UnsafeRawBufferPointer) throws -> Bool) throws -> File.ByteOffset.Stride

It can get difficult to parse the signature towards the end. Marking the handler and function as throwing closer to the beginning would make it more readable IMO. One thing it allows me to do more easily is to remove the spaces around the arrow for the closure parameter (just a little thing which I find helps me read the trailing closure/return type more quickly).

public throwing func scan(length: File.ByteOffset.Stride?,
                                         by frameSize: File.ByteOffset.Stride,
                                         with handler: throwing (_ range: Range<File.ByteOffset>, _ data: UnsafeRawBufferPointer)->Bool) -> File.ByteOffset.Stride

- Karl

On 26 Dec 2016, at 18:38, thislooksfun via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Hello Swifters,

I've been writing a lot more Swift code recently, and I have found that the default placement of the 'throws' declaration is often confusing, especially to those of us switching from languages where the type of errors thrown is explicitly defined (like Java)

For example,
// This is pretty clear, this can throw an error
func foo() throws
{ ... }

// Also pretty clear, this returns a String
func bar() -> String
{ ... }

// Confusing. Does this throw a String? Does it return a String? Does it do both?
// I personally keep reading this as 'this can throw a String'
func baz() throws -> String

// Equivalent code in Java (not a model, just for clarification of why the above is confusing)
String baz() throws StringFormatException
I therefore suggest either tweaking the syntax around, or moving, the `throws` keyword to avoid this confusion.

Some ideas I've had:
// Add a comma to separate them
func baz() throws, -> String

// Move `throws` to the end
func baz() -> String throws

// Change it to a prefix modifier (like `mutating`)
throwing func baz() -> String
I'm still not sold on any of the above syntaxes, but I would love to hear your feedback.

This would affect existing code, but it would be a fairly small change that would result in very large readability improvements, especially for newcomers, and especially for those coming for a language such as Java.

-thislooksfun (tlf)

_______________________________________________
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


(Matt Whiteside) #16

On syntax, I feel like this is the obvious one:

func convert(_: String) -> Int throws IntegerConversionError

I agree this is the best syntax, though I might add a comma in there for even more readability:

func convert(_:String) -> Int, throws IntegerConversionError {
   ...
}

I wonder if this might be problematic in the presence of trailing where clauses though, as in this contrived example:

func doSomething<S:Sequence>(seq:S) -> Int where S.Iterator == T, S.Iterator: Hashable, throws SomeKindOfError {
   ...
}

It seems like it should be alright, but perhaps I’m missing something.

-Matt

···

On Dec 27, 2016, at 06:38, Anton Zhilin via swift-evolution <swift-evolution@swift.org> wrote:

Basically, we say that the function can either return an Int, or throw an IntegerConversionError. (Side note: yes, not NumericConversionError, if we want the API to both provide most detailed information when we need it, and express the range of possible errors for a particular function through the type system. However, one can also create hierarchies of error protocols to aid in abstraction—both abstraction and preciseness are important.)

But can we make a step even further? One can say that the function returns “either Int or an error”. Rust users blame Swift for creating syntax sugar for everything—maybe we can live without it this time? Look at it this way: we already have a deep support for Optional<T> in the language. It’s so seamless, many people don’t even realize they work with Optional<T>. Can we make working with a standard enum Result<T, E> this simple?

We can even leave current syntax in place, just T throws E will be a sugar for Result<T, E>. Methods of error handling described in this manifesto <https://github.com/apple/swift/blob/master/docs/ErrorHandling.rst> will be represented, respectively, by Optional, Result, and fatalError, with all of them defined in the standard library—isn’t that reasonable?

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


(Chris Lattner) #17

This doesn’t work unless you’re willing to break consistency with function type syntax, or if you’re willing to make function [type/decl] syntax ambiguous.

How would you express this, for example?

  let x : (_ a : Int) throws -> (_ b: Float) throws -> Double

it would be ambiguous to move the ‘throws’ keyword to the end of the function type, because you'd get:

  let x : (_ a : Int) -> (_ b: Float) -> Double throws throws

-Chris

···

On Dec 26, 2016, at 2:55 PM, Dave Abrahams via swift-evolution <swift-evolution@swift.org> wrote:

// Move `throws` to the end
func baz() -> String throws

I agree that reads much better.


(Tyler Cloutier) #18

Hello Swifters,

I've been writing a lot more Swift code recently, and I have found
that the default placement of the 'throws' declaration is often
confusing, especially to those of us switching from languages where
the type of errors thrown is explicitly defined (like Java)

For example,
// This is pretty clear, this can throw an error
func foo() throws
{ ... }

// Also pretty clear, this returns a String
func bar() -> String
{ ... }

// Confusing. Does this throw a String? Does it return a String? Does it do both?
// I personally keep reading this as 'this can throw a String'
func baz() throws -> String

// Equivalent code in Java (not a model, just for clarification of why the above is confusing)
String baz() throws StringFormatException
I therefore suggest either tweaking the syntax around, or moving, the
`throws` keyword to avoid this confusion.

Some ideas I've had:
// Add a comma to separate them
func baz() throws, -> String

// Move `throws` to the end
func baz() -> String throws

I agree that reads much better.

func baz() -> (String | throws)
func baz() -> (String | throws: BazError)
let x: (_ a: Int) -> (throws | (_ b: Float) -> (throws | Double))

Now where getting somewhere. Somewhere weird, to be sure… but somewhere.

···

On Dec 26, 2016, at 2:55 PM, Dave Abrahams via swift-evolution <swift-evolution@swift.org> wrote:
on Mon Dec 26 2016, thislooksfun <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

// Change it to a prefix modifier (like `mutating`)
throwing func baz() -> String
I'm still not sold on any of the above syntaxes, but I would love to hear your feedback.

This would affect existing code, but it would be a fairly small change
that would result in very large readability improvements, especially
for newcomers, and especially for those coming for a language such as
Java.

-thislooksfun (tlf)

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

--
-Dave

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


(Xiaodi Wu) #19

"throws" makes more sense closer to the end of the function signature
because it's an outcome like the return type. Swift's function syntax is
fairly consistent in this regard: <modifiers> func <name>(<inputs>)
<outcomes>.

Personally, I think the keyword is fine where it is and this is the kind
of change where there would have to be *significant* advantages to changing
it. I think it would be hard to make the case that a change at this point
would warrant breaking existing code.

In a vacuum, I too would probably lean towards `throws` being closer to the
end of the signature than it is now, but that's kind of beside the point.

As a meta-comment, although this syntax was introduced prior to the
evolution process, one must expect that the core team debated between all
obvious options and chose the current one over the alternatives. Even
before the current point where source-breaking changes need "extreme"
justification, it would have required significant motivation consisting of,
say, empirical evidence of frequently incorrect code, etc., to justify a
change. The bar for revisiting previous decisions is and justifiably should
be very high; in the recent past, it's generally taken place due to glaring
difficulties found during implementation that could not be fixed without
amending a previous proposal.

···

On Mon, Dec 26, 2016 at 2:20 PM, Tony Allevato via swift-evolution < swift-evolution@swift.org> wrote:

On Mon, Dec 26, 2016 at 10:59 AM Lucas Neiva via swift-evolution < > swift-evolution@swift.org> wrote:

I like "throwing" as a prefix. It's reads well and fits very nicely with
"mutating".

Remembering where to put the keyword for is also easier if it's at the
beginning, where it fits grammatically as "throwing func".

On 26 Dec 2016, at 19:53, Micah Hainline via swift-evolution < >> swift-evolution@swift.org> wrote:

I'd prefer the placement at the very end, I do think it would improve
readability, especially when taking closures as parameters and returning
closures. However, I don't think the value would be worth the cost of
breaking existing code. At the least if this were to go forward I would
think we'd want both styles to work even if one was preferred or the other
was deprecated.

On Dec 26, 2016, at 12:41 PM, Derrick Ho via swift-evolution < >> swift-evolution@swift.org> wrote:

I personally do not see anything wrong with its current placement.

It may be there because it was based on an existing cocoa pattern from
objective-c

- (NSString *)bazWithError:(NSError **)error { ... }

Because objective c could only return one thing, using pointer-to-pointer
was needed to deliver more than one.

When swift came along it became this...

func baz(error: NSErrorPointer) -> String

The style felt old-fashioned and was replaced with throw.

func baz() throws -> String

The evolution is consistent. The pattern is familiar. I think we should
keep the placement of throw as it is.

On Mon, Dec 26, 2016 at 9:38 AM thislooksfun via swift-evolution < >> swift-evolution@swift.org> wrote:

Hello Swifters,

I've been writing a lot more Swift code recently, and I have found that
the default placement of the 'throws' declaration is often confusing,
especially to those of us switching from languages where the type of errors
thrown is explicitly defined (like Java)

For example,

// This is pretty clear, this can throw an error

func foo() throws

{ ... }

// Also pretty clear, this returns a String

func bar() -> String

{ ... }

// Confusing. Does this throw a String? Does it return a String? Does it do both?

// I personally keep reading this as 'this can throw a String'

func baz() throws -> String

// Equivalent code in Java (not a model, just for clarification of why the above is confusing)

String baz() throws StringFormatException

I therefore suggest either tweaking the syntax around, or moving, the
`throws` keyword to avoid this confusion.

Some ideas I've had:

// Add a comma to separate them

func baz() throws, -> String

// Move `throws` to the end

func baz() -> String throws

// Change it to a prefix modifier (like `mutating`)

throwing func baz() -> String

I'm still not sold on any of the above syntaxes, but I would love to hear
your feedback.

This would affect existing code, but it would be a fairly small change
that would result in very large readability improvements, especially for
newcomers, and *especially* for those coming for a language such as Java.

-thislooksfun (tlf)

_______________________________________________

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

_______________________________________________
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

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


(Tony Allevato) #20

"throws" makes more sense closer to the end of the function signature
because it's an outcome like the return type. Swift's function syntax is
fairly consistent in this regard: <modifiers> func <name>(<inputs>)
<outcomes>.

Personally, I think the keyword is fine where it is and this is the kind of
change where there would have to be *significant* advantages to changing
it. I think it would be hard to make the case that a change at this point
would warrant breaking existing code.

···

On Mon, Dec 26, 2016 at 10:59 AM Lucas Neiva via swift-evolution < swift-evolution@swift.org> wrote:

I like "throwing" as a prefix. It's reads well and fits very nicely with
"mutating".

Remembering where to put the keyword for is also easier if it's at the
beginning, where it fits grammatically as "throwing func".

On 26 Dec 2016, at 19:53, Micah Hainline via swift-evolution < > swift-evolution@swift.org> wrote:

I'd prefer the placement at the very end, I do think it would improve
readability, especially when taking closures as parameters and returning
closures. However, I don't think the value would be worth the cost of
breaking existing code. At the least if this were to go forward I would
think we'd want both styles to work even if one was preferred or the other
was deprecated.

On Dec 26, 2016, at 12:41 PM, Derrick Ho via swift-evolution < > swift-evolution@swift.org> wrote:

I personally do not see anything wrong with its current placement.

It may be there because it was based on an existing cocoa pattern from
objective-c

- (NSString *)bazWithError:(NSError **)error { ... }

Because objective c could only return one thing, using pointer-to-pointer
was needed to deliver more than one.

When swift came along it became this...

func baz(error: NSErrorPointer) -> String

The style felt old-fashioned and was replaced with throw.

func baz() throws -> String

The evolution is consistent. The pattern is familiar. I think we should
keep the placement of throw as it is.

On Mon, Dec 26, 2016 at 9:38 AM thislooksfun via swift-evolution < > swift-evolution@swift.org> wrote:

Hello Swifters,

I've been writing a lot more Swift code recently, and I have found that
the default placement of the 'throws' declaration is often confusing,
especially to those of us switching from languages where the type of errors
thrown is explicitly defined (like Java)

For example,

// This is pretty clear, this can throw an error

func foo() throws

{ ... }

// Also pretty clear, this returns a String

func bar() -> String

{ ... }

// Confusing. Does this throw a String? Does it return a String? Does it do both?

// I personally keep reading this as 'this can throw a String'

func baz() throws -> String

// Equivalent code in Java (not a model, just for clarification of why the above is confusing)

String baz() throws StringFormatException

I therefore suggest either tweaking the syntax around, or moving, the
`throws` keyword to avoid this confusion.

Some ideas I've had:

// Add a comma to separate them

func baz() throws, -> String

// Move `throws` to the end

func baz() -> String throws

// Change it to a prefix modifier (like `mutating`)

throwing func baz() -> String

I'm still not sold on any of the above syntaxes, but I would love to hear
your feedback.

This would affect existing code, but it would be a fairly small change
that would result in very large readability improvements, especially for
newcomers, and *especially* for those coming for a language such as Java.

-thislooksfun (tlf)

_______________________________________________

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

_______________________________________________
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