Swift 3 Closure - swift

In Swift 3 can I use string-specific implementation in trailing closure?
let names = ["Ekram","Galib","Hasan","Rangon","Asif","Saikat"]
let reversedName = names.sorted{ > }

Why wrap the > in a trailing closure? sorted(by:) takes a function and > already matches its signature. So just do:
let reversedName = names.sorted(by: >)
Just to state maybe non-obvious things:
a) Operators in Swift work like regular functions, e.g. in this case sth like func > <T>(lhs: T, rhs: T) -> Bool
b) In Swift functions are named closures, if an API expects a closure (like (lhs: T, rhs: T) -> Bool), you can also use a named function, like > or func compareTheTwo(a: String, b: String) -> Bool

Yup, but you have to specify which arguments to it you’re actually comparing:
let reversedNames = names.sorted { $0 > $1 }

Related

How can a closure in Swift only be passed in a * for the reduce function?

extension Array {
func reduce<T>(_ initial: T, combine: (T, Element) -> T) -> T {
var result = initial
for x in self {
result = combine(result, x)
}
return result
}
}
How does the below function work when it only passes a * to the combine closure?
func productUsingReduce(integers: [Int]) -> Int {
return integers.reduce(1, combine: *)
}
static func * (lhs: Self, rhs: Self) -> Self is an operator function defined on the Numeric protocol. So, you are really just passing in a function that takes two arguments.
What does the declaration mean?
combine: (T, Element) -> T
It says: the combine parameter is a function that takes two parameters, a T and an Element, and returns a T.
Well, in Swift, operators are functions, and * is such a function. So it suffices to pass a reference to this function as the combine parameter. The bare name, *, is that reference.

Swift - Reference default comparison function as a function parameter

I'm trying to implement a convenience Collection.sorted(by: KeyPath) function.
So far, it works if do
func sorted<T: Comparable>(by keyPath: KeyPath<Element, T>) -> [Element] {
return sorted { lhs, rhs
return lhs[keyPath: keyPath] < rhs[keyPath: keyPath]
}
}
But what if I want to allow the caller to specify the actual sorting logic ? I added a callback to perform the comparison, like such (taking inspiration from the orginal sorted(_:) function signature).
func sorted<T: Comparable>(by keyPath: KeyPath<Element, T>, _ compare: (T, T) throws -> Bool) rethrows -> [Element] {
return try sorted { lhs, rhs in
return try compare(lhs[keyPath: keyPath], rhs[keyPath: keyPath])
}
}
Now, this is all works, but it means the callsite always has to specify which sorting operation to perform.
let sorted = myArray.sorted(by: \.name, <)
I'd like it to default to <, but how can I reference the < operator by default, in my function's signature ?
It is actually possible to reference the un-applied < function by wrapping it in parentheses (<) when using it as a default parameter.
func sorted<T: Comparable>(
by keyPath: KeyPath<Element, T>,
_ compare: (T, T) throws -> Bool = (<)
) rethrows -> [Element] {
return try sorted { lhs, rhs in
return try compare(lhs[keyPath: keyPath], rhs[keyPath: keyPath])
}
}
However, there is currently an issue with the compiler when doing this.
Even though < doesn't throw, the compiler will still enforce you to use try at the call site.
A bug report for this was opened quite some time ago, and is still unresolved. If you run into this, please upvote it: https://bugs.swift.org/browse/SR-1534
Additionally, as pointed out in the comments, the sorted(by:) function is actually 2 different functions.
One requires Comparable and uses < internally, while the other lets you specify the sorting logic directly and thus, does not require Comparable conformance.
Therefore, this convenience sorting by keyPath would still require 2 functions.

is there a more elegant syntax for Swift Filter with 2 parameters

Is there a more elegant way to filter with an additional parameter (or map, reduce).
When I filter with a single parameter, we get a beautiful easy to ready syntax
let numbers = Array(1...10)
func isGreaterThan5(number:Int) -> Bool {
return number > 5
}
numbers.filter(isGreaterThan5)
However, if I need to pass an additional parameter to my function it turns out ugly
func isGreaterThanX(number:Int,x:Int) -> Bool {
return number > x
}
numbers.filter { (number) -> Bool in
isGreaterThanX(number: number, x: 8)
}
I would like to use something like
numbers.filter(isGreaterThanX(number: $0, x: 3))
but this gives a compile error annonymous closure argument not contained in a closure
You could change your function to return a closure which serves
as predicate for the filter method:
func isGreaterThan(_ lowerBound: Int) -> (Int) -> Bool {
return { $0 > lowerBound }
}
let filtered = numbers.filter(isGreaterThan(5))
isGreaterThan is a function taking an Int argument and returning
a closure of type (Int) -> Bool. The returned closure "captures"
the value of the given lower bound.
If you make the function generic then it can be used with
other comparable types as well:
func isGreaterThan<T: Comparable>(_ lowerBound: T) -> (T) -> Bool {
return { $0 > lowerBound }
}
print(["D", "C", "B", "A"].filter(isGreaterThan("B")))
In this particular case however, a literal closure is also easy to read:
let filtered = numbers.filter( { $0 > 5 })
And just for the sake of completeness: Using the fact that
Instance Methods are Curried Functions in Swift, this would work as well:
extension Comparable {
func greaterThanFilter(value: Self) -> Bool {
return value > self
}
}
let filtered = numbers.filter(5.greaterThanFilter)
but the "reversed logic" might be confusing.
Remark: In earlier Swift versions you could use a curried function
syntax:
func isGreaterThan(lowerBound: Int)(value: Int) -> Bool {
return value > lowerBound
}
but this feature has been removed in Swift 3.

Overriding / operator for Optionals using generics results in endless loop

lets take a look at the following code snippet:
func / <T>(lhs: T?,rhs: T?) throws -> T? {
switch (lhs,rhs) {
case let (l?,r?):
return try l/r
default:
return nil
}
}
let x : Double? = 2
let y : Double? = 2
let z = try! x/y
I created a generic function that expects two optional parameters. If I run this code it leads to an endless loop because try l/r uses func / <T>(lhs: T?,rhs: T?) to divide the values. Can anyone explain why dividing two none optional double values results in a function call to the method I wrote and not the default / operator definition for Double?
If I extend Double by an extension that requires a static / operator for that class everything works like a charm:
protocol Dividable {
static func /(lhs: Self, rhs: Self) -> Self
}
extension Double: Dividable {}
func / <T:Dividable>(lhs: T?,rhs: T?) throws -> T? {
switch (lhs,rhs) {
case let (l?,r?):
return l/r
default:
return nil
}
}
let x : Double? = 2
let y : Double? = 2
let z = try! x/y
The binary arithmetic for e.g. Double is not implemented using concrete Double types, but rather as default generic implementations for types conforming to FloatingPoint:
swift/stdlib/public/core/FloatingPoint.swift.gyb
Within the block of your custom / function, the compiler does not know that the typeholder T conforms to FloatingPoint, and the overload resolution of l/r will resolve to the method itself (since the FloatingPoint implementions, while being more specific, are not accessible to the more general non-constrained type T in your custom implementation).
You could workaround this by adding FloatingPoint as a type constraint also to your own custom method:
func /<T: FloatingPoint>(lhs: T?, rhs: T?) throws -> T? {
switch (lhs, rhs) {
case let (l?, r?):
return try l/r
default:
return nil
}
}
Likewise, the binary arithmetic for integer types are implemented as default generic implementations constrained to types conforming to the internal protocol _IntegerArithmetic, to which the public protocol IntegerArithmetic conforms.
swift/stdlib/public/core/IntegerArithmetic.swift.gyb
You can use the latter public protocol to implement an overload of your custom operator function for integer types.
func /<T: IntegerArithmetic>(lhs: T?, rhs: T?) throws -> T? {
switch (lhs, rhs) {
case let (l?, r?):
return try l/r
default:
return nil
}
}
Finally, you might want to consider why you'd want this function to throw. N also ote that there are ways to simplify you implementations when dealing with exactly two optional values that you want to operate on only in case both differ from nil. E.g.:
func /<T: FloatingPoint>(lhs: T?, rhs: T?) -> T? {
return lhs.flatMap { l in rhs.map{ l / $0 } }
}
func /<T: IntegerArithmetic>(lhs: T?, rhs: T?) -> T? {
return lhs.flatMap { l in rhs.map{ l / $0 } }
}
Of, if you prefer semantics over brevity, wrap your switch statement in a single if statement
func /<T: FloatingPoint>(lhs: T?, rhs: T?) -> T? {
if case let (l?, r?) = (lhs, rhs) {
return l/r
}
return nil
}
func /<T: IntegerArithmetic>(lhs: T?, rhs: T?) -> T? {
if case let (l?, r?) = (lhs, rhs) {
return l/r
}
return nil
}
Your function signature doesn't let the compiler know anything about the type of lhs and rhs, other than that they're the same type. For example you could call your method like this:
let str1 = "Left string"
let str2 = "Right string"
let result = try? str1 / str2
This will result in an infinite loop because the only method that the compiler knows called / that takes in 2 parameters of the same type (in this case String) is the one that you've declared; return try l/r will call your func / <T>(lhs: T?,rhs: T?) throws -> T? method over and over again.
As you mentioned in your question, you will need a protocol that your parameters must conform to. Unfortunately there is no existing Number or Dividable protocol that would fit your needs, so you'll have to make your own.
Note that division will crash when the denominator is 0 and will not throw an error, so you should be able to remove the throws keyword from your function so that it is:
func / <T:Dividable>(lhs: T?, rhs: T?) -> T?
Edit to clarify further
If you think about what the compiler knows at that point I think it makes more sense. Once inside the function all the compiler knows is that lhs and rhs are of type T and optional. It doesn't know what T is, or any of its properties or functions, but only that they're both of type T. Once you unwrap the values you still only know that both are of type T and non-optional. Even though you know that T (in this instance) is a Double, it could be a String (as per my example above). This would require the compiler to iterate over every possible class and struct to find something that supports your method signature (in this case func / (lhs: Double, rhs: Double) -> Double), which it simply can't do (in a reasonable time), and would lead to unpredictable code. Imagine if you added this global method and then every time / was used on something existing (such as Float(10) / Float(5)) your method was called, that would get pretty messy and confusing pretty quickly.

Shorthand for wrapping a swift variable in an optional?

Swift allows us to use the shorthand notation str! to unwrap an optional. But what if we want to do the opposite?
Say I have a variable:
var str = String() // String
Is there any shorthand notation to convert this to an optional (i.e. String? or String!)?
(E.g. I want to do something like var strOptional = ?(str).)
Alternatively, if there is no shorthand for this notation, how can I convert it to an optional without explicitly mentioning its type (e.g. I don't want to mention String).
In other words, I know that I can wrap a variable as an optional with any of these methods:
var strOptional = str as String?
var strOptional: String? = str
var strOptional = String?(str)
... but in each case, I must explicitly write String.
I would rather write something like: var strOptional = str as typeof?(str), if there is no shorthand syntax. (The advantage is that if the variable's type is frequently changed in the code base, it would be one less place to update.)
As far as a real world example of where this would be useful, imagine I want to use an AVCaptureDevice and I use the following code:
let device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
device.lockForConfiguration(nil)
lockForConfiguration() will crash at runtime on a device that has no video camera, and the compiler won't warn me about it. The reason is that defaultDeviceWithMediaType may return nil according to the documentation[1], yet it is defined to return a AVCaptureDevice!.
To fix a faulty API like this, it would be nice to do something like:
let device = ?(AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo))
... to get a AVCaptureDevice?, and have the compiler catch any mistakes I might make.
Currently, I must resort to the more verbose:
let device: AVCaptureDevice? = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
Another example:
In this case, I want to give a default value to my variable that is a string, but later on, I may want to assign it a nil value.
var myString = "Hi"
// ...
if (someCondition()) {
myString = nil // Syntax error: myString is String
}
Currently I have to resort to var myString: String? = "Hi" but something like var myString = ?("Hi") would be less verbose.
[1] If you open AVCaptureDevice.h, you will see the following documentation about the return value: "The default device with the given media type, or nil if no device with that media type exists."
Optional is just an enum in swift, so you can do: Optional(str)
From the swift interface:
/// A type that can represent either a `Wrapped` value or `nil`, the absence
/// of a value.
public enum Optional<Wrapped> : _Reflectable, NilLiteralConvertible {
case None
case Some(Wrapped)
/// Construct a `nil` instance.
public init()
/// Construct a non-`nil` instance that stores `some`.
public init(_ some: Wrapped)
/// If `self == nil`, returns `nil`. Otherwise, returns `f(self!)`.
#warn_unused_result
public func map<U>(#noescape f: (Wrapped) throws -> U) rethrows -> U?
/// Returns `nil` if `self` is `nil`, `f(self!)` otherwise.
#warn_unused_result
public func flatMap<U>(#noescape f: (Wrapped) throws -> U?) rethrows -> U?
/// Create an instance initialized with `nil`.
public init(nilLiteral: ())
}
To wrap up a variable you could use operator overloading and generic functions. For example:
prefix operator ??? {}
prefix func ??? <T> (x: T) -> T? {
return Optional(x)
}
To relate this to your second example, you would do the following:
var myString = ???"Hi" // Optional("Hi")
if someCondition() {
myString = nil
}
In the lighthearted spirit that, as I understand, the question was posed, you can define a postfix operator that uses one character less than your ideal solution (a pair of parens and a question mark):
postfix operator =? {}
postfix func =? <T> (rhs: T) -> T? { return rhs }
postfix func =? <T> (rhs: T!) -> T? { return rhs ?? nil }
var x = 3=?
x is Int? //--> true
var imp: Int! = 3
var opt = imp=?
opt is Int? //--> true
As to Apple's APIs you mention, since they already return an optional, albeit an implicitly unwrapped optional, you could use the nil coalescing operator ?? to convert it to a plain optional:
let y: Int! = 3 // posing for a rogue API
y is Int? //--> false
let z = y ?? nil
z is Int? //--> true
Perhaps a sligtly more interesting use of a dodgy operator is a higher order operator function that lifts T -> Us into T? -> U?s...
func opt <T, U> (f: T -> U) -> T? -> U? { // we'll implement this as an operator
return { $0.map(f) }
}
postfix operator ->? {}
postfix func ->? <T, U> (f: T -> U) -> T? -> U? {
return { $0.map(f) }
}
Now, let's use it:
let square: Int -> Int = { $0 * $0 }
let i: Int? = 3
square->? (i)
Which is equivalent to:
opt(square)(i)
Which is equivalent to (but potentially a little more versatile than):
i.map(square)
This all makes much more sense when used along with the pipe forward operator:
infix operator |> { associativity left precedence 89 }
func |> <A, B>(a: A, f: A -> B) -> B {
return f(a)
}
Then you can do:
i |> opt(square)
or
i |> square->?
Or we can conflate these into an optional pipe forward, which can take care of implicitly unwrapped optionals too:
infix operator ?> { associativity left precedence 89 }
func ?> <T, U> (lhs: T?, rhs: T -> U) -> U? {
return lhs.map(rhs)
}
let im: Int! = 5
let op: Int? = 5
im ?> square |> debugPrintln //--> Optional(25)
op ?> square |> debugPrintln //--> Optional(25)
Which is equivalent to:
debugPrintln(op.map(square))