how do you refer to a type’s instance subscript getter?
self.indices[key].map(self.subscript(_:))
// error: no property or method named 'subscript';
// did you mean to use the subscript operator?
how do you refer to a type’s instance subscript getter?
self.indices[key].map(self.subscript(_:))
// error: no property or method named 'subscript';
// did you mean to use the subscript operator?
Just this?
self.indices[key].map { self[$0] }
right, that’s what i’m writing right now, but that’s not a reference to the subscript getter, it’s an anonymous function that wraps a call to the subscript getter.
I see, makes sense. Does it lead to a different ASM (in those cases when it works, with a non subscript method)?
It's never been possible.
Same situation for callAsFunction
.
The closest the language allows to what you need is to supply an argument, effectively turning a subscript into a property. In the case of a () ->
subscript, this syntax is just empty brackets.
struct S {
subscript() -> Void {
get { () }
nonmutating set { }
}
}
\S.[] // ReferenceWritableKeyPath<S, ()>
[S()].map(\.[])
S()[keyPath: \.[]] = ()
No similar feature exists for callAsFunction
. Having both ()
and []
in this language is an anachronism.
Is your fear that it will run slower?
I didn't measure any performance differences between map(xxx)
and map { xxx }
in the following test:
import Foundation
struct Foo {
func foobar(_ numbers: [Int]) -> Int {
numbers
.map(subscript2)
// .map { subscript2($0) }
.reduce(0) { $0 &+ $1}
}
func subscript2(_ i: Int) -> Int {
i &* 2 &+ 5678
}
}
let foo = Foo()
let numbers = (0 ... 10000000).map { $0 &* 3 &+ 1234 }
var result = 0
let start = CFAbsoluteTimeGetCurrent()
for _ in 0 ..< 100 {
result &+= foo.foobar(numbers)
}
let elapsed = CFAbsoluteTimeGetCurrent() - start
print("elapsed \(Int(elapsed * 1000)) ms (result: \(result))")
can’t you reference it with instance.callAsFunction(label1:label2:)
? if i remember right, this was the justification for requiring people to declare it as a named function and not a “magic” declaration like func () -> ()
.
As they go over in that thread, yes, and as with methods, you generally don't need explicit labels. The problem is not in lack of possibility of member access, but in ergonomics and consistency.
Subscript getters should be accessible as closures.
"callAsFunction
" instances should be accessible as closures.
Subscripts should be deprecated, and functions should have had setters added.
(1 will not be necessary if this happens instead, but I'm not optimistic.)
Note, you can overload callAsFunction
for getters. I can't tell what you're working with in your post. The most ubiquitous overload is
extension Collection {
func callAsFunction(_ index: Index) -> Element {
self[index]
}
}
[1, 2][0]
[1, 2](0)