Skip to content

Latest commit

 

History

History
37 lines (23 loc) · 9.62 KB

commonly_proposed.md

File metadata and controls

37 lines (23 loc) · 9.62 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 dashboard includes a list of changes that have been 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

  • Change Array<T> subscript access to 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. Changing the unlabeled array subscript to return an optional has come up multiple times before and is very unlikely to be accepted.

Control Flow, Closures, Optional Binding, and Error Handling

  • 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.
  • Remove or deprecate the force-unwrap operator !: Force-unwrap and force-try are legitimately useful parts of the language, and not just for source stability reasons. Therefore, proposals to deprecate or remove the force-unwrap operator (or try!), even in a mode enabled via compiler flag, will not be considered by the core team. Whether the Swift compiler should gain a more general "linting" capability to guide coding style remains a possible topic of discussion.
  • 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."