Prototyping what Swift can look like in educational settings

Believe it or not, it is on my list of things to explore. I’ve already partially implemented a very rudimentary DataObject for hiding some of the medium lifting in PG (and TSQL, though it’s not public at this time). I’ve been poking at LINQ and thinking about possible ways to implement something similar.

···

From: Jens Alfke <jens@mooseyard.com<mailto:jens@mooseyard.com>>
Date: Wednesday, January 6, 2016 at 8:10 PM
To: Andy Satori <dru@druware.com<mailto:dru@druware.com>>
Cc: Dave Fenton <sirdavidfenton@gmail.com<mailto:sirdavidfenton@gmail.com>>, "swift-users@swift.org<mailto:swift-users@swift.org>" <swift-users@swift.org<mailto:swift-users@swift.org>>
Subject: Re: [swift-users] "business applications market" flame

On Jan 6, 2016, at 5:04 PM, Dru Satori <dru@druware.com<mailto:dru@druware.com>> wrote:

Oh, on OS X, swift works fine with PostgreSQL and ODBC datasources via Obj-C frameworks, that isn’t the challenge.

It would be interesting to see how far Swift’s syntax can be pushed to create a cleaner syntax for queries. I’m thinking of C#’s LINQ, which is really sweet. Some LINQ stuff can be replicated in Swift, I believe, but there are parts of it that rely on a super-powerful C# feature where a function can receive a parameter in the form of a parse tree of the expression. (Sort of like LISP macros.)

—Jens

When you use an implicitly-unwrapped optional type like String! here, it can implicitly convert to String, or it can convert to a supertype such as Any. When more than one conversion is possible, the type checker currently always scores the String! to String conversion lower than other conversions, since it would rather perform a safe upcast than a potentially-trapping String! to String conversion, leading to the behavior you're seeing now.

We plan to rework how T! types work soon in order to make their behavior more predictable. I think the plan is to make expressions involving T! always immediately convert to T unless they're in an immediately Optional context, which would give you the behavior you expect in this case. cc'ing Joe Pamer, who's working on the design here.

-Joe

···

On Jan 7, 2016, at 9:12 AM, Don Wills via swift-users <swift-users@swift.org> wrote:

OK, I'll raise a bug. But it brings up a bigger question - what are the rules for overloading method resolution in the context of optionals? Is that a separate bug, or just a documentation issue?

OK, I'll raise a bug. But it brings up a bigger question - what are the rules for overloading method resolution in the context of optionals? Is that a separate bug, or just a documentation issue?

···

On Jan 7, 2016, at 9:59 AM, Jeremy Pereira <jeremy.j.pereira@googlemail.com> wrote:

I think it’s a bug.

This (in which s1 is explicitly unwrapped instead of implicitly unwrapped)

class Test {
   private var s1 : String?

   func tst() {
       let t1 : Test1 = Test1()
       t1.mth("abc", s1!)
   }
}

compiles just fine and should be equivalent to Don’s original code in which s1 is optional but implicitly unwrapped.

I think you should raise a bug, Don.

On 7 Jan 2016, at 04:53, Jens Alfke via swift-users <swift-users@swift.org> wrote:

On Jan 6, 2016, at 7:16 PM, Don Wills via swift-users <swift-users@swift.org> wrote:

Swift method lookup obviously chose the second mth func if it exists, but why?

From the behavior here, it looks like the compiler is first looking for a matching method, then if it can’t find one it unwraps the optional parameter and looks for a match again. So in this case it immediately finds a match (the second mth) and doesn’t try unwrapping the String! parameter.

I have no idea whether that’s correct/intentional behavior, or a bug. I do know that function overloading can create weird situations in any language that supports it (notably C++), so I’m not surprised that there are some edge cases in Swift too.

I really don't understand optionals.

Well, think of the declaration of s1 as being
  private var s1 : Optional<String>
which is what it actually is under the hood. That makes it pretty clear that the 2nd mth method is the one that will get called. The confusion comes in when you also consider that the compiler will implicitly deref an Optional<String> to String if it’s been declared using “!”, in which case the first mth can be called. Now it’s sort of ambiguous which is preferable.

—Jens

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

Oh, on OS X, swift works fine with PostgreSQL and ODBC datasources via Obj-C frameworks, that isn’t the challenge.

It would be interesting to see how far Swift’s syntax can be pushed to create a cleaner syntax for queries. I’m thinking of C#’s LINQ, which is really sweet. Some LINQ stuff can be replicated in Swift, I believe, but there are parts of it that rely on a super-powerful C# feature where a function can receive a parameter in the form of a parse tree of the expression. (Sort of like LISP macros.)

I got part of the way there. I was able to define a set of classes/enums and operator overrides such that I got to the point where I could write

dbConnection.select([“column1", “column2”], from: “table”, where: “column3” == SQL.Integer(1) && “column4” > SQL.Integer(2))

SQL being an enum of the different possible SQL types.

The operators in the where clause did not actually do the and/or/not or comparisons but built up an expression tree that could be serialised into a string version of the where clause for use in a SQL statement.

···

On 7 Jan 2016, at 01:10, Jens Alfke via swift-users <swift-users@swift.org> wrote:

On Jan 6, 2016, at 5:04 PM, Dru Satori <dru@druware.com> wrote:

—Jens

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

Do you really believe that you can stop the "users" who "loathed them so much" from doing what they want to do with Swift? Hubris isn't a strong enough word to describe that attitude.

FWIW, I've already started down the path of dealing with the lack of unchecked <whatever-you-call-em>s by using the following code:

func add(p1: String, _ p2 Any) {
    try! addWithThrows(p1, p2)
}

private func addWithThrows(p1: String, _ p2 Any) throws {
    // code that handles many types for p2, followed by return for each of the valid types
    throw Exception("Invalid type") /* for those types not supported which is a programmer error */
}

public class Exception: ErrorType {
    init() {
    }
    init(_ msg: String) {
    }
}

You can laugh all you at my OPINION about Java's checked and unchecked, but in the end, the great unwashed masses of programmers do whatever they believe is best to build their software, regardless of what programming languages designers believe or try to force upon them.

···

On Jan 7, 2016, at 12:27 PM, Brent Royal-Gordon via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:

IMO, Java has it right - let the API designer decide which approach to take.

That's a frankly laughable misreading of the Java story. The Java story is that they wanted everyone to use checked exceptions, but the users loathed them so much that they found hacks to get around the checked exception system

Do you really believe that you can stop the "users" who "loathed them so much" from doing what they want to do with Swift? Hubris isn't a strong enough word to describe that attitude.

It’s impossible to implement unchecked exceptions in Swift because it lacks any form of stack-unwinding. For example, if A calls B calls C, and B is not marked as ‘throws’, then there is no way for C to return an error back to A. (Unless the error is stored externally, like as an object property, instead of being directly returned.)

FWIW, I've already started down the path of dealing with the lack of unchecked <whatever-you-call-em>s by using the following code:

“try!” isn’t anything like an unchecked exception. It simply ignores the error. It’s the equivalent of the unfortunate Java idiom:
  try {
    somethingThatMightThrowAnException();
  } catch(Exception e) { /* la la la I can’t hear you */ }
Back in my Java days I tracked several mysterious bugs down to usage of this idiom. Internally something was failing, but the exception was ignored so there was no indication of the failure. That made it much harder for me to find.

    throw Exception("Invalid type") /* for those types not supported which is a programmer error */

The correct way to signal a programmer error in Swift is with assert() or fatalError() [sp?]. Which removes your need to use the above workaround, because the method no longer needs to be marked as throws.

—Jens

···

On Jan 7, 2016, at 2:33 PM, Don Wills <don.wills@portablesoftware.com> wrote:

IMO, Java has it right - let the API designer decide which approach to take.

That's a frankly laughable misreading of the Java story. The Java story is that they wanted everyone to use checked exceptions, but the users loathed them so much that they found hacks to get around the checked exception system

Do you really believe that you can stop the "users" who "loathed them so much" from doing what they want to do with Swift? Hubris isn't a strong enough word to describe that attitude.

No, but I think we can design a system that fewer users will hate so much that they actively seek to thwart it. That's why Swift has you mark throwing functions, but doesn't make you declare which errors they can throw—this is seen as a good balance between the anything-goes world of unchecked exceptions and the annoyingly-specific world of checked exceptions.

FWIW, I've already started down the path of dealing with the lack of unchecked <whatever-you-call-em>s by using the following code:

func add(p1: String, _ p2 Any) {
    try! addWithThrows(p1, p2)
}

private func addWithThrows(p1: String, _ p2 Any) throws {
    // code that handles many types for p2, followed by return for each of the valid types
    throw Exception("Invalid type") /* for those types not supported which is a programmer error */
}

public class Exception: ErrorType {
    init() {
    }
    init(_ msg: String) {
    }
}

That's great! You're clearly indicating that addWithThrows(_:_:) can throw, and at the call site you assert non-failure. This may not be the best way to handle errors—a more descriptive ErrorType and some do/catch code could probably give a better error experience, or if all errors should crash you could just use precondition()—but that's your choice. What's important is that the error-handling behavior of your code is obvious to anyone who reads it.

You can laugh all you at my OPINION about Java's checked and unchecked, but in the end, the great unwashed masses of programmers do whatever they believe is best to build their software, regardless of what programming languages designers believe or try to force upon them.

"Laughable" was unkind; I apologize for using that word. What I was trying to get at was that Java's designers never intended for users to use unchecked exceptions very often—this was an unintended consequence of their design.

The design of the language inescapably shapes the code written in it, though not always in the direction the language's designers intend. Java's design was intended to shape code into robustly handling errors; instead, it shaped code to circumvent its safety checks and ignore errors. Swift is trying to learn from those mistakes, by using a less burdensome form of checked errors, and by making it easier to crash when there's an error (using `try!`) than ignore an error (using an empty `catch` clause).

Undoubtedly some people will still find ways to use Swift's error system in unintended ways, but hopefully they will do so less often than they would if we had slavishly copied another language's error handling.

···

--
Brent Royal-Gordon
Architechies

FYI, try! aborts if an error is thrown. It is more analogous to:

try {
  somethingThatMightThrowAnException();
} catch(Exception e) {
  abort(); // this better not happen
}

-Chris

···

On Jan 7, 2016, at 2:56 PM, Jens Alfke via swift-users <swift-users@swift.org> wrote:

On Jan 7, 2016, at 2:33 PM, Don Wills <don.wills@portablesoftware.com <mailto:don.wills@portablesoftware.com>> wrote:

Do you really believe that you can stop the "users" who "loathed them so much" from doing what they want to do with Swift? Hubris isn't a strong enough word to describe that attitude.

It’s impossible to implement unchecked exceptions in Swift because it lacks any form of stack-unwinding. For example, if A calls B calls C, and B is not marked as ‘throws’, then there is no way for C to return an error back to A. (Unless the error is stored externally, like as an object property, instead of being directly returned.)

FWIW, I've already started down the path of dealing with the lack of unchecked <whatever-you-call-em>s by using the following code:

“try!” isn’t anything like an unchecked exception. It simply ignores the error. It’s the equivalent of the unfortunate Java idiom:
  try {
    somethingThatMightThrowAnException();
  } catch(Exception e) { /* la la la I can’t hear you */ }
Back in my Java days I tracked several mysterious bugs down to usage of this idiom. Internally something was failing, but the exception was ignored so there was no indication of the failure. That made it much harder for me to find.

Do you really believe that you can stop the "users" who "loathed them so much" from doing what they want to do with Swift? Hubris isn't a strong enough word to describe that attitude.

It’s impossible to implement unchecked exceptions in Swift because it lacks any form of stack-unwinding. For example, if A calls B calls C, and B is not marked as ‘throws’, then there is no way for C to return an error back to A. (Unless the error is stored externally, like as an object property, instead of being directly returned.)

Actually, that is circular logic. "It is impossible to do A in B because B lacks the thingies necessary to do A." Regardless of that twisted logic, of course Swift could have implemented the stack unwinding stuff. Such support is an integral feature of LLVM. See Exception Handling in LLVM — LLVM 18.0.0git documentation

FWIW, I've already started down the path of dealing with the lack of unchecked <whatever-you-call-em>s by using the following code:

“try!” isn’t anything like an unchecked exception. It simply ignores the error. It’s the equivalent of the unfortunate Java idiom:
  try {
    somethingThatMightThrowAnException();
  } catch(Exception e) { /* la la la I can’t hear you */ }
Back in my Java days I tracked several mysterious bugs down to usage of this idiom. Internally something was failing, but the exception was ignored so there was no indication of the failure. That made it much harder for me to find.

    throw Exception("Invalid type") /* for those types not supported which is a programmer error */

The correct way to signal a programmer error in Swift is with assert() or fatalError() [sp?]. Which removes your need to use the above workaround, because the method no longer needs to be marked as throws.

assert() is of no use because it disappears if optimization is turned on. And fatalError() is also of no use for complex, multi-threaded systems like HTTP servers - systems in which a thread can croak but that you don't want to take down the entire process.

···

On Jan 7, 2016, at 3:56 PM, Jens Alfke <jens@mooseyard.com> wrote:

On Jan 7, 2016, at 2:33 PM, Don Wills <don.wills@portablesoftware.com <mailto:don.wills@portablesoftware.com>> wrote:

There will be those who shoe-horn idioms known from previous programming languages into their Swift programs.

That is not an argument in favor of those idioms being provided in Swift.

···

On Thursday, January 7, 2016 2:33 PM, Don Wills wrote:

You can laugh all you at my OPINION about Java's checked and unchecked, but in the end, the great unwashed masses of programmers do whatever they believe is best to build their software, regardless of what programming languages designers believe or try to force upon them.

As someone who shipped significant Java codebases, I actually found significant value in having readily identifiable anti-patterns that marked bad code. Anywhere API that caught all exceptions, transparently passed all exceptions along, or attempted to catch runtime errors was immediately suspect.

Kate Stone k8stone@apple.com <mailto:k8stone@apple.com>
 Xcode Low Level Tools

···

On Jan 7, 2016, at 12:27 PM, Brent Royal-Gordon via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:

IMO, Java has it right - let the API designer decide which approach to take.

That's a frankly laughable misreading of the Java story. The Java story is that they wanted everyone to use checked exceptions, but the users loathed them so much that they found hacks to get around the checked exception system

Why are you even using throw and try-bang here? It looks like, instead of
throw, you should be using preconditionFailure: “Use this function to stop
the program when control flow can only reach the call if your API was
improperly used.”

https://developer.apple.com/library/ios/documentation/Swift/Reference/Swift_StandardLibrary_Functions/index.html#//apple_ref/swift/func/s:FSs19preconditionFailureFTKT_SS4fileVSs12StaticString4lineSu_T_

···

On Thu, Jan 7, 2016 at 4:33 PM, Don Wills via swift-users < swift-users@swift.org> wrote:

*func add(p1: String, _ p2 Any) {*
* try! addWithThrows(p1, p2)*
*}*

*private func addWithThrows(p1: String, _ p2 Any) throws {*
* // code that handles many types for p2, followed by return for each
of the valid types*
* throw Exception("Invalid type") /* for those types not supported
which is a programmer error */*
*}*

I’m a fan of the Freakonomics folks [1]. They have this mantra that goes something like: trying to persuade people who don't want to be persuaded is a big mistake. When you have this urge to try to persuade people of things that the best thing to do is just to take a deep breath and ask yourself: "Why do I need to persuade them? What's my real reason for wanting to persuade them?"

I took the message to heart a few years back. It has really lowered my
blood pressure and some how the sunny Florida weather just seems
sunnier. You know what I mean?

I digress. Cheers! :beers:

[1]http://freakonomics.com

As someone who shipped significant Java codebases, I actually found significant value in having readily identifiable anti-patterns that marked bad code. Anywhere API that caught all exceptions, transparently passed all exceptions along, or attempted to catch runtime errors was immediately suspect.

Another example of unintended use of the language!

···

--
Brent Royal-Gordon
Architechies

My particular situation was a conversion from Java. There are about 10 different add() methods with different parameters in its containing class. Only one of the add() overloads could cause a RuntimeException. In Java, we use a subclass of RuntimeException as the ReallyBadError indicator that is catchable near the top of the call stack, and possibly recoverable, such as by restarting a thread. The problem is that the calling code is spread across dozens of classes in several different products. Trying to figure out which of the add calls need to be enclosed with this:
  do {
     try add()
  }
  catch()...
is a giant hunt for needles in a haystack, and even if we could find them all would be a maintenance nightmare.

The fact that I bumped into this situation converting a bunch of code from Java is irrelevant. The programming language feature I desire (unchecked thingies that unwind the stack until running into a relevant try/catch) is simply absent in Swift.

Here is a more in depth description of why that feature is important. I need a non-checked <whateveryoucallit> for the *almost* fatal situations that are recoverable at a very high level. NullPointer is the prime example of a non-checked exception in Java. Letting the programmer write code that decides how to deal with such a situation is all I want in Swift. Unfortunately, assert() is irrelevant to the problem and fatalError() is not acceptable. The server needs to stay up, even in the face of latent bugs causing NullPointer exceptions and user-defined versions of similar errors.

The Swift requirement that all throw <struct> statenments must be declared with "throws" in the containing method s a real deal killer for big APIs that want to provide the option for the programmer to build some type of recovery mechanism.

Specifically, the “Use this function to stop the program..." approach you suggest is simply unacceptable. I can't live with the *entire* program to stopping. Think of a program such as Apache Server and you will understand what I'm talking about.

···

On Jan 8, 2016, at 3:28 PM, Rob Mayoff via swift-users <swift-users@swift.org> wrote:

Why are you even using throw and try-bang here? It looks like, instead of throw, you should be using preconditionFailure: “Use this function to stop the program when control flow can only reach the call if your API was improperly used.”

https://developer.apple.com/library/ios/documentation/Swift/Reference/Swift_StandardLibrary_Functions/index.html#//apple_ref/swift/func/s:FSs19preconditionFailureFTKT_SS4fileVSs12StaticString4lineSu_T_

On Thu, Jan 7, 2016 at 4:33 PM, Don Wills via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:

func add(p1: String, _ p2 Any) {
    try! addWithThrows(p1, p2)
}

private func addWithThrows(p1: String, _ p2 Any) throws {
    // code that handles many types for p2, followed by return for each of the valid types
    throw Exception("Invalid type") /* for those types not supported which is a programmer error */
}

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

Hold on. Swift doesn’t run in a virtual machine, doesn’t have a true garbage collector, and doesn’t (to my knowledge) have the same safety guarantees as “managed” languages like Java or C#. It’s a lot safer than C or C++, but buggy Swift programs can crash.

For example, my understanding is that dereferencing an implicitly-unwrapped optional (e.g. an “Int!”) that contains nil really does dereference a null pointer and causes a bus error. Otherwise every such dereference would have to have code in it to preflight the pointer, which is inefficient. Even if I’m wrong and Swift does preflight, it’s response is to trigger a fatalError that crashes the program. (Go is able to catch such a deref and turn it into a recoverable panic, but only because it installs a SIGBUS signal handler in the process, which is part of Go’s “we take over the entire process and do everything our way” philosophy.)

If you have a server process that needs to stay running even if modules fail, then you’ll probably have to run those modules as child processes and monitor them.

Again: apples and oranges.

I see now what you’re asking for, but you’ve been confusing matters by talking about checked vs. unchecked exceptions. As I’ve said many times, Swift has neither. What you want is basically a per-thread fatal error that terminates the thread but leaves the process running. Maybe this can be added in the future, but currently Swift has no intrinsic notion of threads so there’s nowhere to put such a mechanism.

—Jens

···

On Jan 8, 2016, at 3:01 PM, Don Wills via swift-users <swift-users@swift.org> wrote:

The server needs to stay up, even in the face of latent bugs causing NullPointer exceptions and user-defined versions of similar errors.

That sort of perspective is something I can only aspire to. Still, I did enjoy this discourse, and learned a few things along the way :)

···

On Jan 7, 2016, at 7:02 PM, Ryan Lovelett via swift-users <swift-users@swift.org> wrote:

I’m a fan of the Freakonomics folks [1]. They have this mantra that goes something like: trying to persuade people who don't want to be persuaded is a big mistake. When you have this urge to try to persuade people of things that the best thing to do is just to take a deep breath and ask yourself: "Why do I need to persuade them? What's my real reason for wanting to persuade them?"

I took the message to heart a few years back. It has really lowered my blood pressure and some how the sunny Florida weather just seems sunnier. You know what I mean?

I digress. Cheers! :beers:

[1] http://freakonomics.com

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

The server needs to stay up, even in the face of latent bugs causing NullPointer exceptions and user-defined versions of similar errors.

Hold on. Swift doesn’t run in a virtual machine, doesn’t have a true garbage collector, and doesn’t (to my knowledge) have the same safety guarantees as “managed” languages like Java or C#. It’s a lot safer than C or C++, but buggy Swift programs can crash.
For example, my understanding is that dereferencing an implicitly-unwrapped optional (e.g. an “Int!”) that contains nil really does dereference a null pointer and causes a bus error. Otherwise every such dereference would have to have code in it to preflight the pointer, which is inefficient. Even if I’m wrong and Swift does preflight, it’s response is to trigger a fatalError that crashes the program. (Go is able to catch such a deref and turn it into a recoverable panic, but only because it installs a SIGBUS signal handler in the process, which is part of Go’s “we take over the entire process and do everything our way” philosophy.)

My understanding of null references with forced unwrapping of optionals in Swift corresponds with what you say. But that's not what I am talking about. All I am asking for is that the "throws" keyword on a method definition be optional - that is, a method can throw a <thingy> with the throw statement without specifying "throws", and it can be caught by a matching try/catch clause up the stack. That is perfectly possible with LLVM and does not entail any ill-defined behavior. LLVM is capable of and well defined for supporting exactly what I'm looking for.

You first sentence concerns me though. What "safety guarantees" does Swift lack that Java and C# have (other than possible memory leaks because of ARC)? Part of our communication problem is that I don't believe we agree on what the word "managed" means. To me it means "memory management", that is, garbage collection and dynamic class loaders. I suspect you are using it as per Microsoft's definition - a section of code that runs in the CLR that is type and pointer safe, vs. a section of code that is not (ie. "unmanaged"). FWIW, I believe that Microsoft's .NET/CLR is the only place in the computer industry that uses the word "managed" like that.

If you have a server process that needs to stay running even if modules fail, then you’ll probably have to run those modules as child processes and monitor them.

That's really ugly and defeats the whole idea of GCD.

Again: apples and oranges.

I see now what you’re asking for, but you’ve been confusing matters by talking about checked vs. unchecked exceptions. As I’ve said many times, Swift has neither. What you want is basically a per-thread fatal error that terminates the thread but leaves the process running. Maybe this can be added in the future, but currently Swift has no intrinsic notion of threads so there’s nowhere to put such a mechanism.

A per-thread fatal error handler is not the answer though. A full fledged unchecked try/catch handler is what I am looking for, which can be implemented in Swift without any changes to LLVM.

Don

PS. I'll stop calling the object of a throw an exception. Words matter, and yes, Swift documentation does not use the word exception. It is unfortunate that Swift designers decided to use the keywords try, catch and throw and then decided to call what those statements deal with by a name that is different from all other programming languages, AFAIK.

···

On Jan 8, 2016, at 6:47 PM, Jens Alfke <jens@mooseyard.com> wrote:

On Jan 8, 2016, at 3:01 PM, Don Wills via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:

The server needs to stay up, even in the face of latent bugs causing NullPointer exceptions and user-defined versions of similar errors.

Hold on. Swift doesn’t run in a virtual machine, doesn’t have a true garbage collector, and doesn’t (to my knowledge) have the same safety guarantees as “managed” languages like Java or C#. It’s a lot safer than C or C++, but buggy Swift programs can crash.
For example, my understanding is that dereferencing an implicitly-unwrapped optional (e.g. an “Int!”) that contains nil really does dereference a null pointer and causes a bus error. Otherwise every such dereference would have to have code in it to preflight the pointer, which is inefficient. Even if I’m wrong and Swift does preflight, it’s response is to trigger a fatalError that crashes the program. (Go is able to catch such a deref and turn it into a recoverable panic, but only because it installs a SIGBUS signal handler in the process, which is part of Go’s “we take over the entire process and do everything our way” philosophy.)

All I am asking for is that the "throws" keyword on a method definition be optional - that is, a method can throw a <thingy> with the throw statement without specifying "throws", and it can be caught by a matching try/catch clause up the stack. That is perfectly possible with LLVM and does not entail any ill-defined behavior. LLVM is capable of and well defined for supporting exactly what I'm looking for.

Swift made a conscious choice not to include exceptions thrown through arbitrary stack frames not because it was technically impossible, but because its designers judged the costs to be too high.

The problem is this: if a piece of code is going to exit early because of an error, it has to be written to handle that early exit. Otherwise it will misbehave—fail to deallocate memory, fail to close file handles/sockets/database connections/whatever, fail to release locks, etc. In a language like Java, writing truly exception-safe code requires a ridiculous quantity of try/finally blocks. That's why nobody does it. They make judgements about which exceptions they're likely to see and which resources are dangerous to leak, and only protect their code against those specific anticipated conditions. Then something unforeseen happens and their program breaks.

This is even worse in a reference-counted language like Swift because correctly balancing the reference counts in the presence of exceptions basically requires every function to include an implicit finally block to balance all the retain counts. This means the compiler has to generate lots of extra code on the off chance that some call or another throws an exception. The vast majority of this code is never, ever used, but it has to be there, bloating the process.

Because of these problems, Swift chose not to support traditional exceptions; instead, it only allows you to throw errors in specially-marked regions of code. But as a corollary, that means that, if something goes really wrong in code that can't throw, all it can really do to prevent a disaster is crash. And currently, the only thing you can crash is the entire process.

Eventually it may become possible to create some kind of self-contained unit of code within a process; a failed precondition would only crash the unit it's in, and since that code's side effects could only be within that unit, the rest of the process could safely continue running. But right now, no such feature exists.

You first sentence concerns me though. What "safety guarantees" does Swift lack that Java and C# have (other than possible memory leaks because of ARC)? Part of our communication problem is that I don't believe we agree on what the word "managed" means. To me it means "memory management", that is, garbage collection and dynamic class loaders. I suspect you are using it as per Microsoft's definition - a section of code that runs in the CLR that is type and pointer safe, vs. a section of code that is not (ie. "unmanaged"). FWIW, I believe that Microsoft's .NET/CLR is the only place in the computer industry that uses the word "managed" like that.

The CLR and especially the JVM try to create a safe, hermetically-sealed environment where, to a first approximation, nothing bad can ever happen. You can't crash a process without it causing a catchable exception. You can't get a reference to memory unless it's part of a properly-allocated, correctly-initialized, and still-present object. You can't cause the garbage collector to free an object that's still accessible, or leak an object that isn't anymore. You literally can't express unsafe constructs in their bytecodes. There are some escape hatches, particularly in the CLR, and of course there are bugs that make it possible to do things that shouldn't be allowed, but the goal is to create safety guarantees that are literally impossible to subvert, so that it's safe to run code from an untrusted source.

Swift is not like that. Compiled Swift code is machine code; there's just no validating it. The standard library includes constructs that can access arbitrary memory addresses. Memory management is done with reference counting, and the Unmanaged type in the library can subvert it. You can call freely into arbitrary machine code. And a crash is a crash, not an exception. There's simply no attempt to provide the level of complete safety that the CLR and JVM attempt to achieve.

If you have a server process that needs to stay running even if modules fail, then you’ll probably have to run those modules as child processes and monitor them.

That's really ugly and defeats the whole idea of GCD.

GCD is meant for lightweight concurrency in a shared memory space. Though it provides tools to help mediate between activities on different queues, it makes no attempt to *prevent* activity on one queue from screwing up another queue.

A per-thread fatal error handler is not the answer though. A full fledged unchecked try/catch handler is what I am looking for, which can be implemented in Swift without any changes to LLVM.

Again, not in a fully safe way, and not without significant costs that Swift's designers judged to not be worth it.

···

--
Brent Royal-Gordon
Architechies

All I am asking for is that the "throws" keyword on a method definition be optional - that is, a method can throw a <thingy> with the throw statement without specifying "throws", and it can be caught by a matching try/catch clause up the stack.

That’s asking for much, much, much more than making a keyword optional. You’re asking for the underlying error handling mechanism to be something completely different than what it is, i.e. stack-unwinding exceptions rather than returning an error value.

That is perfectly possible with LLVM and does not entail any ill-defined behavior.

There is a vast difference between machine code supporting something, and a language supporting it. You could say the same thing about nearly any language feature that Swift decided not to support. “But LLVM allows multiple inheritance!” “There’s nothing in LLVM preventing making all value bindings immutable!” “LLVM supports goto statements!"

The designers of Swift do not like exceptions. They decided not to include them in the language. Arguing for exceptions here is a tiresome religious war. When I worked at Apple I had some arguments about exceptions with people on the Cocoa and compiler teams. I definitely prefer exceptions to plain old return values (as in C or Go or Swift 1.x), but the compromise in Swift 2 is good enough that I’m happy with it, and I appreciate arguments like Brent’s about the overhead it saves. (If you’ve looked t the disassembly of exception-heavy C++ code, you can see all the code-size overhead it adds.)

All language designers have features they dislike and won’t add. Try arguing for late-binding dynamic dispatch to C++ gurus. Try arguing for explicit “free” calls in a Java forum. Tell the Haskell maintainers that mutable variables make coding so much easier. If you think language designers should give in and add every feature someone thinks is important, then you get the real kitchen sink you keep saying Swift is.

That’s the last I’m going to write about this. It’s stopped having any value. I’ve been around long enough to be sick of language flame wars, and that’s about all this is.

—Jens

···

On Jan 8, 2016, at 6:38 PM, Don Wills <don.wills@portablesoftware.com> wrote: