Agreed. Comparatively with other language implementations, this still feels very much half cooked.
Agreed... and the same goes for functions with extensions... and I'm assuming that generic typealias-ing with this, would also work if the more general non-nominal type issues were addressed.
There are infinite reasons to have (Int, Int), so an extension (Int, Int) seems dangerous to me.
let x = (0, 0)
x.something()
Since Xcode will autocomplete all of the members available through extensions, one would have to be careful that they were using the member(s) they meant to interpreted (Int,Int) with the same semantics as the extensions they're defined in.
typealias XYCoordinates = (Int, Int)
extension XYCoordinates {
var isAtOrigin: Bool { return self.0 == 0 && self.1 == 0 }
}
let pair: XYCoordinates = (0,0)
let b = pair.isAtOrigin
let tuple: (Int, Int) = (0,0)
let b = tuple.isAtOrigin // error, property not found
I can see the value in having extensions on anonymous tuple shapes like (Int, Int) or (T, T) where T: Comparable, but if we could also constrain extensions to named types we could be more disciplined about what we accept in anonymous extensions to avoid accidental programmer error.
I think something that could help with your concerns here is newtype, which would basically be enhanced typealiases that look like separate types while inheriting the original type's functionality. That means you can add independent protocol conformances for what is essentially the same underlying type. I think it could also be a more general solution to the one type, one conformance problem.
you can already define functions with tuples as arguments, which by that logic should be considered "dangerous" as well.
Of course, it wouldn't make too much sense to add semantic methods/extensions to tuples, but there's structural things that can be done, e.g. making tuples equatable and comparable.
Exactly re functions, but so too operators; the ability to extend non-nominal types is a limitation in Swift solely due to its underlying implementation. Whereas in Kotlin, and C# this limitation doesn't exists because both Function and Tuples are essentially nominal types.
As for it wouldn't make too much sense to add comment; that's an opinion I don't share, but its inconsequential here because the topic at hand is about ensuring non-nominal types are as full featured as nominal types.
Tuples in Swift have/had a number of syntactic inconsistencies; many of which the core team and others have strived to remedy (with some push back).
So this particular track is certainly not exposing any new "danger" that wasn't already there. Plus for example: there's nothing stopping the implementation from requiring double wrapping of rounded brackets as has been proposed before, and similarly the agreed amendments should carry forward for any other inconsistencies.
Edit:
Extension methods essentially shouldn't behave any different to this.
typealias XYCoordinates = (Int, Int)
func isAtOrigin(_ tuple: XYCoordinates) -> Bool {
return tuple.0 == 0 && tuple.1 == 0
}
let pair: XYCoordinates = (0,0)
let b = isAtOrigin(pair) // OK
let tuple: (Int, Int) = (0,0)
let b = isAtOrigin(tuple) // OK
I haven't thought about operators in this context, and the trick with a helper type makes it much more easy to see what is going on (hardly any custom operator has an obvious meaning, and they are hard to look up ).
Another alternative are plain old free functions (something along the lines of func with<T>(_ input: T, block: (inout T) -> Void) -> T), which can be defined for all kinds of types...
For reference: Request for Discussion: Setup closures
Returning to the original topic ;-): Is anyone using free functions to work with tuples or closures which would work better as extensions?
The reason I used a postfix operator rather than a free function as a workaround (for the current inability to extend non-nominal types) was that it makes it less cumbersome to both implement and use: You'll get code completion for your extension methods by simply adding eg a • where the cursor is, instead of having to back up and prepend the non-nominally typed value with a free function and wrap it in another set of function-application-parentheses. Free functions are also hard to lookup/discover (they have no context for code completion except the module they are defined in).
would look less clear and require a more involved implementation using free function(s) instead of a postfix operator. (Try implementing it both ways and you'll see what I mean.)
Sure a lot of stuff can be tagged on with custom operators and/or wrappers; and Swift's history is littered with many examples including e.g. this more recent one for turning a keypath into a function .
Would like to know what's the status for this thread, in particular, what are the obstacles to make a function / closure a nominal type.
This is related to my recent work with UnboundedRange, different from PartialRangeUpto or PartialRangeFrom or Range, this is a function, hence, cannot conform to a particular protocol. It presents challenges when supporting it because it requires to enumerate all possible combinations to support multi-dimensional array indexing.
Has there been any more discussion or thought into this feature? I don't fully understand why Swift has this differentiation between nominal and non-nominal types. All languages which just treat tuple/function/types as real types are much more powerful.
"Someone has to do it" is a roundabout way of saying "no one working on the compiler has the motivation, bandwidth, or desire to do it".
The real question is, how do we make this a priority for Apple or someone with the skills to implement it, if there's nothing stopping it? Should someone pitch it? Though I'm sure someone already has… and if someone has, why has someone with the know-how not turned it into a proposal with an implementation?
I'd be happy to write the pitch and proposal if someone can help implement it.
We don’t dictate the engineering priorities of Apple or any other company.
The same options apply as in any open-source project: if you want to see something done, you can do it yourself, you can recruit people to do it with you, you can sponsor someone to do it for you, or you can recruit people to sponsor with you someone to do it for you.
I know. I'm asking how I get the ball rolling. Asking what I need to "do myself" as you say.
If no one has pitched this before, I can write a pitch. If someone has pitched it, why didn't it take off? Is the pitcher unable to implement it themselves like me? Okay, how do I garner support and get someone(s) to help implement it? I've never shipped a Swift feature like this before
FWIW, some other companies have feature request voting systems in place, so that's not entirely true Swift could take some notes
Personally I'm getting sick of features app devs are begging for being sidelined for things we never asked for. It would be nice if we could vote on what gets worked on next instead of shouting into the void and crossing our fingers
Figuring out the answers to these questions is the perfect way to get started! If I wanted to get the ball rolling, I would:
Search these forums for previous discussions about these features, with an eye for talk of implementation details and prior attempts
Figure out what roadblocks, if any, prior attempts have hit
Based on that, I would see how I could apply myself to work around these roadblocks, or at the very least, summarize the current state of affairs and figure out what would be necessary to move forward, implementation-wise
Put together a post detailing this current state of affairs, and based on the difficulty of moving forward:
If within my technical ability: work on an implementation
If beyond my technical ability, but within my capability of understanding of the work that needs to be done: pitch the functionality, detailing the work needed to proceed, and put out a general request for help with the implementation
If beyond my understanding of how work would even proceed, detail what I do know, and tentatively ask if anyone has more insight on what would need to happen to move forward, and go from there
There is always more to be done than time in the day to do it, and at the end of the day, the work needs to be prioritized somehow (and no matter how this is done, someone will be unhappy). The project is always happy to receive contributions from folks who are interested in seeing Swift evolve, and grow in functionality.