Skip to content

Latest commit

 

History

History
51 lines (26 loc) · 11 KB

commonly_proposed.md

File metadata and controls

51 lines (26 loc) · 11 KB

Commonly Rejected Changes

This is a list of changes to the Swift language that are frequently proposed but that are unlikely to be accepted. If you're interested in pursuing something in this space, please familiarize yourself with the discussions that we have already had. In order to bring one of these topics up, you'll be expected to add new information to the discussion, not just to say, "I really want this" or "this exists in some other language and I liked it there".

Additionally, proposals for out-of-scope changes will not be scheduled for review. The readme file identifies a list of priorities for the next major release of Swift, and the proposal review status page includes a list of changes that have been deferred for future discussion because they were deemed to be out of scope at the time of review (in addition to a list of changes proposed and rejected after a formal review).

Several of the discussions below refer to "C family" languages. This is intended to mean the extended family of languages that resemble C at a syntactic level, such as C++, C#, Objective-C, Java, and Javascript. Swift embraces its C heritage. Where it deviates from other languages in the family, it does so because the feature was thought actively harmful (such as the pre/post-increment ++) or to reduce needless clutter (such as ; or parentheses in if statements).

Basic Syntax and Operators

  • Replace {} brace syntax with Python-style indentation: Surely a polarizing issue, but Swift will not change to use indentation for scoping instead of curly braces.

  • Remove ; semicolons: Semicolons within a line are an intentional expressivity feature. Semicolons at the end of the line should be handled by a linter, not by the compiler.

  • Replace logical operators (&&, ||, !, etc.) with words like "and", "or", "not", and allow non-punctuation operators and infix functions: The operator and identifier grammars are intentionally partitioned in Swift, which is a key part of how user-defined overloaded operators are supported. Requiring the compiler to see the "operator" declaration to know how to parse a file would break the ability to be able to parse a Swift file without parsing all of its imports. This has a major negative effect on tooling support. While not needing infix support, not would need operator or keyword status to omit the parentheses as ! can, and not somePredicate() visually binds too loosely compared to !somePredicate().

  • Replace ?: ternary operator: Definitely magical, but it serves a very important use-case for terse selection of different values. Proposals for alternatives have been intensely discussed, but none have been "better enough" for it to make sense to diverge from the precedent established by the C family of languages.

Strings, Characters, and Collection Types

  • Single-quotes '' for character literals: Swift takes the approach of highly valuing Unicode. However, there are multiple concepts of a character that could make sense in Unicode, and none is so much more commonly used than the others that it makes sense to privilege them. We'd rather save single quoted literals for a greater purpose (e.g. non-escaped string literals).

  • Make Array<T> subscript access return T? or T! instead of T: The current array behavior is intentional, as it accurately reflects the fact that out-of-bounds array access is a logic error. Changing the current behavior would slow Array accesses to an unacceptable degree. This topic has come up multiple times before but is very unlikely to be accepted.

Control Flow, Closures, Optional Binding, and Error Handling

  • if/else and switch as expressions: These are conceptually interesting things to support, but many of the problems solved by making these into expressions are already solved in Swift in other ways. Making them expressions introduces significant tradeoffs, and on balance, we haven't found a design that is clearly better than what we have so far.

  • Replace continue keyword with synonyms from other scripting languages (e.g. next, skip, advance, etc): Swift is designed to feel like a member of the C family of languages. Switching keywords away from C precedent without strong motivation is a non-goal.

  • Remove support for default: in switch and just use case _:: default is widely used, case _ is too magical, and default is widely precedented in many C family languages.

  • Rename guard to unless: It is a common request that guard be renamed unless. People requesting this change argue that guard is simply a logically inverted if statement, and therefore unless is a more obvious keyword. However, such requests stem from a fundamental misunderstanding of the functionality provided by guard. Unlike if, guard enforces that the code within its curly braces provides an early exit from the codepath. In other words, a guard block must return, throw, break, continue or call a function that does not return, such as fatalError(). This differs from if quite significantly, and therefore the parallels assumed between guard and if are not valid.

  • Infer return for omitted guard body: It has been proposed many times to allow omission of the guard body for the sake of brevity. However, a core principle of Swift is to make control flow explicit and visible. For example, the try keyword exists solely to indicate to the human reader where thrown errors can happen. Implicit returns would violate this principle, favoring terseness over clarity in a way that isn't typical of Swift. Furthermore, there are many ways of exiting the scope other than return (loops may want break or continue), and not every function has an obvious default value to return.

  • Change closure literal syntax: Closure syntax in Swift has been carefully debated internally, and aspects of the design have strong motivations. It is unlikely that we'll find something better, and any proposals to change it should have a very detailed understanding of the Swift grammar.

  • Use pattern-matching in if let instead of optional-unwrapping: We actually tried this and got a lot of negative feedback, for several reasons: (1) Most developers don't think about things in "pattern matching" terms, they think about "destructuring". (2) The vastly most common use case for if let is actually for optional matching, and this change made the common case more awkward. (3) This change increases the learning curve of Swift, changing pattern matching from being a concept that can be learned late to something that must be confronted early. (4) The current design of if case unifies "pattern matching" around the case keyword. (5) If a developer unfamiliar with if case runs into one in some code, they can successfully search for it in a search engine or Stack Overflow.

  • Syntactic sugar for if let self-assignment: An alternative syntax (such as if let foo? { ... } or if let foo=? { ... }) to serve as a shorthand for if let foo = foo { ... } is often proposed and rejected because it is favoring terseness over clarity by introducing new magic syntactic sugar.

  • Replace the do/try/repeat keywords with C++-style syntax: Swift's error handling approach is carefully designed to make it obvious to maintainers of code when a call can "throw" an error. It is intentionally designed to be syntactically similar in some ways, but different in other key ways, to exception handling in other languages. Its design is a careful balance that favors maintainers of code that uses errors, to make sure someone reading the code understands what can throw. Before proposing a change to this system, please read the Error Handling Rationale and Proposal in full to understand why the current design is the way it is, and be ready to explain why your changes would be worth unbalancing this design.

Miscellaneous

  • Use garbage collection (GC) instead of automatic reference counting (ARC): Mark-and-sweep garbage collection is a well-known technique used in many popular and widely used languages (e.g., Java and JavaScript) and it has the advantage of automatically collecting reference cycles that ARC requires the programmer to reason about. That said, garbage collection has a large number of disadvantages and using it would prevent Swift from successfully targeting a number of systems programming domains. For example, real-time systems (video or audio processing), deeply embedded controllers, and most kernels find GC to be generally unsuitable. Further, GC is only efficient when given 3–4× more memory to work with than the process is using at any time, and this tradeoff is not acceptable for Swift.

  • Disjunctions (logical ORs) in type constraints: These include anonymous union-like types (e.g. (Int | String) for a type that can be inhabited by either an integer or a string). "[This type of constraint is] something that the type system cannot and should not support."

  • Rewrite the Swift compiler in Swift: This would be a lot of fun someday, but (unless you include rewriting all of LLVM) requires the ability to import C++ APIs into Swift. Additionally, there are lots of higher priority ways to make Swift better.