I'd like to see compilation conditions back on the drawing board. I really like that they're part of the compilation rather than just string processing, but they're too simple and feel like a forgotten cousin.
Given this thread I'd love to see the related subject of Swift meta language rethought. To that end I'd like to be able to replace gyb (see string processing comment above) with result builder executed at run time to create any Swift eg types.
Removal of callAsFunction in favor of anonymous functions: func (...)
If we then added named subscripts this would align very well:
struct S {
func name(...) {}
func (...) {} // instead of `func callAsFunction(...)`
subscript (...) {}
subscript name(...) {} // new
}
let s = S()
s.name(...) // calling a named method
s(...) // calling an anonymous method
s[...] // calling a subscript
s.name[...] // calling a named subscript
And it would signal on why we really need to fix subscript label rules.
Iâd be in favor of func _() similar to how we can write func hey(_: Int) {}; hey(_: 0). But all in all, I donât see why folks are so against callAsFunction. Yes, itâs not the most natural syntax for Swift but it isnât worth a breaking change in my opinion. Subscript arguments are a blatant exception to Swiftâs argument syntax for functions, which are much more commonly declared.
Sorry if my post came off as aggressive or overly opinionated. I was honestly asking about the arguments for superseding callAsFunction because I havenât really followed related discussions.
The thing is it's not syntax at all, it's a special-cased stringly-typed function name that magically gets turned into an anonymous method. It goes against all compile-safe philosophies of Swift, and, although it's a very minor feature, is hands-down one of the most sub-standard evolution acceptances.
you are talking about @dynamicCallable, which is different from callAsFunction.
anonymous member functions cannot be passed as an object.
elements.map(self.callAsFunction(_:))
this is one of the pain points of subscripts, which need closure literals to be used functionally, and i for one am glad we did not go down this route for functors.
Type Metadata. .Type, and .Protocol changes voice already, but improvements to Mirror, or a newer API would be appreciated.
Tuple, Variadic, and Function parameter list, and fixed size array changes. Personally, I'd be up for a nice mental model for these types and how they compose, even if it introduces a little bit more syntax noise.
A string datatype which enables python like usage. In my experience I've found solving Project Euler problems much less convenient than Swift, and yet the indexing patterns are pretty much the same.
I quite like this, it's very natural, symmetric and it can be almost introduced as a non breaking change (if to deprecate callAsFunction instead of outright removal), but indeed subscript labels rules deserve to be straightened even if that's a breaking change on its own.
I do like the general direction. It doesn't sit well in my mind that callAsFunction (and to a lesser extent subscript) looks like an everyday function but is actually tied into syntactic magic. With Python's dunder sugar (__foo__) there's at least a hint that something special is going on (especially if it's a new corner of the language I've never used or seen before).
people want named subscripts because until very recently, it was not possible to vend mutable views on types with storage. now that we have _move(_:) on mutable self, i canât think of many situations where i would want to use a named subscript instead of a full-featured nested type. it helps keep the base type from becoming cluttered with views.
If we REALLY wanted, we could have allowed a leading dot to refer to an anonymous function self.(_:). There is no big difference between that and callAsFunction except that it's possibly easier to parse as a human. ;)
My guess is that we can still make self.[_:] possible to refer to a subscript.
While you're not wrong, there is always have been a solution for absence of things like toggle(), yet sometimes the convenient part still wins. Requiring the user to do a 'move' dance and coming up with view types to solve this problem smells a lot like unnecessary boilerplate enforcement to me.
However I personally don't want the discussion to derail any further into those specifics.
If we're making breaking changes, I'd love to go back to the (now abandoned) plan of moving unapplied method references from curried functions (Self) -> (Args) -> Result to regular functions (Self, Args) -> Result. Keypath support for methods is nice, but I'd still like usable unapplied mutating methods.
Another one is that Set is not the same same as Set<_> inside extensions with additional constraints on elements:
extension Set where Element == Int {
func dummyFunc() -> Set<String> {
Set(map(\.description))
// â Cannot convert Set<Int> to return type Set<String>
}
}
It always catches me off guard. Iâd rather have to use Self or fully specify the generic parameters.
I might be one of the few people who actually like the basic Codable, but as soon as you move outside of a 'standard' workflow it fails quickly. It would be great to address some areas around this to make it much more flexible and hopefully gain some speed. Some lessons could be learnt from Rust's Serde.
I also really miss having named arguments in tuples. I understand the arguments as to why they were removed, but it just feels like removing useful information from the language.