I would not characterize not trapping when an assertion fails as “fault tolerance.” There is no guarantee whatsoever that continued operation is in any way correct or that any incorrectness is proportional to the fault. If we could make such a guarantee, your point would stand, but the logic behind halting execution entirely by default is that we can make no such guarantees.
It is necessary, but not sufficient. Trapping certainly is not fault tolerant...
No, Ben, you're flipping my implication around. I'm not judging anybody's use of the term. I'm saying that the kind of “safety” referred to by the OP is not something we can supply as any kind of guarantee, and a trap that occurs because of the way you used
enumerate() is not in conflict with what we ever intended to promise by saying “swift is a safe language.” That's only an absolute truth w.r.t. memory safety, and yes, the kind of safety you say is defined in the dictionary is more casual because it can't be formally defined.
I don’t know of anyone making that claim.
To sum up, not trapping is not a form of fault tolerance, and it does not provide a “type of safety.”
I do think “lenience” is a fairly good term for this behavior, as it affords the user an opportunity to provide other forms of recovery. That lenience can be used well, resulting in some degree of fault tolerance, or it can be abused, resulting in even less safety. This possibility of either good or bad effect up to the end user is well captured, I think, by the idea of the behavior being described as “lenient.”
Trapping is NOT fault tolerant... thus knowing that something doesn't trap is necessary to provide fault tolerance.
You are forgetting that we are talking about the word "Safe" here. I am pointing out that if people are thinking of "safe" as fault tolerant (which is a reasonable assumption for those outside the SE discussions), then they are quite surprised when we classify trapping as "safe".
It isn't that not trapping provides a type of safety so much that trapping removes a form of safety.
To be clear, I am not arguing that we shouldn't trap... just that we need to understand why there has been confusion, find consistent language to talk about these different concepts, and then be clearer in our use of them. As @Nevin said, we need to educate.
Not so. It is not true that, but for trapping, Swift would be more fault tolerant. No form of fault tolerance is offered by not trapping in Swift, and no safety is removed by trapping.
That is indeed a pain point for some users. It is also the case that they are quite surprised that not trapping is unsafe (even in the sense of “not fault tolerant”), which in the general case (i.e., without dedicated alternative error handling, which requires anticipating the logic error, which could equally be done whether Swift traps or doesn’t trap) it is.
Please stop attributing your strawman arguments to me and then arguing against them instead of what I am actually saying. Please go back and take a minute to read what I actually wrote.
I’m not sure why you think I’m trying to attribute any arguments to you that you didn’t write, or that I’m trying to argue against you. I’m drilling down on specific points that I think could stand some elaboration in this conversation.
Because you keep quoting me and then saying things like:
Which is attributing a different argument than the one I made to me.
The only thing I am really arguing is that people who are not deep into Swift culture are confused by the way we use terminology and we need to fix that. If we don't want to give up "safe" as meaning "memory safe", then we need to make a term to explicitly represent the larger (non-memory centric) concept and educate around that.
I believe the issue here is that the Swift team, and many, many other software engineers, categorically deny your assertion "that trapping removes a form of safety". Trapping is the only form of safety that can be provided for violated invariants unless one knows exactly what the code is doing. Anything else requires domain knowledge.
Again, I am not arguing against trapping, just that we need to be clearer in our language around it.
This is not true where throwing or returning an optional is possible. Both throwing and optionals allow parts of the code with greater domain knowledge to handle the issue. That said, there are certainly places where we have (correctly) chosen to trap for either speed or ergonomic reasons. There are also a couple of places left where trapping may be the only option.
Which is fine. I have not once in this thread (despite being quoted out of context) argued that we shouldn't trap in those cases. It is however really important to know where traps might happen in code, and to communicate that clearly.
I don't think anyone can reasonably argue that there isn't confusion around the term "safe" here because it keeps. coming. up.
That confusion is something we need to deal with in one way or another. The way I have suggested is by being explicit in our terms, using them consistently, and educating. I don't see why that is so controversial...
Throwing and returning optionals are not for violated invariants, they're for expected failure states. Those are two completely different things. When we speak of invariants we mean things like, "this pointer is never null". Much grief has been caused by the fact that dereferencing a null pointer in C is undefined behaviour instead of being required to trap.
This example is exactly 100% the use-case of optionals.
I greatly prefer Swift's use of optionals to trapping on nil...
Optionals force me to consider "Even though it is not supposed to be, what if it is somehow nil? How should I handle that?". Also, by having an explicit way to represent when something could be nil, it gives us a way to represent that something ACTUALLY CAN'T BE nil (the non-optional form) as a full guarantee...
Yes, but one of the ways it forces you to do that is that if you simply
! the optional, then you crash if it's
nil. If it didn't, very few people would learn not to just dereference an optional.
Sure. Read what I said above again... I am not arguing against trapping. I will say that it needs to be clear where it can happen (and
! is great for telling readers of code where something might crash so they can reason about it). Adding
! is also an explicit choice being made on how to handle it (as opposed to the C problem of forgetting to check if it is 0)