Ternary operator in Swift Error - swift

Why does this code gives error(Swift 2.2) :
Expected Expresion
at return line
func == (lhs: Employee, rhs: Employee) -> Int {
return (lhs.empName == rhs.empName && lhs.empCode == rhs.empCode)?1:0
}

There's no need to use the ternary operator here — x ? true : false is exactly the same as x. I'd write:
func ==(lhs: Employee, rhs: Employee) -> Bool {
return lhs.empName == rhs.empName && lhs.empCode == rhs.empCode
}

Silly. There has to be a space between the BOOL being checked upon and the ?
So flag?expressionA:expressionB won't work.
Instead flag ?expressionA:expressionB will work.
Maybe compiler assumes flag? as optional chaining.
This works
func == (lhs: Employee, rhs: Employee) -> Int {
return (lhs.empName == rhs.empName && lhs.empCode == rhs.empCode) ?1:0
}

Related

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.)

Swift stdlib default implemention for Greate operation

extension Decimal: LCDecimalPrecise {
public static func == (lhs: Decimal, rhs: Decimal) -> Bool {
return !((lhs - rhs).doubleValue > LCMetricUnit.moneyPrecise ||
(rhs - lhs).doubleValue > LCMetricUnit.moneyPrecise)
}
public static func < (lhs: Decimal, rhs: Decimal) -> Bool {
return (lhs - rhs).doubleValue < -LCMetricUnit.moneyPrecise
}
public static func > (lhs: Decimal, rhs: Decimal) -> Bool {
return (lhs - rhs).doubleValue > LCMetricUnit.moneyPrecise
}
}
after overriding the first two methods(> operator method ignored), then calling the method of the following for example:
if Decimal(string: "1") > Decimal(string: "2") {//TODO sth}
I think the less(<) operator will expect to be called according the document and source code,
When debugging, it doesn't be called. So strange!!! Finally, we implement greater operation to work around this problem.

What is the Swift equivalent for Java's Comparator Interface

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
}
}

Compare Day/Month in Swift Struct

I would like sort an array of SpecialDay instances: [struct1, struct2, struct3, ...] using the code below:
struct SpecialDay: Hashable, Comparable {
var day: Int
var month: Int
var hashValue: Int {
return (31 &* day.hashValue &+ month.hashValue)
}
}
func ==(lhs: SpecialDay, rhs: SpecialDay) -> Bool {
return lhs.day == rhs.day && lhs.month == rhs.month
}
func <(lhs: SpecialDay, rhs: SpecialDay) -> Bool {
return lhs.day < rhs.day && lhs.month <= rhs.month
}
Sorting would be done like this:
let newArray = currentArray.sorted({ $0 < $1 })
I think I only need to find the right logic behind the comparable method:
func <(lhs: SpecialDay, rhs: SpecialDay) -> Bool
... but I am pulling my teeth on this one. My currently implemented logic is obviously not sorting correctly.
Any hints would be greatly appreciated.
The problem is the and in this line:
return lhs.day < rhs.day && lhs.month <= rhs.month
If the lhs month is less than the rhs it should always return true not taking into account the day. However, when you and with the comparison to days, you can get a false for the days not being less and a true for the months, which results in a false. You need something just a little more complicated:
func <(lhs: SpecialDay, rhs: SpecialDay) -> Bool {
if lhs.month < rhs.month { return true }
else if lhs.month > rhs.month { return false }
else {
return lhs.day < rhs.day
}
}

Defining `Comparable` for optional types in Swift 1.2

import SwiftyJSON
public typealias FeedItem = JSON
extension FeedItem {
var id: Int { get { return self["id"].intValue } }
}
public func <(lhs: FeedItem, rhs: FeedItem) -> Bool {
return lhs.id < rhs.id
}
public func ==(lhs: FeedItem, rhs: FeedItem) -> Bool {
return lhs.id == rhs.id
}
extension FeedItem:Comparable {}
extension Optional : Comparable {}
public func < <T>(l:T?, r:T?) -> Bool {
if let a=l,b=r {
return a < b
} else if (l==nil) && (r != nil) { return true }
else { return false }
}
public func == <T>(l:T?, r:T?) -> Bool {
if let a=l, b=r {
return a==b
} else {
return false
}
}
First, it should read extension Optional<T where T:Comparable>: Comparable but swift 1.2 does not allow that. Anyway I can express the constraint more explicitly rather than expecting the reader to realize the fact by noticing return a < b and return a==b ?
Second (and apparently more important): the code above works when I use < and > but minElement and maxElement both return nil when a nil is present in their input no matter what and min and max fall into infinite recursion:
let items: [FeedItem?] = [ nil, .Some(JSON(["id":2])), .Some(JSON(["id":1])) ]
println(items[0]?.id) // nil
println(items[1]?.id) // Optional(2)
println(items[2]?.id) // Optional(1)
println(items[0] < items[1]) // true
println(items[1] < items[2]) // false
println(items[2] < items[1]) // true
println(minElement(items)) // nil
println(maxElement(items)) // nil
println( min(items[0],items[2]) ) // nil
println( min(items[2],items[1]) ) // crashes due to infinite recursion
I'm no debug (or swift) expert but from what I can gather in XCode I believe the
if let a=l,b=r {
return a < b
}
part somehow misses the point that a and b are not Optionals but FeedItems. I expect the a < b should call the < operator on FeedItem and not the one on Optional but apparently this is exactly what happens; i.e. a < b resolves to the same function it is called from (that is, the < for Optionals) and thus a recursion happens. I might be wrong though.
Insights ?