Rationale behind Swift's BidirectionalCollection extension - ios

It is my understanding that extensions are often used on protocols to provide a default implementation. My question is about a pattern I have observed in the Swift Standard Library's protocol BidirectionalCollection. Consider the code below:
protocol BidirectionalCollection: {
// other method requirements ...
func distance(from start: Self.Index, to end: Self.Index) -> Int
// other method requirements ...
}
followed by
extension BidirectionalCollection {
// other default implementations ...
#inlinable public func distance(from start: Self.Index, to end: Self.Index) -> Int
// other default implementations ...
}
I don't understand two things about this extension:
Why we are able to write the method without a body (which I have always seen in default method implementations), and
What value this specific extension brings. At first glance the only difference just seems the leading #inlinable public. But can't protocol method requirements be prepended with those keywords anyway? What is the use of doing it in the protocol extension?

Related

Difference between generic function whose return type is protocol and nongeneric function whose argument and return type are protocol

When I work on the opaque types, I read this section in the official documents of Swift.
Another problem with this approach is that the shape transformations
don’t nest. The result of flipping a triangle is a value of type
Shape, and the protoFlip(:) function takes an argument of some type
that conforms to the Shape protocol. However, a value of a protocol
type doesn’t conform to that protocol; the value returned by
protoFlip(:) doesn’t conform to Shape. This means code like
protoFlip(protoFlip(smallTriange)) that applies multiple
transformations is invalid because the flipped shape isn’t a valid
argument to protoFlip(_:).
This part made me consider about nested functions whose return type is protocol and I wanted to play about the protocol return types in the playground. As a result, I created a protocol called Example and also, a non generic and generic concrete types that conform to Example protocol. I kept "sample" method implementations which is protocol requirement as simple as possible because of focusing return types.
protocol Example {
func sample(text: String) -> String
}
struct ExampleStruct: Example {
func sample(text: String) -> String {
return text
}
}
struct ExampleGenericStruct<T: Example>: Example {
var t: T
func sample(text: String) -> String {
return t.sample(text: "\n")
}
}
After that, I created a generic function which has an argument constraint by Example protocol and returns Example protocol. Then, I tested my function as nested.
func genericTestExample<T: Example>(example: T) -> Example {
return ExampleGenericStruct(t: example)
}
genericTestExample(example: genericTestExample(example: ExampleStruct()))
I got this error:
Value of protocol type 'Example' cannot conform to 'Example'; only
struct/enum/class types can conform to protocols
This is what I expected. Function returns the protocol itself, not the concrete type that conforms it.
Finally, I wrote an another function.
func testExample(example: Example) -> Example {
if example is ExampleStruct {
return example
}
return ExampleGenericStruct(t: ExampleStruct())
}
When I run the code, I could nest this function successfully.
testExample(example: testExample(example: ExampleStruct()))
I can pass any value to both genericTestExample and testExample functions as long as it conforms to Example protocol. Also, they have the same protocol return type. I don't know why I could nest testExample function while I could not nest genericTestExample function or vise versa.
swift 5.4
2021-09-27 08:36 UTC
#ceylanburak
you should use the Opaque Types in swift.
// some Example is **Opaque Types** !!!
func genericTestExample<T: Example>(example: T) -> some Example {
return ExampleGenericStruct(t: example)
}
now follow your previous mind
genericTestExample(example: genericTestExample(example: ExampleStruct()))
and it equals to
let e1: some Example = genericTestExample(example: ExampleStruct())
genericTestExample(example: e1)

Associatedtype depends on protocol [duplicate]

Why doesn't this Swift code compile?
protocol P { }
struct S: P { }
let arr:[P] = [ S() ]
extension Array where Element : P {
func test<T>() -> [T] {
return []
}
}
let result : [S] = arr.test()
The compiler says: "Type P does not conform to protocol P" (or, in later versions of Swift, "Using 'P' as a concrete type conforming to protocol 'P' is not supported.").
Why not? This feels like a hole in the language, somehow. I realize that the problem stems from declaring the array arr as an array of a protocol type, but is that an unreasonable thing to do? I thought protocols were there exactly to help supply structs with something like a type hierarchy?
Why don't protocols conform to themselves?
Allowing protocols to conform to themselves in the general case is unsound. The problem lies with static protocol requirements.
These include:
static methods and properties
Initialisers
Associated types (although these currently prevent the use of a protocol as an actual type)
We can access these requirements on a generic placeholder T where T : P – however we cannot access them on the protocol type itself, as there's no concrete conforming type to forward onto. Therefore we cannot allow T to be P.
Consider what would happen in the following example if we allowed the Array extension to be applicable to [P]:
protocol P {
init()
}
struct S : P {}
struct S1 : P {}
extension Array where Element : P {
mutating func appendNew() {
// If Element is P, we cannot possibly construct a new instance of it, as you cannot
// construct an instance of a protocol.
append(Element())
}
}
var arr: [P] = [S(), S1()]
// error: Using 'P' as a concrete type conforming to protocol 'P' is not supported
arr.appendNew()
We cannot possibly call appendNew() on a [P], because P (the Element) is not a concrete type and therefore cannot be instantiated. It must be called on an array with concrete-typed elements, where that type conforms to P.
It's a similar story with static method and property requirements:
protocol P {
static func foo()
static var bar: Int { get }
}
struct SomeGeneric<T : P> {
func baz() {
// If T is P, what's the value of bar? There isn't one – because there's no
// implementation of bar's getter defined on P itself.
print(T.bar)
T.foo() // If T is P, what method are we calling here?
}
}
// error: Using 'P' as a concrete type conforming to protocol 'P' is not supported
SomeGeneric<P>().baz()
We cannot talk in terms of SomeGeneric<P>. We need concrete implementations of the static protocol requirements (notice how there are no implementations of foo() or bar defined in the above example). Although we can define implementations of these requirements in a P extension, these are defined only for the concrete types that conform to P – you still cannot call them on P itself.
Because of this, Swift just completely disallows us from using a protocol as a type that conforms to itself – because when that protocol has static requirements, it doesn't.
Instance protocol requirements aren't problematic, as you must call them on an actual instance that conforms to the protocol (and therefore must have implemented the requirements). So when calling a requirement on an instance typed as P, we can just forward that call onto the underlying concrete type's implementation of that requirement.
However making special exceptions for the rule in this case could lead to surprising inconsistencies in how protocols are treated by generic code. Although that being said, the situation isn't too dissimilar to associatedtype requirements – which (currently) prevent you from using a protocol as a type. Having a restriction that prevents you from using a protocol as a type that conforms to itself when it has static requirements could be an option for a future version of the language
Edit: And as explored below, this does look like what the Swift team are aiming for.
#objc protocols
And in fact, actually that's exactly how the language treats #objc protocols. When they don't have static requirements, they conform to themselves.
The following compiles just fine:
import Foundation
#objc protocol P {
func foo()
}
class C : P {
func foo() {
print("C's foo called!")
}
}
func baz<T : P>(_ t: T) {
t.foo()
}
let c: P = C()
baz(c)
baz requires that T conforms to P; but we can substitute in P for T because P doesn't have static requirements. If we add a static requirement to P, the example no longer compiles:
import Foundation
#objc protocol P {
static func bar()
func foo()
}
class C : P {
static func bar() {
print("C's bar called")
}
func foo() {
print("C's foo called!")
}
}
func baz<T : P>(_ t: T) {
t.foo()
}
let c: P = C()
baz(c) // error: Cannot invoke 'baz' with an argument list of type '(P)'
So one workaround to to this problem is to make your protocol #objc. Granted, this isn't an ideal workaround in many cases, as it forces your conforming types to be classes, as well as requiring the Obj-C runtime, therefore not making it viable on non-Apple platforms such as Linux.
But I suspect that this limitation is (one of) the primary reasons why the language already implements 'protocol without static requirements conforms to itself' for #objc protocols. Generic code written around them can be significantly simplified by the compiler.
Why? Because #objc protocol-typed values are effectively just class references whose requirements are dispatched using objc_msgSend. On the flip side, non-#objc protocol-typed values are more complicated, as they carry around both value and witness tables in order to both manage the memory of their (potentially indirectly stored) wrapped value and to determine what implementations to call for the different requirements, respectively.
Because of this simplified representation for #objc protocols, a value of such a protocol type P can share the same memory representation as a 'generic value' of type some generic placeholder T : P, presumably making it easy for the Swift team to allow the self-conformance. The same isn't true for non-#objc protocols however as such generic values don't currently carry value or protocol witness tables.
However this feature is intentional and is hopefully to be rolled out to non-#objc protocols, as confirmed by Swift team member Slava Pestov in the comments of SR-55 in response to your query about it (prompted by this question):
Matt Neuburg added a comment - 7 Sep 2017 1:33 PM
This does compile:
#objc protocol P {}
class C: P {}
func process<T: P>(item: T) -> T { return item }
func f(image: P) { let processed: P = process(item:image) }
Adding #objc makes it compile; removing it makes it not compile again.
Some of us over on Stack Overflow find this surprising and would like
to know whether that's deliberate or a buggy edge-case.
Slava Pestov added a comment - 7 Sep 2017 1:53 PM
It's deliberate – lifting this restriction is what this bug is about.
Like I said it's tricky and we don't have any concrete plans yet.
So hopefully it's something that language will one day support for non-#objc protocols as well.
But what current solutions are there for non-#objc protocols?
Implementing extensions with protocol constraints
In Swift 3.1, if you want an extension with a constraint that a given generic placeholder or associated type must be a given protocol type (not just a concrete type that conforms to that protocol) – you can simply define this with an == constraint.
For example, we could write your array extension as:
extension Array where Element == P {
func test<T>() -> [T] {
return []
}
}
let arr: [P] = [S()]
let result: [S] = arr.test()
Of course, this now prevents us from calling it on an array with concrete type elements that conform to P. We could solve this by just defining an additional extension for when Element : P, and just forward onto the == P extension:
extension Array where Element : P {
func test<T>() -> [T] {
return (self as [P]).test()
}
}
let arr = [S()]
let result: [S] = arr.test()
However it's worth noting that this will perform an O(n) conversion of the array to a [P], as each element will have to be boxed in an existential container. If performance is an issue, you can simply solve this by re-implementing the extension method. This isn't an entirely satisfactory solution – hopefully a future version of the language will include a way to express a 'protocol type or conforms to protocol type' constraint.
Prior to Swift 3.1, the most general way of achieving this, as Rob shows in his answer, is to simply build a wrapper type for a [P], which you can then define your extension method(s) on.
Passing a protocol-typed instance to a constrained generic placeholder
Consider the following (contrived, but not uncommon) situation:
protocol P {
var bar: Int { get set }
func foo(str: String)
}
struct S : P {
var bar: Int
func foo(str: String) {/* ... */}
}
func takesConcreteP<T : P>(_ t: T) {/* ... */}
let p: P = S(bar: 5)
// error: Cannot invoke 'takesConcreteP' with an argument list of type '(P)'
takesConcreteP(p)
We cannot pass p to takesConcreteP(_:), as we cannot currently substitute P for a generic placeholder T : P. Let's take a look at a couple of ways in which we can solve this problem.
1. Opening existentials
Rather than attempting to substitute P for T : P, what if we could dig into the underlying concrete type that the P typed value was wrapping and substitute that instead? Unfortunately, this requires a language feature called opening existentials, which currently isn't directly available to users.
However, Swift does implicitly open existentials (protocol-typed values) when accessing members on them (i.e it digs out the runtime type and makes it accessible in the form of a generic placeholder). We can exploit this fact in a protocol extension on P:
extension P {
func callTakesConcreteP/*<Self : P>*/(/*self: Self*/) {
takesConcreteP(self)
}
}
Note the implicit generic Self placeholder that the extension method takes, which is used to type the implicit self parameter – this happens behind the scenes with all protocol extension members. When calling such a method on a protocol typed value P, Swift digs out the underlying concrete type, and uses this to satisfy the Self generic placeholder. This is why we're able to call takesConcreteP(_:) with self – we're satisfying T with Self.
This means that we can now say:
p.callTakesConcreteP()
And takesConcreteP(_:) gets called with its generic placeholder T being satisfied by the underlying concrete type (in this case S). Note that this isn't "protocols conforming to themselves", as we're substituting a concrete type rather than P – try adding a static requirement to the protocol and seeing what happens when you call it from within takesConcreteP(_:).
If Swift continues to disallow protocols from conforming to themselves, the next best alternative would be implicitly opening existentials when attempting to pass them as arguments to parameters of generic type – effectively doing exactly what our protocol extension trampoline did, just without the boilerplate.
However note that opening existentials isn't a general solution to the problem of protocols not conforming to themselves. It doesn't deal with heterogenous collections of protocol-typed values, which may all have different underlying concrete types. For example, consider:
struct Q : P {
var bar: Int
func foo(str: String) {}
}
// The placeholder `T` must be satisfied by a single type
func takesConcreteArrayOfP<T : P>(_ t: [T]) {}
// ...but an array of `P` could have elements of different underlying concrete types.
let array: [P] = [S(bar: 1), Q(bar: 2)]
// So there's no sensible concrete type we can substitute for `T`.
takesConcreteArrayOfP(array)
For the same reasons, a function with multiple T parameters would also be problematic, as the parameters must take arguments of the same type – however if we have two P values, there's no way we can guarantee at compile time that they both have the same underlying concrete type.
In order to solve this problem, we can use a type eraser.
2. Build a type eraser
As Rob says, a type eraser, is the most general solution to the problem of protocols not conforming to themselves. They allow us to wrap a protocol-typed instance in a concrete type that conforms to that protocol, by forwarding the instance requirements to the underlying instance.
So, let's build a type erasing box that forwards P's instance requirements onto an underlying arbitrary instance that conforms to P:
struct AnyP : P {
private var base: P
init(_ base: P) {
self.base = base
}
var bar: Int {
get { return base.bar }
set { base.bar = newValue }
}
func foo(str: String) { base.foo(str: str) }
}
Now we can just talk in terms of AnyP instead of P:
let p = AnyP(S(bar: 5))
takesConcreteP(p)
// example from #1...
let array = [AnyP(S(bar: 1)), AnyP(Q(bar: 2))]
takesConcreteArrayOfP(array)
Now, consider for a moment just why we had to build that box. As we discussed early, Swift needs a concrete type for cases where the protocol has static requirements. Consider if P had a static requirement – we would have needed to implement that in AnyP. But what should it have been implemented as? We're dealing with arbitrary instances that conform to P here – we don't know about how their underlying concrete types implement the static requirements, therefore we cannot meaningfully express this in AnyP.
Therefore, the solution in this case is only really useful in the case of instance protocol requirements. In the general case, we still cannot treat P as a concrete type that conforms to P.
EDIT: Eighteen more months of working w/ Swift, another major release (that provides a new diagnostic), and a comment from #AyBayBay makes me want to rewrite this answer. The new diagnostic is:
"Using 'P' as a concrete type conforming to protocol 'P' is not supported."
That actually makes this whole thing a lot clearer. This extension:
extension Array where Element : P {
doesn't apply when Element == P since P is not considered a concrete conformance of P. (The "put it in a box" solution below is still the most general solution.)
Old Answer:
It's yet another case of metatypes. Swift really wants you to get to a concrete type for most non-trivial things. [P] isn't a concrete type (you can't allocate a block of memory of known size for P). (I don't think that's actually true; you can absolutely create something of size P because it's done via indirection.) I don't think there's any evidence that this is a case of "shouldn't" work. This looks very much like one of their "doesn't work yet" cases. (Unfortunately it's almost impossible to get Apple to confirm the difference between those cases.) The fact that Array<P> can be a variable type (where Array cannot) indicates that they've already done some work in this direction, but Swift metatypes have lots of sharp edges and unimplemented cases. I don't think you're going to get a better "why" answer than that. "Because the compiler doesn't allow it." (Unsatisfying, I know. My whole Swift life…)
The solution is almost always to put things in a box. We build a type-eraser.
protocol P { }
struct S: P { }
struct AnyPArray {
var array: [P]
init(_ array:[P]) { self.array = array }
}
extension AnyPArray {
func test<T>() -> [T] {
return []
}
}
let arr = AnyPArray([S()])
let result: [S] = arr.test()
When Swift allows you to do this directly (which I do expect eventually), it will likely just be by creating this box for you automatically. Recursive enums had exactly this history. You had to box them and it was incredibly annoying and restricting, and then finally the compiler added indirect to do the same thing more automatically.
If you extend CollectionType protocol instead of Array and constraint by protocol as a concrete type, you can rewrite the previous code as follows.
protocol P { }
struct S: P { }
let arr:[P] = [ S() ]
extension CollectionType where Generator.Element == P {
func test<T>() -> [T] {
return []
}
}
let result : [S] = arr.test()

How can I use the __builtin_expect in Swift?

How can I use the __builtin_expect(::) in Swift?
Does Swift still support this method?
I found the following definition in Dispatch, but I can't call it.
public func __builtin_expect(_: Int, _: Int) -> Int
Builtin.swift in the Swift standard library defines
/// Optimizer hint that `x` is expected to be `true`.
#_transparent
#_semantics("fastpath")
public func _fastPath(_ x: Bool) -> Bool {
return _branchHint(x, expected: true)
}
/// Optimizer hint that `x` is expected to be `false`.
#_transparent
#_semantics("slowpath")
public func _slowPath(_ x: Bool) -> Bool {
return _branchHint(x, expected: false)
}
and these are documented in the Standard Library Programmers Manual: Builtins:
_fastPath returns its argument, wrapped in a Builtin.expect. This informs the optimizer that the vast majority of the time, the branch
will be taken (i.e. the then branch is “hot”).
[...]
_slowPath is the same as _fastPath, just with the branches swapped. Both are just wrappers around _branchHint, which is otherwise never
called directly.
[...]
NOTE: these are due for a rename and possibly a redesign. They
conflate multiple notions that don’t match the average standard
library programmer’s intuition.
See also Does guard hint the optimiser that this is the unlikely branch in the Swift forum.
However, these functions are not publicly exposed, and the leading underscore indicates that they are meant for library internal use only. It is currently possible to use them in your code
if _fastPath(conditionExpectedToBeTrue) {
// ...
}
if _slowPath(conditionExpectedToBeFalse) {
// ...
}
but that is not guaranteed to work or to compile in the future.

When to use generics in Swift [duplicate]

This question already has answers here:
What is the in-practice difference between generic and protocol-typed function parameters?
(2 answers)
Closed 5 years ago.
I studied about generics but i still have no understanding, why to use them, when we can use protocols instead?
For example, examine following function:
public static func delete<T>(entity: T, auth: Auth) -> Observable<Void> where T: MSRequestEntity, T: DictConvertable {
// function do something
}
Ok, we have generic entity T, that is conform to MSRequestEntity and DictConvertable.
But we can simply rewrite this like that:
public static func delete(entity: MSRequestEntity & DictConvertable, auth: Auth) -> Observable<Void> {
// function do something
}
So, my question is, in what case should i use generics? All of situations i have imaging could easily be handled with protocols.
In the case you have provided you are correct. It doesn't necessarily add anything by making it generic.
But take the example where you have some protocol MyProtocol and you want to create a function that takes two of these and returns a third. But the function only works if first and second are of the same type...
func combine(first: MyProtocol, second: MyProtocol) -> MyProtocol {
// do some combining here.
}
Now it's less well defined because first and second can be of different types here. The only thing that is required is that they conform to the protocol. And what is the return type?
Now consider...
function combine<T: MyProtocol>(first: T, second: T) -> T {
// do some combining here
}
Now the function is generic but what that adds is that still first and second must conform to the protocol. But now they must be of the same type. And the function will return another item of the same type as first and second.
In this case you definitely benefit from using generics rather than just the protocol.

Check if optional protocol method is implemented in Swift?

I have a swift protocol:
#objc protocol SomeDelegate {
optional func myFunction()
}
I one of my classes I did:
weak var delegate: SomeDelegate?
Now I want to check if the delegate has myFunction implemented.
In objective-c I can do:
if ([delegate respondsToSelector:#selector(myFunction)]) {
...
}
But this is not available in Swift.
Edit: This is different from: What is the swift equivalent of respondsToSelector? I focus on class protocols not on classes.
How do I check if my delegate has an optional method implemented?
Per The Swift Programming Language:
You check for an implementation of an optional requirement by writing
a question mark after the name of the requirement when it is called,
such as someOptionalMethod?(someArgument). Optional property
requirements, and optional method requirements that return a value,
will always return an optional value of the appropriate type when they
are accessed or called, to reflect the fact that the optional
requirement may not have been implemented.
So the intention is not that you check whether the method is implemented, it's that you attempt to call it regardless and get an optional back.
You can do
if delegate?.myFunction != nil {
}
I've found it successful to add an extension to the protocol that defines basic default implementation and then any class implementing the protocol need only override the functions of interest.
public protocol PresenterDelegate : class {
func presenterDidRefreshCompleteLayout(presenter: Presenter)
func presenterShouldDoSomething(presenter: Presenter) -> Bool
}
then extend
extension PresenterDelegate {
public func presenterDidRefreshCompleteLayout(presenter: Presenter) {}
public func presenterShouldDoSomething(presenter: Presenter) -> Bool {
return true
}
}
Now any class needing to conform to the PresenterDelegate protocol has all functions already implemented, so it's now optional to override it's functionality.
I normally implement it like this:
self.delegate?.myFunction?()
if the delegate methods returns a value:
var result = defaultValue
if let delegateResult = self.delegate?.myFunction?() else {
result = delegateResult
}
//do something with result
Declaration
#objc public protocol nameOfDelegate: class {
#objc optional func delegateMethod(_ varA: int, didSelect item: Item)
}
Implimetation
if let delegate = nameOfDelegate {
delegate.delegateMethod?(1, didDeselect: node)
}
I know this question is 5 years old, but I would like to share what I found. My solution works as of 2021, XCode 11+, Swift 5.
Say I wanted to figure out whether the function sign follows the GIDSignInDelegate protocol and also know what all the optional functions for GIDSignInDelegate are.
I have to look at the source code of the GIDSignIn module, and this is how.
Click on jump to definition on the main module that is imported. It will lead to a file like this:
Copy the entire line, import GoogleSignIn.GIDSignIn and paste it in the ViewController or whatever .swift file (doesn't really matter).
Within the swift file, right click on the GIDSignIn part of the import line GoogleSignIn.GIDSignIn and jump to definition. This will lead you to the actual module with all the available functions (the functions not marked optional may be stubs, which are required functions in the delegate protocol):
From this file, I can see that there is a sign function that is a stub of GIDSignInDelegate and an optional sign function that is implemented as a method overload.
I used this for GIDSignInDelegate, but you can use the same method to figure out whether any function follows any delegate protocol.

Resources