Swift Comparable Protocol great than method - swift

class Test {
var count: Int;
init(count: Int) {
self.count = count;
}
}
extension Test: Comparable {
static func <(lhs: Test, rhs: Test) -> Bool {
return lhs.count > rhs.count
}
}
When I write this extension everything work okay but when i change < to > compiler error return
Type 'Test' does not conform to protocol 'Equatable'
Comparable extension required write < this function
What is this reason?

If you look at the docs for Comparable, you can see that it inherits from Equatable.
Equatable requires == to be implemented:
static func ==(lhs: Test, rhs: Test) -> Bool {
return lhs.count == rhs.count
}
I should also mention that count does not have an initial value. So you need to add an initializer for Test or a initial value to count.
EDIT:
If you look at the docs for Comparable, you'll find this bit:
Types with Comparable conformance implement the less-than operator (<)
and the equal-to operator (==). These two operations impose a strict
total order on the values of a type, in which exactly one of the
following must be true for any two values a and b:
a == b
a < b
b < a
So you must implement < and == but > is unnecessary. That's why it doesn't work when you only have >.

Related

Contradictory protocol conformances

Can anybody explain please, what is going on here:
struct Test {
var value: Int
}
// -----------------------------------
protocol Test1: Equatable {
var value: Int { get set }
}
extension Test1 {
static func == (lhs: Self, rhs: Self) -> Bool {
lhs.value == rhs.value + 1
}
}
// -----------------------------------
protocol Test2: Equatable {
var value: Int { get set }
}
extension Test2 {
static func == (lhs: Self, rhs: Self) -> Bool {
lhs.value == rhs.value + 2
}
}
// -----------------------------------
extension Test: Test1 {}
extension Test: Test2 {}
let a = Test(value: 5)
let b = Test(value: 5)
print(a == b) // true, which is unexpected
If conforms only to Test1 or only to Test2 it works as expected.
Conforming to Test1 and Test2. At first I thought that the order will matter. But looks like it just cancels each other! Without any warnings. Which is very counterintuitive.
Note: Test conforms to Equatable not because of the two extensions you provided, but because of the auto-generated Equatable implementation. As you said, if there were only those two extensions, it would be ambiguous which == is the Equatable implementation.
Neither of the == in the Test1 or Test2 protocol extensions are called. Instead, the auto-generated Equatable implementation is called. As you may recall, a == operator is auto-generated for types whose properties are all Equatable, and is declared to conform to Equatable itself.
This is because members declared in extensions use static binding, so when there are multiple versions of the same member available, the version declared in the extension will only be chosen if the compile time type is the extension's type. For example:
protocol P { }
class C : P { func f() { print("C") } }
extension P { func f() { print("P") } }
C().f() // C
(C() as P).f() // P
In a == b, both a and b are Test, so none of the extension operators gets chosen. However, since Test1 and Test2 both use Self, you can only use them as generic constraints, and can't cast to them either. Therefore, I don't think you will be able to call the == declared in the extensions at all.
Anyway, if you want to see an error message saying that there are duplicate == operators available:
struct Test {
var value: Int
var x: Any? // now there is no auto-generated Equatable implementation!
}
error: type 'Test' does not conform to protocol 'Equatable' extension
Test: Test1 {} ^
note: candidate exactly matches
static func == (lhs: Self, rhs: Self) -> Bool {
^
note: candidate exactly matches
static func == (lhs: Self, rhs: Self) -> Bool {
^
If you remove one of the extensions, then Test conforms to Equatable because of the extension, as there is no more ambiguity. Therefore, the auto-generated implementation isn't auto-generated anymore, and there is only one == to choose from - the one declared in the extension.

Why does conforming to Strideable change how multiplication is evaluated?

I created an infinite loop by conforming a Swift struct to the Strideable protocol. I reduced the problem to the following case.
struct T: Strideable {
func advanced(by n: Int) -> T { return T() }
func distance(to other: T) -> Int {
print("Hello")
return self == T() ? 0 : 1
}
}
print(T() == T())
Running this code in a playground results in an unending stream of "Hello"s. If struct T: Strideable is replaced with struct T: Equatable, "true" prints as I would expect.
I suspect that there is a default implementation of Equatable for types conforming to Strideable which is distinct from the auto-synthesized implementation for structs whose members are all equatable. The struct in my project has many members, so I would not like to manually implement a member-wise comparison.
Why does conforming to Strideable change how equality is implemented, and is there a way to recover the expected behavior without manually implementing Equatable?
It's from apple documents:
Important
The Strideable protocol provides default implementations for the equal-to (==) and less-than (<) operators that depend on the Stride type’s implementations. If a type conforming to Strideable is its own Stride type, it must provide concrete implementations of the two operators to avoid infinite recursion.
So either you provide the "==" and "<" implementation like this :
struct Temp: Strideable {
var error = 1
func advanced(by n: Int) -> Temp { return Temp() }
func distance(to other: Temp) -> Int {
print("hello")
return self == other ? 0 : 1
}
static func == (left : T, right: T){
print("great")
}
}
or use some value to manager the stride property. like var location : Int = 0

understanding protocol extensions in swift

I am trying to implement a basic protocol extension like so:
protocol Value {
func get() -> Float
mutating func set(to:Float)
}
extension Value {
static func min(of a:Value, and b:Value) -> Float {
if a < b { //Expression type 'Bool' is ambiguous without more context
return a.get()
}else{
return b.get()
}
}
static func < (a:Value, b:Value) -> Bool {
return a.get() < b.get()
}
}
At the if clause the compiler says:Expression type 'Bool' is ambiguous without more context. Why doesn't this work?
As touched on in this Q&A, there's a difference between operator overloads implemented as static members and operator overloads implemented as top-level functions. static members take an additional (implicit) self parameter, which the compiler needs to be able to infer.
So how is the value of self inferred? Well, it has to be done from either the operands or return type of the overload. For a protocol extension, this means one of those types needs to be Self. Bear in mind that you can't directly call an operator on a type (i.e you can't say (Self.<)(a, b)).
Consider the following example:
protocol Value {
func get() -> Float
}
extension Value {
static func < (a: Value, b: Value) -> Bool {
print("Being called on conforming type: \(self)")
return a.get() < b.get()
}
}
struct S : Value {
func get() -> Float { return 0 }
}
let value: Value = S()
print(value < value) // Ambiguous reference to member '<'
What's the value of self in the call to <? The compiler can't infer it (really I think it should error directly on the overload as it's un-callable). Bear in mind that self at static scope in a protocol extension must be a concrete conforming type; it can't just be Value.self (as static methods in protocol extensions are only available to call on concrete conforming types, not on the protocol type itself).
We can fix both the above example, and your example by defining the overload as a top-level function instead:
protocol Value {
func get() -> Float
}
func < (a: Value, b: Value) -> Bool {
return a.get() < b.get()
}
struct S : Value {
func get() -> Float { return 0 }
}
let value: Value = S()
print(value < value) // false
This works because now we don't need to infer a value for self.
We could have also given the compiler a way to infer the value of self, by making one or both of the parameters take Self:
protocol Value {
func get() -> Float
}
extension Value {
static func < (a: Self, b: Self) -> Bool {
print("Being called on conforming type: \(self)")
return a.get() < b.get()
}
}
struct S : Value {
func get() -> Float { return 0 }
}
let s = S()
print(s < s)
// Being called on conforming type: S
// false
The compiler can now infer self from the static type of operands. However, as said above, this needs to be a concrete type, so you can't deal with heterogenous Value operands (you could work with one operand taking a Value; but not both as then there'd be no way to infer self).
Although note that if you're providing a default implementation of <, you should probably also provide a default implementation of ==. Unless you have a good reason not to, I would also advise you make these overloads take homogenous concrete operands (i.e parameters of type Self), such that they can provide a default implementation for Comparable.
Also rather than having get() and set(to:) requirements, I would advise a settable property requirement instead:
// Not deriving from Comparable could be useful if you need to use the protocol as
// an actual type; however note that you won't be able to access Comparable stuff,
// such as the auto >, <=, >= overloads from a protocol extension.
protocol Value {
var floatValue: Double { get set }
}
extension Value {
static func == (lhs: Self, rhs: Self) -> Bool {
return lhs.floatValue == rhs.floatValue
}
static func < (lhs: Self, rhs: Self) -> Bool {
return lhs.floatValue < rhs.floatValue
}
}
Finally, if Comparable conformance is essential for conformance to Value, you should make it derive from Comparable:
protocol Value : Comparable {
var floatValue: Double { get set }
}
You shouldn't need a min(of:and:) function in either case, as when the conforming type conforms to Comparable, it can use the top-level min(_:_:) function.
You can't write
if a < b {
because a and b have type Value which is NOT Comparable.
However you can compare the float value associated to a and b
if a.get() < b.get() {
If you want to be able to make types that can use operators such as >, <, ==, etc., they have to conform to the Comparable protocol:
protocol Value: Comparable {
func get() -> Float
mutating func set(to: Float)
}
This comes with more restrictions though. You will have to change all the Value types in the protocol extension to Self:
extension Value {
static func min(of a: Self, and b: Self) -> Float {
if a < b { //Expression type 'Bool' is ambiguous without more context
return a.get()
}else{
return b.get()
}
}
static func < (a: Self, b: Self) -> Bool {
return a.get() < b.get()
}
}
The Self types get replaced with the type that implements the protocol. So if I implemented Value on a type Container, the methods signatures would look like this:
class Container: Value {
static func min(of a: Container, and b: Container) -> Float
static func < (a: Container, b: Container) -> Bool
}
As a side note, if you want Value to conform to Comparable, you might want to also add the == operator to the Value extension:
static func <(lhs: Self, rhs: Self) -> Bool {
return lhs.get() < rhs.get()
}

Does Swift support automatic generation of operators?

I'm looking to avoid writing unnecessary code. If I define == and < for a type, is it possible to automatically obtain <= (< or ==), > (not < and not ==), or >= (not <)? I would think Swift would provide these operators for free, but that doesn't seem to be the case.
If you make your type conform to Equatable, it will provide a default implementation of != based on your ==.
If you make your type conform to Comparable, it will provide default implementations of >, <=, and >= based on your <.
Note that Comparable extends Equatable, so you must also provide == to conform to Comparable.
Yes. That's exactly how Comparable protocol works. You only have to define 2 operators: < and ==. Swift will figure out the rest.
struct MyStruct : Comparable {
var value: Int
}
func == (lhs: MyStruct, rhs: MyStruct) -> Bool {
return lhs.value == rhs.value
}
func < (lhs: MyStruct, rhs: MyStruct) -> Bool {
return lhs.value < rhs.value
}
let a = MyStruct(value: 1)
let b = MyStruct(value: 42)
print(b > a) // We never defined `>` operator
Yes.
Implement == from Equatable and < from Comparable, and the rest of the operators will use the default implementations as you expect.
To add Comparable conformance to your custom types, define the < and == operators as static methods of your types. The == operator is a requirement of the Equatable protocol, which Comparable extends—see that protocol’s documentation for more information about equality in Swift. Because default implementations of the remainder of the relational operators are provided by the standard library, you’ll be able to use !=, >, <=, and >= with instances of your type without any further code.

Swift enum inequality

I'm used to being able to treat enums as numeric values, and thus employ operators like >, <=, etc. For most enum uses this is probably not that necessary, but one case where it is is states:
#objc public enum MyState: Int {
case Loading = 0
case Loaded
case Resolved
case Processed
}
I want to be able to take an instance variable and check this:
var state: MyState = ...
if state > .Loaded {
...
}
But Swift is complaining that it doesn't know what to do. I've declared the enum as being an Int. Is my only option to compare the rawValues? I was hoping to avoid that as it's just going to be really ugly, and Swift gets sooo close on its own.
Wouldn't something along these lines suffice?
enum State: Int, Comparable {
case Loading
case Loaded
case Resolved
case Processed
}
func < (lhs: State, rhs: State) -> Bool {
return lhs.rawValue < rhs.rawValue
}
let state = State.Resolved
state > .Loaded // true
Note that only < implementation is needed since enums are already equatable...
And in general, comparability of enums is independent of their raw values, if any – for example:
enum State: Comparable {
case Good
case Bad
}
func < (lhs: State, rhs: State) -> Bool {
return lhs == .Bad && rhs == .Good
}
let state = State.Good
state > .Bad // true
On the second thought, Swift does allow us to extend RawRepresentable protocol with exact effect that #devios is looking for:
/// Extends all `RawRepresentable` enums with `Comparable` raw values,
/// such as `enum E : Int` or `enum E : String`...
///
public func < <E: RawRepresentable where E.RawValue : Comparable> (lhs: E, rhs: E) -> Bool {
return lhs.rawValue < rhs.rawValue
}
With this tucked in somewhere in your library of extensions, all you need to do is to explicitly opt in by declaring your type as Comparable:
enum N: Int, Comparable {
case Zero, One, Two, Three
}
enum S: String, Comparable {
case A, B, C, D
}
let n: N = .Two
n > .One // true
let ss: [S] = [.B, .A, .D, .C].sort() // [A, B, C, D]
This still allows you to provide a concrete implementation if the generic behaviour is not a perfect fit for a particular type:
func < (lhs: S, rhs: S) -> Bool {
return rhs.hashValue < lhs.hashValue // inverting the ordering
}
let ss: [S] = [.B, .A, .D, .C].sort() // [D, C, B, A]
I'm not entirely sure what you want, but there are two ways of going about this, one of which you already mentioned, which is using raw values.
The other way is using the Comparable protocol. You can have the enum conform to the protocol and implement the four methods (< is required, >, <= and >= are optional):
enum MyState: Int, Comparable {
...
}
func < (lhs: MyState, rhs: MyState) -> Bool {
return lhs.rawValue < rhs.rawValue
}
// add other three protocol methods if needed
Then you can compare them like integers:
if someState > .Loading {
...
}
Just implement the different logical operators for your enum. No need to use Equatable or Comparable
enum State: Int
{
case Loading
case Loaded
case Resolved
case Processed
}
func < (lhs: State, rhs: State) -> Bool
{
return lhs.rawValue < rhs.rawValue
}
func > (lhs: State, rhs: State) -> Bool
{
return lhs.rawValue > rhs.rawValue
}