- I shouldn't have used the word "switch". My point is that if (by design or by accident) the "angle bracket" syntax becomes a problem, then it could be deprecated in favor of square brackets, thus "not source breaking", just "a gigantic look-and-feel change".
- I think you misunderstood my point. I'm talking about C/C++ style tricks where malloc-like APIs can take arguments. As I point out in the original post, this goal can be solved other ways (for example, revive the "new" keyword from Swift's pre-beta past).
- This is deeply malloc related. It's similar to the popular "zero sized array" language extension that many compilers support. In any case, I doubt that this feature is worth using reserved/concise syntax, but the larger point is that maybe some unforeseen compiler feature might want the syntax (and as I replied to @jrose, I'm struggling to find a use case for
static subscript
that doesn't feel contrived or a symptom of suboptimal design).
I think we're well past the point of doing (1). We've managed to avoid having to write the angle brackets nearly as often (due to type inference and protocol extensions), and having another spelling for generic argument lists wouldn't improve things at this point.
(Personal viewpoint) In general, I think the only use of the <type> [ ... ]
syntax should be for static subscripts, or not at all. Taking the syntax for (2) or (3) would be surprising, because we've set up expectations with the relationship between static/instance for properties and methods.
Doug
There was some thought of using it to represent dimension for Vectors, Matrices, and Fixed Arrays:
let vec3 : Int[3] = ...
let matrix : Double[2][2] = ...
of course there is also the idea of:
let vec3 : Int x 3 = ...
let matrix : Double x 2 x 2 = ...
I do find the first much easier to read, but that may just be my C background...
I suspect we'd end up with something like:
let vec3: [Int x 3] = ...
let matrix: [Double x 3 x 3] = ...
to keep the square brackets surrounding the type.
Doug
Very reluctant +1.
This feature should exist to keep the consistency between how instance and types can be treated, but I can't help but worry for the bad programming practices this encourages.
Pretty much anything that I can think of that would benefit from being statically-subscript-able, is something that should be mocked in a unit test, and since the static subscript operators is ... static, that can't be done.
Even the Environment
example given, I find to be poorly designed. I would much rather see it implemented as:
public protocol Environment {
public subscript(_ name: String) -> String?
}
public struct RealEnvironment: Environment { /* Bikesheddable name for example purposes */
static let shared = Environment() // Singleton variable
public subscript(_ name: String) -> String? { // now an instance subscript operator
get { return getenv(name).map(String.init(cString:)) }
set {
guard let newValue = newValue else {
unsetenv(name)
return
}
setenv(name, newValue, 1)
}
}
}
Because this is an instance, it introduces a seam, which now makes it possible for a mock object to be substituted in, and used wherever an Environment
is needed:
public struct MockEnvironment: Environment {
var values: [String: String]
init(initialValues: [String: String]) {
self.values = initialValues
}
public subscript(_ name: String) -> String? {
get { return self.values[name] }
set { self.values[name] = newValue }
}
}
This is just basic OO design stuff, I'm sure I'm preaching to the choir, but still. I can't think of anything that would make sense to be statically-subscript-able, that you wouldn't want to mock at some point.
PS: Now that I wrote it, I realize you could make extend Dictionary
to conform to Environment
as is, but that wouldn't be very clear, so I'd probably prefer having the MockEnvironment
anyway, in order to better communicate intent.
This wouldnât preclude that, since you could just write a ânormalâ static subscript function which takes a single âwhatever vectors useâ parameter returns the vector (or its type, depending on how things get implemented).
Completely unnecessary, I find it hard to believe that any non-crappy code would ever actually make use of this.
But consistent with static
let
, var
and func
declarations, so very strong +1
What is your evaluation of the proposal?
+1!
Is the problem being addressed significant enough to warrant a change to Swift?
Yes, it unifies the language consistency.
Does this proposal fit well with the feel and direction of Swift?
Of course.
How much effort did you put into your review? A glance, a quick reading, or an in-depth study?
Read the proposal.
- What is your evaluation of the proposal?
Light +1. I don't think the proposal's use cases are that compelling, but it seems like something that could become more useful over time, and may enable other Swift features.
- Is the problem being addressed significant enough to warrant a change to Swift?
I don't think the lack of this feature is a significant problem, but its addition could make the language more useful without much of a downside.
- Does this proposal fit well with the feel and direction of Swift?
I don't believe there's a good guide on what's expected or desired out of Swift's metatypes, so I can't answer this. In general the solution "feels" like Swift, which is as far as I can go.
- If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
Nope.
- How much effort did you put into your review? A glance, a quick reading, or an in-depth study?
Followed the thread and read the proposal.
Even the
Environment
example given, I find to be poorly designed. I would much rather see it implemented as:public protocol Environment { public subscript(_ name: String) -> String? } public struct RealEnvironment: Environment { /* Bikesheddable name for example purposes */ static let shared = Environment() // Singleton variable public subscript(_ name: String) -> String? { // now an instance subscript operator get { return getenv(name).map(String.init(cString:)) } set { guard let newValue = newValue else { unsetenv(name) return } setenv(name, newValue, 1) } } }
I get where you're coming from, but at some point, you do have to have the actual API that really accesses the environment. It'd be nice if that API wasn't getenv(_:)
, setenv(_:_:_:)
, and unsetenv(_:)
, and pretending that you're merely working with one instance of the actual, real environment is somewhere between silly and misleading.
It'd be nice if that API wasn't
getenv(_:)
,setenv(_:_:_:)
, andunsetenv(_:)
Indeed. Static subscripts would make for a nice replacement. But I think that should be an internal private API, at which point I don't really care whether it uses subscripts or methods, because it wouldn't impact end user ergonomics.
Still, I do support this just for consistency's sake, but I don't think the env example is particularly compelling, and I've struggled to find an example that is.
- What is your evaluation of the proposal?
+1
- Is the problem being addressed significant enough to warrant a change to Swift?
It's not a feature that will find much use in my usual app code, but as the change is purely additive, I'm for it. It doesn't complicate the mental model and it uses the syntax (the square brackets) that is used for subscripting in other cases.
- Does this proposal fit well with the feel and direction of Swift?
Yes, as I see the current feel and direction as cleaning things up and fixing the inconsistencies.
- If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
No comparison.
- How much effort did you put into your review? A glance, a quick reading, or an in-depth study?
Read the proposal, read the thread.
The Core Team has accepted this proposal. Thank you, everyone!