Mathematical sign as function parameter - swift

Can I somehow send the mathematical sign (+, -, *) as function parameters? I want to call reduce() function for different sign.

In swift signs are functions name for a specified mathematic operation. To pass sign as parameter the parameter type must be function that takes two numbers and return a number. If you command + click on any sign you will see its definition as follow :
public func +(lhs: UInt8, rhs: UInt8) -> UInt8
public func +(lhs: Int8, rhs: Int8) -> Int8
public func +(lhs: UInt16, rhs: UInt16) -> UInt16
public func +(lhs: Int16, rhs: Int16) -> Int16
public func +(lhs: UInt32, rhs: UInt32) -> UInt32
public func +(lhs: Int32, rhs: Int32) -> Int32
public func +(lhs: UInt64, rhs: UInt64) -> UInt64
public func +(lhs: Int64, rhs: Int64) -> Int64
public func +(lhs: UInt, rhs: UInt) -> UInt
public func +(lhs: Int, rhs: Int) -> Int
In your case your reduce function should look as the following one
func reduce(sign: (Int,Int)->Int) -> Int{
return sign(2,3)
}
reduce(*)
reduce(-)

func doSomeCalculation(_ fun:((Int, Int) -> Int)) -> Int {
return fun(12,13)
}
doSomeCalculation(+) // 25
doSomeCalculation(-) // -1
The same can be done for UInt, the IntXX, etc.
+ is basically simply a function that takes two arguments and returns the sum of it. Since functions are objects like any other you can pass them around as such.
The same way you can pass + into reduce.

Yes, you can send any binary operator to the reduce() function, providing the original value and the elements in the collection are of the same type, and thus the operator can be applied.
Think at operators as functions/closures and you'll understand why this is possible in Swift. In fact operators are just like functions - they are named closures.
Also think at the way new operators can be added - you define a function with the operator name that takes a number of parameters equal to the operator arity.
Thus, the following is syntactically correct, and provides the expected output (6):
[1,2,3].reduce(0, combine: +)

Send as a Character, then switch to identify:
func acceptASign(sign: Character) {
switch sign {
case "+":
//do some addition
case "-":
//do some subtraction
case "*":
//do some multiplication
case "/":
//do some division
default:
break;
}
}

Related

Using Swift Generics to Call a Non-Generic Library

I'm trying to write a generic Swift wrapper for some of the vector operations in the Accelerate vDSP framework and I'm running into a problem calling the functions in a generic way.
My vector struct looks like:
public struct Vector<T> {
let array: [T]
public static func add(_ a: [T], _ b: [T]) -> [T] {
vDSP.add(a, b)
}
public static func + (_ lhs: Self , _ rhs: Self) -> Self {
Self.add(lhs.array, rhs.array)
}
}
The problem is the add function is overloaded to either take Floats and return Floats or take Doubles and return Doubles. Since the type isn't known at compile time I get an error No exact matches in call to static method 'add'
The only way I've found to get around this is to explicitly check the type before the call and cast:
public static func add(_ a: [T], _ b: [T]) -> [T] {
if T.self is Float.Type {
return vDSP.add(a as! [Float], b as! [Float]) as! [T]
} else {
return vDSP.add(a as! [Double], b as! [Double]) as! [T]
}
}
or to use constrained methods
public static func add(_ a: T, _ b: [T]) -> [T] where T == Float { vDSP.add(a, b) }
public static func add(_ a: T, _ b: [T]) -> [T] where T == Double { vDSP.add(a, b) }
Both of these lead to uncomfortable code duplication, and what's more if I had more than two types (for example if supported is added for the upcoming Float16 type) I'd need to keep adding more and more cases. The latter approach seems especially bad since the method bodies are identical.
I'd like to be able to do something like vDSP.add<T>(a, b) but it seems Swift doesn't support this. Is there some other way to acheive this and avoid the code duplication?

Swift - How to write generic max function

I'm new to Swift and I want to write a generic max function which compares the two parameter and returns the larger one, for basic types like Int, Double, etc.
func max<T>(_ num1:T, _ num2:T) -> T {
return (num1 > num2) ? num1 : num2;
}
But I found this does't work, reported that Binary operation '>' cannot be applied to two 'T' operand.
I saw an example about generic add function Here
protocol Summable { static func +(lhs: Self, rhs: Self) -> Self }
extension Int: Summable {}
extension Double: Summable {}
func add<T: Summable>(x: T, y: T) -> T {
return x + y
}
So I think I should have a protocol for my max function, too. So this is my attempt:
protocol Comparable {
static func >(lhs: Self, rhs: Self) -> Self
}
extension Int:Comparable {}
extension Double:Comparable {}
But this doesn't work. I know there is a provided Comparable protocol from Swift, but I want to try it myself. Could you please help?
protocol TempComparable {
static func >(lhs:Self, rhs:Self) -> Bool;
}
func max<T:TempComparable>(_ num1:T, _ num2:T) -> T {
return (num1 > num2) ? num1 : num2;
}
What you need is to create your protocol as the sub-protocol of Comparable and provide a unique name instead of naming it same as an existing Type which causes confusion. And implement the protocol requirements in the extension of your protocol and conform the required types to the protocol. Here's how:
protocol CustomComparable: Comparable {
static func > (lhs: Self, rhs: Self) -> Self
}
extension CustomComparable {
static func > (lhs: Self, rhs: Self) -> Self {
lhs > rhs ? lhs : rhs
}
}
extension Int: CustomComparable {}
extension Double: CustomComparable {}

Generic Swift Function Error Swift 3.0

func multiply<T: Strideable> (lhs: T, rhs: T) -> T {
return lhs * rhs
}
Why is this returning an error of:
No '*' candidates produce the expected contextual result result type 'T'
Found a work around by extending the * operator to the Double, Int, and Float types.
protocol Numeric {
func *(lhs: Self, rhs: Self) -> Self
}
extension Double: Numeric {}
extension Float: Numeric {}
extension Int: Numeric {}
Look into Strideable protocol, it does not have method ''. If you rather want it so that 'T' can be multiplied to another 'T', you should rather declare it in such a way that 'T' has ''.
func multiply<T: Strideable> (lhs: T, rhs: T) -> T where T:IntegerArithmetic {
return lhs * rhs
}
Or, you can also do as other answer suggests, since with this method you can only use Integers.

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.

Regarding functions, the math symbol function * is called differently. Why?

The definition of the multiply symbol is this.
public func *(lhs: Int, rhs: Int) -> Int
I can use it in a function, like this.
func productUsingReduce(xs: [Int]) -> Int {
return xs.reduce(1, { x,y in x * y})
}
or simply like this.
func productUsingReduce(xs: [Int]) -> Int {
return xs.reduce(1, *)
}
If I try to define the same thing with a different name.
func yes(lhs: Int, rhs: Int) -> Int {
return lhs * rhs
}
I get a compiler error when I try to use it like this.
func productUsingReduce(xs: [Int]) -> Int {
return xs.reduce(1, { x,y in x yes y})
}
Why?
And why doesn't the following sytnax compile?
func productUsingReduce(xs: [Int]) -> Int {
return xs.reduce(1, { x, y in *(lhs: x, rhs: y) })
}
Your function func yes(.. is just a standard function.
To define an operator you have to declare the operator
infix operator yes
and the corresponding function
func yes(lhs: Int, rhs: Int) -> Int {
return lhs * rhs
}
But now comes the bad news: You cannot use alphanumeric characters as operators.
* definition is made of two parts:
The method definition (in Swift.Math.Integers, Swift.Math.Floating and so on)
public func *(lhs: Int, rhs: Int) -> Int
and its operator behavior (in Swift, you can write import Swift in Xcode and CMD+click on it to access the file)
infix operator * : MultiplicationPrecedence
The last snippet makes * an infix operator, so you can only use it in infix form.
About your yes function, you cannot make it behave as an operator. While you can define your own custom operators, they can only contain certain characters. As per the language specification:
Custom operators can begin with one of the ASCII characters /, =, -, +, !, *, %, <, >, &, |, ^, ?, or ~, or one of the Unicode characters defined in the grammar below (which include characters from the Mathematical Operators, Miscellaneous Symbols, and Dingbats Unicode blocks, among others). After the first character, combining Unicode characters are also allowed.
So you have to use it its standard function form.
But you could do
func ^^^(lhs: Int, rhs: Int) -> Int {
return lhs * rhs
}
infix operator ^^^
and that would work as expected
3 ^^^ 2 // 6