What is the Swift equivalent for Java's Comparator Interface - swift

I have the following Java code below that I am trying to convert into Swift accordingly. Can somebody help me on this issue. Thanks
public class CarsSortById implements Comparator<Cars>{
#Override
public int compare(Cars car1, Cars car2) {
return (car1.getCarId() < car2.getCarId()) ? -1:
(car1.getCarId() > car2.getCarId() ) ? 1:0 ;
}
}

Swift equivalent of Comparable<T>
Is the Comparable protocol. It requires that your type define an < operator. Since it derives from the Equatable protocol, you need to define the == operator, as well:
class Car {
let id: Int
// other fields
}
extension Car: Equatable {
static func == (lhs: Car, rhs: Car) -> Bool {
return lhs.id == rhs.id
}
}
extension Car: Comparable {
static func < (lhs: Car, rhs: Car) -> Bool {
return lhs.id < rhs.id
}
}
Swift equivalent of Comparator<T>
In Java, Comparator is an interface that lets you define sorting functions in addition to the one a type defines for itself via the Comparable Interface. Interfaces like this are necessary because Java didn't support lambdas prior to 1.8. And after Java 1.8, interfaces form the basis of lambdas.
Swift doesn't have an equivalent interface (called a protocol, in Swift). There's no need, since Swift can let you just define closures without the #functionalinterface cruft of Java.
Usually, Java Comparators are only used once. In this case, just call sort with a custom sorting closure:
let carsSortedByID = cars.sorted { $0.id < $1.id }
If you need to resume the sorting closure, you could assign it to a variable. Naturally, it would make sense to store these as static variable in an extension on the type that they sort.:
extension Car {
static let idSorter: (Car, Car) -> Bool = { $0.id < $1.id }
}
let carsSortedByID = cars.sorted(by: Car.idSorter)

As already mentioned in other answers and in the comment, in swift there is nothing for that. It is just closure.
But here is how you define Comparable
class Car {
var id = -1
}
extension Car: Comparable {
static func == (lhs: Car, rhs: Car) -> Bool {
return lhs.id == rhs.id
}
static func < (lhs: Car, rhs: Car) -> Bool {
return lhs.id < rhs.id
}
}

If you're looking to specifically replicate the Java Comparator behavior where it returns a negative number for "less than", zero for "equal", or a positive number for "greater than", you could write a function that returns a ComparisonResult.
ComparisonResult is an enum with the cases .orderedAscending, .orderedSame, and .orderedDescending.
You could rewrite your function in Swift:
extension Car {
func compare(with other: Car) -> ComparisonResult {
return self.carId < other.carId
? .orderedDescending
: self.carId > other.carId ? .orderedAscending : .orderedSame
}
}

Related

class AnyComparable inherits from class AnyEquatable

public class AnyEquatable: Equatable {
public let value: Any
private let equals: (Any) -> Bool
public init<E: Equatable>(_ value: E) {
self.value = value
self.equals = { $0 as? E == value }
}
public static func == (lhs: AnyEquatable, rhs: AnyEquatable) -> Bool {
lhs.equals(rhs.value) || rhs.equals(lhs.value)
}
}
public class AnyComparable: AnyEquatable, Comparable {
private let compares: (Any) -> Bool
public init<C: Comparable>(_ value: C) {
super.init(value)
self.compares = { ($0 as? C).map { $0 < value } ?? false }
}
public static func < (lhs: AnyComparable, rhs: AnyComparable) -> Bool {
lhs.compares(rhs.value) || rhs.compares(lhs.value)
}
}
I've got an error:
Overridden method 'init' has generic signature C where C:
Comparable which is incompatible with base method's generic signature
E where E: Equatable; expected generic signature to be C where C:
Equatable
Why does the compiler think that I'm overriding initializer? I didn't use the word "override". I can't override here because the method 'init' has different signature (which the compiler tells itself). It's not an overriding. I want the subclass to use its own initilizer, and I (obviously) don't want inherit superclass initializer.
So, how can I achieve that? What can be more natural than something comparable inherits from something equatable! Why can't I do that?
Note that your initialiser in the subclass does override the initialiser in the superclass. If you fix the constraint on C as the compiler asks you to, the next thing the compiler will tell you, is that you are missing an override keyword.
This behaviour is quite consistent, so it seems like it is deliberately designed that the generic constraints are not taken into account when determining whether one method overrides another. Here's another example of this:
class A {
func f<T>(t: T) {}
}
class B: A {
func f<C: Equatable>(t: C) {} // error
}
Anyway, one way you can work around this is to just change the argument label:
public init<C: Comparable>(comparable value: C) {
self.compares = { ($0 as? C).map { $0 < value } ?? false }
super.init(value)
}
The downside of this is that the client code gets a bit less concise. You have to do AnyComparable(comparable: something) every time, which is quite long. One solution is to put both AnyEquatable and AnyComparable in the same file, make both initialisers fileprivate. You can then provide factory functions (in the same file) that create these classes. For example:
public extension Equatable {
func toAnyEquatable() -> AnyEquatable {
.init(equatable: self)
}
}
public extension Comparable {
func toAnyComparable() -> AnyComparable {
.init(comparable: self)
}
}
Also note that your implementation of < doesn't make much sense. It should be:
public static func < (lhs: AnyComparable, rhs: AnyComparable) -> Bool {
lhs.compares(rhs.value) || (rhs != lhs && !rhs.compares(lhs.value))
}
and compares should mean "less than",
self.compares = { ($0 as? C).map { value < $0 } ?? false }
to say "lhs < rhs or rhs > lhs".
But even still, there are cases where using this class with completely unrelated types still doesn't make much sense, just FYI:
let a = AnyComparable(comparable: "foo")
let b = AnyComparable(comparable: 1)
print(a < b) // true
print(a > b) // true
print(a <= b) // false
print(a >= b) // false
print(a == b) // false
So please do be careful!

How to check if two structs have the same generic parameter type in Swift?

While checking out this repository https://github.com/Samasaur1/DiceKit I stumbled on following piece of code implementing Comparable/Hashable this way:
public struct DieSide<OutputType: Hashable>: Hashable {
public let value: OutputType
// snip
public static func == (lhs: DieSide, rhs: DieSide) -> Bool { //IMPORTANT NOTE: THIS DOES NOT ACCEPT DieSides WITH DIFFERENT GENERIC ARGUMENTS
guard type(of: lhs.value) == type(of: rhs.value) else {
return false
}
return lhs.value == rhs.value
}
// snip
}
You can find the code here.
I believe this check could be done on the language level using where clause instead of checking the types of the arguments in the code and especially - so the comment won't be necessary anymore.
One approach I tried is this one, but that clearly doesn't work (Neither type in same-type constraint ('error type' or 'error type') refers to a generic parameter or associated type):
public static func == (lhs: DieSide, rhs: DieSide) -> Bool where lhs.value.Type == rhs.value.Type {
return lhs.value == rhs.value
}
I also searched for similar answers but was able to find solutions for languages other than Swift at the moment.
Any help on accessing the generic parameters' types appreciated.
The guard statement in that code is pointless. It is impossible for type(of: lhs.value) == type(of: rhs.value) to be false.
The first of these is just shorthand for the second.
public static func == (lhs: DieSide, rhs: DieSide) -> Bool {
lhs.value == rhs.value
}
public static func == (lhs: DieSide<OutputType>, rhs: DieSide<OutputType>) -> Bool {
lhs.value == rhs.value
}
(You can also use Self instead of DieSide.)

Equatable alternatives for Void in Swift

I'm trying to add conditional Equatable conformance to a type say Box<T>, if T is Equatable. Since Swift.Void is not Equatable, Box<Void> is not Equatable.
struct Box<T> {
//...
}
extension Box: Equatable where T: Equatable {
}
I can define a new type like below as a solution:
public struct Empty: Equatable {
}
And then use Box<Empty> instead of Box<Void> and that would work. But, wondering if there any alternatives to introducing a new type.
Update:
I tried this but it doesn't work
struct Box<T> {
//...
}
extension Box: Equatable where T: Equatable {
static func ==(lhs: Box<T>, rhs: Box<T>) -> Bool {
return true
}
}
extension Box where T == Void {
static func ==(lhs: Box<T>, rhs: Box<T>) -> Bool {
return true
}
}
I get an error during compilation: FooBarBaz does not conform to protocol Equatable
enum FooBarBaz: Equatable {
case success(box: Box<Void>)
// case success(box: Box<Int>) compiles as expected.
}
Please note that I'm using Swift 4.1
I get an error during compilation: FooBarBaz does not conform to protocol Equatable
This half-answer focuses on explaining why the approach you've tried yourself will not (yet) work.
There is a limitation, currently, with conditional conformances, that will limit you from using this particular technique to achieve your goal. Citing SE-0143: Conditional conformances, implemented in Swift 4.1:
Multiple conformances
Swift already bans programs that attempt to make the same type conform
to the same protocol twice, e.g.:
...
This existing ban on multiple conformances is extended to conditional
conformances, including attempts to conform to the same protocol in
two different ways.
...
The section overlapping conformances describes some of the
complexities introduced by multiple conformances, to justify their
exclusion from this proposal. A follow-on proposal could introduce
support for multiple conformances, but should likely also cover
related features such as private conformances that are orthogonal to
conditional conformances.
Which wont allow us to construct multiple conditional conformances as e.g.:
struct Box<T> { }
extension Box: Equatable where T == Void {
static func ==(lhs: Box<T>, rhs: Box<T>) -> Bool {
return true
}
}
// error: redundant conformance of 'Box<T>' to protocol 'Equatable'
extension Box: Equatable where T: Equatable {
static func ==(lhs: Box<T>, rhs: Box<T>) -> Bool {
return true
}
}
On the other hand, if we look at your own example:
struct Box<T> { }
extension Box: Equatable where T: Equatable {
static func ==(lhs: Box<T>, rhs: Box<T>) -> Bool {
return true
}
}
extension Box where T == Void {
static func ==(lhs: Box<T>, rhs: Box<T>) -> Bool {
return true
}
}
// error: type 'Void' does not conform to protocol 'Equatable'
func foo<T: Equatable>(_ _: T) { print(T.self, "is Equatable") }
foo(Box<Void>())
Swift accurately identifies that Box<Void> is not Equatable: the extension Box where T == Void will not mean that Box<Void> conforms to Equatable, as it does not leverage a conditional conformance of Box to Equatable when T is Void (it just provides a == method in case T is Void.
Conditional conformances express the notion that a generic type will
conform to a particular protocol only when its type arguments meet
certain requirements.
As a side note, the following example yields expected results:
struct Box<T> { }
extension Box: Equatable where T == () {
static func ==(lhs: Box<T>, rhs: Box<T>) -> Bool {
return true
}
}
func foo<T: Equatable>(_ _: T) { print(T.self, "is Equatable") }
foo(Box<Void>()) // Box<()> is Equatable
whereas, peculiarly, replacing the conditional conformance of Box to Equatable if T == () with the typedef of (), namely Void, crashes the compiler:
struct Box<T> { }
extension Box: Equatable where T == Void {
static func ==(lhs: Box<T>, rhs: Box<T>) -> Bool {
return true
}
}
func foo<T: Equatable>(_ _: T) { print(T.self, "is Equatable") }
foo(Box<Void>()) // compiler crash
Assertion failed: (isActuallyCanonicalOrNull() && "Forming a CanType
out of a non-canonical type!"), function CanType,
file /Users/buildnode/jenkins/workspace/oss-swift-4.1-package-osx/swift/include/swift/AST/Type.h,
line 393.
...
Edit: apparently is a (now resolved) bug:
SR-7101: Compiler crash when implementing a protocol for an enum using generics

How can two generic linked list in swift can be compared?

I have a generic linked list and I can check if two linked list are equal if each of the node value are same and are in order.
I have a function which divides linked list in two part and later I want to check two list has same value in it's node.
func divideList(atIndex index:Int) -> (first: LLGeneric<T>?,second: LLGeneric<T>?)
I looking it for my use case where I can check palindrome in linked list after dividing and then comparing ( after reversing one list).
Note: my linked list node is generic something like
class LLGenericNode<T> {
var value: T
var next: LLGenericNode?
weak var previous: LLGenericNode?
init(_ value: T) {
self.value = value
}
}
In order to compare values you have to require that T is Equatable:
class LLGenericNode<T: Equatable> {
// ...
}
Then you can implement == by comparing the values first.
If the values are equal, the list tails are compared recursively.
extension LLGenericNode: Equatable {
static func ==(lhs: LLGenericNode<T>, rhs: LLGenericNode<T>) -> Bool {
if lhs.value != rhs.value {
return false
}
switch (lhs.next, rhs.next) {
case (nil, nil):
// Both tails are == nil:
return true
case let (lvalue?, rvalue?):
// Both tails are != nil:
return lvalue == rvalue // Recursive call
default:
// One tails is nil and the other isn't:
return false
}
}
}
One-liner solution: It should be enough to define a generic T: Equatable, making sure on overloading the == operator, you compare the current values and the next nodes.
Note that with lhs.next == rhs.next you'll cover both recursion and nullability in one shot:
class Node <T: Equatable>: Equatable {
static func == (lhs: Node, rhs: Node) -> Bool {
lhs.value == rhs.value && lhs.next == rhs.next
}
}

Extend existing (generic) swift class to be hashable

I have some class that i want to put into a dictionary however that class is does not conform to Hashable i cant use it as a key in a Swift dictionary. Since its a class it can be identified by its location in memory and im happy to use that its identifier, the type itself doesnt fall into the value semantics world anyway.
Therefore i declare an extension to make it so
extension SomeGenericType : Hashable {
public var hashValue: Int {
return unsafeAddressOf(self).hashValue
}
}
This seems ok, however Hashable inherhits from Equatable so i need to implement tha too, my first try:
public func ==(lhs: SomeGenericType, rhs: SomeGenericType) -> Bool {
return unsafeAddressOf(lhs) == unsafeAddressOf(rhs)
}
Errors with
"Reference to generic type 'SomeGenericType' requires arguments in <...>"
...fair enough so lets do that
public func ==<T : SomeGenericType >(lhs: T, rhs: T) -> Bool {
return unsafeAddressOf(lhs) == unsafeAddressOf(rhs)
}
Now it says
"Reference to generic type 'SomeGenericType' requires arguments in <...>"
Hmm so i can make this work for all SomeGenericType's regardless of what type it gets. Maybe we can just put AnyObject in there?
public func ==<T : SomeGenericType<AnyObject>>(lhs: T, rhs: T) -> Bool {
return unsafeAddressOf(lhs) == unsafeAddressOf(rhs)
}
Ok now == is happy but apparantly im not implementing Hashable properly as there is now a error on my hashable extension saying:
"Type 'SomeGenericType<T>' does not conform to protocol 'Equatable'"
Ive tried fiddling with a constrained Extension on SomeGenericType but i cant seem to make a constrained extension of a type adopt another protocol, the language grammar doesnt seem to allow it, so Im in a bit of pickle here
Edit, for reference SomeGenericType is defined as follows:
class SomeGenericType<T> {
}
The correct syntax is
public func ==<T>(lhs: SomeGenericType<T>, rhs: SomeGenericType<T>) -> Bool {
return unsafeAddressOf(lhs) == unsafeAddressOf(rhs)
}
The operands need to be instances of SomeGenericType for the
same type placeholder T.
For Swift 3, use ObjectIdentifier instead of unsafeAddressOf.
This is an older question but I recently run into a similar problem, except I had a struct.
You might want to implement 4 different infix operator functions:
// #1
public func ==<T>(lhs: SomeGenericType<T>, rhs: SomeGenericType<T>) -> Bool {
return lhs === rhs // it's a class right - check the reference
}
// #2
public func !=<T>(lhs: SomeGenericType<T>, rhs: SomeGenericType<T>) -> Bool {
return !(lhs === rhs)
}
// #3
public func ==<T, U>(lhs: SomeGenericType<T>, rhs: SomeGenericType<U>) -> Bool {
return lhs.hashValue == rhs.hashValue
}
// #4
public func !=<T, U>(lhs: SomeGenericType<T>, rhs: SomeGenericType<U>) -> Bool {
return lhs.hashValue != rhs.hashValue
}
Problem solved? The program should use these and not the generic functions from the stdlib.
You could also check everything by it's hashValue. ;)