Nested Swift class can't conform to Comparable - swift

I am trying to implement a simple array based heap but running into issues with the nested Node class. I would like my nodes to be comparable, however, the compiler is complaining that the node class doesn't conform.
import Foundation
class Heap<E:Comparable> {
var heap = Array<Node<E>>()
init() { }
class Node<E:Comparable >:Comparable {
var key:E!
init(key:E) { self.key = key }
}
}
func < <E> (lhs:Heap<E>.Node<E>, rhs:Heap<E>.Node<E>) -> Bool {
return lhs.key < rhs.key }
func == <E> (lhs:Heap<E>.Node<E>, rhs:Heap<E>.Node<E>) -> Bool {
return lhs.key == rhs.key }

It complains because of the Node class doesn't conform the Comparable protocol.
protocol Comparable : _Comparable, Equatable {
func <=(lhs: Self, rhs: Self) -> Bool
func >=(lhs: Self, rhs: Self) -> Bool
func >(lhs: Self, rhs: Self) -> Bool
}
And one more thing, if you want to use the self.key to compare, then the type should conform Comparable protocol as well. Here's the sample:
class Node<E where E:Comparable>:Comparable {
var key:E!
init(key:E) { self.key = key }
}
func ==<E>(lhs: Node<E>, rhs: Node<E>) -> Bool {
return lhs.key == rhs.key
}
func <<E>(lhs: Node<E>, rhs: Node<E>) -> Bool {
return lhs.key < rhs.key
}

Related

Overload Equality Operator (==) to compare String and Int

I am experiencing with protocols and challenged myself to write a code snippet that overloads the == operator so that it returns true when I compare a random String with value "42" with a Int of value 42. Please don't question the usefulness by simply returning 42 on a String, the main point is getting the Equality Operator to run on the two different types.
Here is what I tried:
Version 1
import Foundation
protocol IntTransformable: Equatable {
func toInt() -> Int
}
extension String: IntTransformable {
func toInt() -> Int {
return 42
}
}
extension Int: IntTransformable {
func toInt() -> Int {
return self
}
}
extension IntTransformable {
static func == (lhs: Self, rhs: Self) -> Bool {
return lhs.toInt() == rhs.toInt()
}
}
// throws: Ambiguous reference to operator function '=='
if "42" == 42 {
print("equal")
} else {
print("unequal")
}
Version 2
import Foundation
protocol IntTransformable: Equatable {
func toInt() -> Int
}
extension String: IntTransformable {
func toInt() -> Int {
return 42
}
}
extension Int: IntTransformable {
func toInt() -> Int {
return self
}
}
extension IntTransformable {
// throws: Protocol 'IntTransformable' can only be used as a generic constraint because it has Self or associated type requirements
static func == (lhs: IntTransformable, rhs: IntTransformable) -> Bool {
return lhs.toInt() == rhs.toInt()
}
}
// throws: Ambiguous reference to operator function '=='
if "42" == 42 {
print("equal")
} else {
print("unequal")
}
You should use these two functions:
func ==(lhs: String, rhs: #autoclosure ()->Int) -> Bool {
guard let stringIntValue = Int(lhs) else { return false }
return stringIntValue == rhs()
}
func ==(lhs: Int, rhs: String) -> Bool {
guard let stringIntValue = Int(rhs) else { return false }
return lhs == stringIntValue
}
But if you really want to involve Protocols here, you should do this like:
extension IntTransformable {
static func ==<T: IntTransformable>(lhs: Self, rhs: T) -> Bool {
return lhs.toInt() == rhs.toInt()
}
}
Usage:
print( 42 == "42" )
print( "42" == 42 )
You're way overthinking this. There is no reason to use protocols here, and you really can't do it because protocols are not really types. Just write your operator(s) at top level:
func == (lhs: Int, rhs: String) -> Bool {
return lhs == Int(rhs)
}
func == (lhs: String, rhs: Int) -> Bool {
return Int(lhs) == rhs
}
Testing:
print(5 == "5") // true
create a string extension, like
public string ToInt(this int value)
{
// some conversion code
return ConvertedStringValue;
}
or you can use a uint.TryParse(string value, out uint output)
this statement will return true if conversion is successful.

operator '<' declared in type 'XXX' must be 'static'

I have the following implementation and also added Comparable extension as follows. But I am getting the following error. I wonder how I could able to fix it.
error: operator '<' declared in type 'Item' must be 'static'
func < (lhs: Item, rhs: Item) -> Bool {
^
static
class Item
{
var timeStamp : Date
var value : Int
init(_ value: Int)
{
self.value = value
self.timeStamp = Date()
}
}
extension Item: Comparable
{
func < (lhs: Item, rhs: Item) -> Bool {
return lhs.timeStamp < rhs.timeStamp
}
func == (lhs: Item, rhs: Item) -> Bool {
return lhs.timeStamp == rhs.timeStamp
}
}
The Comparable protocol requires that the < operator implementation is static. It is documented here. You could fix your code by adding the static keyword like so:
static func < (lhs: Item, rhs: Item) -> Bool {
return lhs.timeStamp < rhs.timeStamp
}

Extend Int enum with comparison operators

Very often you have Int enums like this:
enum Difficulty: Int {
case Easy = 0
case Normal
case Hard
}
Difficulty values have a certain meaning and we may want to introduce order for them. For example, somewhere we need to compare:
let isBonusAvailable = level.difficulty.rawVAlue <= Difficulty.Hard.rawValue
I want to make this code a little bit shorter:
let isBonusAvailable = level.difficulty <= .Hard
It can be easily achieved if I add <= directly to the Difficulty. But I wanted to solve this problem in general, so I tried this super-tricky way:
protocol RawRepresentableByInt {
var rawValue: Int { get }
}
extension RawRepresentableByInt {
static func <(lhs: RawRepresentableByInt, rhs: RawRepresentableByInt) -> Bool {
return lhs.rawValue < rhs.rawValue
}
static func >(lhs: RawRepresentableByInt, rhs: RawRepresentableByInt) -> Bool {
return lhs.rawValue > rhs.rawValue
}
static func <=(lhs: RawRepresentableByInt, rhs: RawRepresentableByInt) -> Bool {
return lhs.rawValue <= rhs.rawValue
}
static func >=(lhs: RawRepresentableByInt, rhs: RawRepresentableByInt) -> Bool {
return lhs.rawValue >= rhs.rawValue
}
}
// Error: Extension of protocol 'RawRepresentable' cannot have an inheritance clause
extension RawRepresentable: RawRepresentableByInt where RawValue == Int {
}
It produces a compiler error:
Error: Extension of protocol 'RawRepresentable' cannot have an inheritance clause
I think there is nothing unimplementable in comparison of Int enum in term of logic. Please, help me to trick the Swift compiler. Anyone, who also need such extensions may participate.
It was easier than I thought. So, basically you can use Self instead of creating an additional protocol.
enum Difficulty: Int {
case Easy = 0
case Normal
case Hard
}
extension RawRepresentable where RawValue: Comparable {
static func <(lhs: Self, rhs: Self) -> Bool {
return lhs.rawValue < rhs.rawValue
}
static func >(lhs: Self, rhs: Self) -> Bool {
return lhs.rawValue > rhs.rawValue
}
static func <=(lhs: Self, rhs: Self) -> Bool {
return lhs.rawValue <= rhs.rawValue
}
static func >=(lhs: Self, rhs: Self) -> Bool {
return lhs.rawValue >= rhs.rawValue
}
}
let easy = Difficulty.Easy
print(easy > .Hard) // false

generics struct implementing protocol with associated type

I am a bit stuck trying to define a container for my ui elements.
As I wanted something that encapsulates a non unique label, a value that can be any comparable object and a concept of being the preferred option I came up with the following protocol:
protocol OptionProtocol:Comparable {
associatedtype Key:Comparable
associatedtype Value:Comparable
var key:Key { get set }
var value:Value { get set }
var main:Bool { get set }
static func <(lhs: Self, rhs: Self) -> Bool
static func ==(lhs: Self, rhs: Self) -> Bool
}
extension OptionProtocol {
static func <(lhs: Self, rhs: Self) -> Bool {
let equalKeys = lhs.key == rhs.key
return equalKeys ? lhs.value < rhs.value : lhs.key < rhs.key
}
static func ==(lhs: Self, rhs: Self) -> Bool{
return (lhs.value == rhs.value) && (lhs.key == rhs.key)
}
}
Now I want to implement the protocol in a generic struct and I cant figure out how. What I want to do is
struct Option<Key, Value>: OptionProtocol {
var key:Key
var value:Value
var main:Bool
}
But the compiler complains that Type 'Option<Key, Value>' does not conform to protocol 'OptionProtocol'
Any pointer would be helpful
The answer was pretty simple. I needed to constraint Key and Value in the struct.
The following struct compiles as expected
struct Option<Key, Value>:OptionProtocol where Key:Comparable, Value:Comparable {
var key:Key
var value:Value
var main:Bool
}

Using a generic protocol type inside of another generic protocol type

I'm trying to figure out how to use a protocol that has a Self or associated type requirement inside of another protocol. Consider the following example:
protocol SortBy {
static var values: [Self] { get }
var title: String { get }
}
protocol Filter {
var sortBy: SortBy { get set }
init(_ filter: Self)
static func == (lhs: Self, rhs: Self) -> Bool
static func != (lhs: Self, rhs: Self) -> Bool
}
I know that since SortBy contains a reference to Self, I can only use it as a generic constraint. What I don't know is if there is any Swift magic I can do to allow what I'm trying to achieve?
Ultimately I want to use the protocols for an example as follows:
enum Sort: SortBy {
case sort1
case sort2
static var values: [Sort] {
return [
.sort1,
.sort2
]
}
var title: String {
switch self {
case .sort1:
return "Sort 1"
case .sort2:
return "Sort 2"
}
}
}
struct FilterExample: Filter {
var sortBy: SortBy
init(_ filter: FilterExample) {
...
}
static func == (lhs: FilterExample, rhs: FilterExample) -> Bool {
...
}
static func != (lhs: FilterExample, rhs: FilterExample) -> Bool {
...
}
}
And in case it matters, I'm using Swift 3.
Thanks for the help in advance.
associatedTypes and generics should be able to get what you want. That said, you should take a look at the Equatable and Comparable protocols. It looks like you're trying to do something related and adoption of those may help you. E.g. adoption of Equatable means you only have to implement == and you get != for free.
protocol SortBy {
static var values: [Self] { get }
var title: String { get }
}
protocol Filter {
associatedtype SortByType: SortBy
var sortBy: SortByType { get set }
init(_ filter: Self)
static func == (lhs: Self, rhs: Self) -> Bool
static func != (lhs: Self, rhs: Self) -> Bool
}
struct FilterExample<T: SortBy>: Filter {
var sortBy: T
init(_ filter: FilterExample<T>) {
self.sortBy = filter.sortBy
}
static func == (lhs: FilterExample, rhs: FilterExample) -> Bool {
return true
}
static func != (lhs: FilterExample, rhs: FilterExample) -> Bool {
return true
}
}