Swift: generic power function as infix operator - swift

Below is the answer to the original question of how to add a power operator for Int numbers:
infix operator ^^ { associativity left precedence 160 }
func ^^ (radix: Int, power: Int) -> Int {
return Int(pow(CGFloat(radix), CGFloat(power)))
}
How would one generalise this so that it works for Double, Float, and Int?

You cannot "generalize" it. You have to implement it for each type separately.
If you look in the Swift header, you will see that that is exactly what Swift itself does for the built-in operators such as +. There is no "general" + function; there is one + function for every numeric type.
Thus:
infix operator ^^ { associativity left precedence 160 }
func ^^ (radix: Int, power: Int) -> Int {
return Int(pow(CGFloat(radix), CGFloat(power)))
}
func ^^ (radix: Double, power: Double) -> Double {
return Double(pow(CGFloat(radix), CGFloat(power)))
}
// ... and so on for as many types as you like ...

Related

Distinguishing Tuple and Multi-Argument Functions

I write this function in playground which has value parameter of tuple type and return type is tuple.
func tuple(value: (Int, Int) ) -> (first: Int, second: Int) {
let firstGrabTuple = value.0 + 5
let secondGrabTuple = value.1 + 5
return (firstGrabTuple, secondGrabTuple)
}
Then I assigned it to constant called closure
let closure = tuple
//(Playground showing) let closure became a function of type (Int, Int) -> (first: Int, second: Int)
Then for double check I write another function that takes closure as its parameter, of type ((Int, Int)) -> (Int, Int)
func anotherTuple(_ closure: ((Int, Int)) -> (Int, Int)) {
closure((5, 5))
}
when I call anotherTuple
anotherTuple { (x) -> (Int, Int) in
let first = x.0 + 5
let second = x.1 + 5
return (first, second)
}
//prints .0 10, .1 10 as expected
So My question is as mention above when first function tuple I assigned it to constant called closure became of type (Int, Int) -> (first: Int, second: Int). But in second function If i have to use a parameter of type as tuple I have to set its parameter in double parentheses like (_ closure: ((Int, Int)) -> (Int, Int)).
But If I remove those double parentheses from anotherTuple function parameter then it will only expect 2 values as multi-argument function. No error for used as multi-argument function instead of tuple argument why is that? Added image for more detail.
and second question is why that
let closure = tuple
//let closure became a function of type (Int, Int) -> (first: Int, second: Int)
not became of type ((Int, Int)) -> (first: Int, second: Int)
**Note - When I tried to pass that constant named closure as argument to another function which will expect closure of type ((Int, Int)) -> (Int, Int) then while typing closure showing me it as ((Int, Int)) -> (Int, Int) in auto complete code.
You're correct about the confusion. I'm somewhat going to just restate your understanding, and say "yes, tuples in Swift are weird and slightly broken."
Swift does not distinguish between functions that take tuples vs multiple arguments in some ways, but does distinguish in other ways. (This is one of many reasons to avoid tuples at this point in Swift's life.)
First, these two functions have almost the same type in Swift (note that Void and () are identical):
func tuple(value: (Int, Int) ) {} // (Int, Int) -> Void
func two(value1: Int, value2: Int) {} // (Int, Int) -> Void
They look the same. But if you define a function that accepts that type, it can't take tuple:
func take(f: (Int, Int) -> Void) {}
take(f: tuple) // Fails
take(f: two) // ok
But if you define a function that takes ((Int, Int)) -> Void it can accept either function:
func take(f: ((Int, Int)) -> Void) {}
take(f: tuple) // ok
take(f: two) // ok
That suggests that (Int, Int) -> Void is a subtype of ((Int, Int)) -> Void.
But variables belie this:
var f: (Int, Int) -> Void
f = tuple // Ok
f = two // Ok
var g: ((Int, Int)) -> Void
g = tuple // ok
g = two // ok
g = f // ok
f = g // ok
And that suggests that (Int, Int) -> Void and ((Int, Int)) -> Void are the same type. But the take function indicates they're not.
Yes. All of that is true at the same time. Functions that accept tuples are not a coherent type in Swift (they do not occupy a clearly-deliniated spot in the type hierarchy). That's just where we are in Swift today.
Old, incorrect answer.
This is just a quirk of Playgrounds, and you should feel free to open a radar about that.
If you check type(of: closure), it'll print the type you expect. Swift knows the correct type; Playgrounds just displays the wrong thing.

Cannot use overloaded operator of struct defined inside function

I have a struct defined inside a function and would like define and use an overloaded operator on that struct:
func test() {
struct Foo {
let value: Int
static func +(left: Foo, right: Foo) -> Foo {
return Foo(value: left.value + right.value)
}
}
print(Foo(value: 2) + Foo(value: 3))
}
But this does not work and I get the following error:
test.swift:10:25: error: binary operator '+' cannot be applied to two 'Foo' operands
print(Foo(value: 2) + Foo(value: 3))
~~~~~~~~~~~~~ ^ ~~~~~~~~~~~~~
test.swift:10:25: note: overloads for '+' exist with these partially matching parameter lists: (Float, Float), (Double, Double), (Float80, Float80), (UInt8, UInt8), (Int8, Int8), (UInt16, UInt16), (Int16, Int16), (UInt32, UInt32), (Int32, Int32), (UInt64, UInt64), (Int64, Int64), (UInt, UInt), (Int, Int), (String, String), (C, S), (S, C), (RRC1, RRC2), (Self, Self.Stride), (Self.Stride, Self), (UnsafeMutablePointer<Pointee>, Int), (Int, UnsafeMutablePointer<Pointee>), (UnsafePointer<Pointee>, Int), (Int, UnsafePointer<Pointee>)
print(Foo(value: 2) + Foo(value: 3))
^
Is it just not suppoerted to define operators on non-global structs or am I missing something? Are there any options to make this work without moving the struct to the file scope?
You can't declare a struct with overload and then use it in the same function. In compilation time, the overload will not be known.
So you have to put the struct outside the function like this
struct Foo{
let value: Int
static func +(lhs: Foo, rhs: Foo) -> Foo {
return Foo(value: lhs.value + rhs.value)
}
}
func test() {
print(Foo(value: 2) + Foo(value: 3))
}

Swift: How do I pass in a value for this argument?

rk4_func(
y_array: [Double],
f_array: [(([Double], Double) -> Double)],
t_val: Double,
h_val: Double)
-> [Double]
I don't understand how to use the argument f_array: [(([Double], Double) -> Double)]. How exactly do I pass that in when calling the function?
That's kind of tricky :)
A quick remainder about Swift's function types: a type of (Int) -> Float means: a function that takes an int and returns a float. Okay, now back to your question:
As the argument f_array says (or, at least, tries to), it expects an array of functions. Inside this array, each function then accepts two arguments:
a doubles array: [Double]
a single double: Double
and returns a Double.
A quick example to get you going:
func f(_ a: [Double], _ b: Double) -> Double { ... }
func g(_ a: [Double], _ b: Double) -> Double { ... }
let f_array = [f, g]
There's a fair share of Swift magic up there. Please let me know if you need any further clarification.

Swift How to access parameter in function

I have something like this:
enum Op {
case Operation(String, (Double, Double) -> Double)
}
Now I want to do this:
var description: String {
get {
switch Op {
case .Operation(let symbol, /* how can I access the two (Double, Double) from (Double, Double) -> Double? */ ):
return Double1 + symbol + Double2
}
}
}
Your question:
how can I access the two (Double, Double)
...makes no sense. There are no Doubles to access. The second value is a (Double, Double) -> Double. That's a function. Not a called function; just a function. The terms Double denote types, not values.
You could capture this function. You could call this function, yourself. But there are no Doubles there. Do you see?
Here's an example of actual working code; try it in a playground:
enum Op {
case Operation(String, (Double, Double) -> Double)
}
func f (x:Double, y:Double) -> Double { return x + y }
let op = Op.Operation("howdy", f)
switch op {
case .Operation(let symbol, let function) :
print(symbol) // Howdy
print(function(1,2)) // 3
}
Do you see? I didn't fetch the two Doubles; I supplied them.

Non-escaping error when implementing Church Numerals in Swift 3

I am attempting to implement Church Numerals in Swift 3. Currently, I have:
func numToChurch(n: Int) -> ((Int) -> Int) -> Int {
return { (f: (Int) -> Int) -> (Int) -> Int in
return { (x : Int) -> Int in
return f(numToChurch(n: n - 1)(f)(x))
}
}
}
func churchToNum(f: ((Int) -> Int) -> (Int)-> Int) -> Int {
return f({ (i : Int) -> Int in
return i + 1
})(0)
}
At this line in my function numToChurch:
return f(numToChurch(n: n - 1)(f)(x))
I keep getting a compile-time error that "Closure of non-escaping parameter 'f' may allow it to escape". As a quick-fix, I accepted the recommended changes to include #escaping:
func numToChurch(n: Int) -> ((Int) -> Int) -> Int {
return { (f: #escaping (Int) -> Int) -> (Int) -> Int in
return { (x : Int) -> Int in
return f(numToChurch(n: n - 1)(f)(x))
}
}
}
But even after making the changes, I keep getting told the same error and it recommends adding another #escaping after "f:". I understand that this has to do with marking function parameters as #escaping to tell the compiler that the parameters can be stored or captured for functional programming. But I don't understand why I keep getting this error.
Original non-escaping question resolved
Help with understanding church encoding in Swift cont:
func zero(_f: Int) -> (Int) -> Int {
return { (x: Int) -> Int in
return x
}
}
func one(f: #escaping (Int) -> Int) -> (Int) -> Int {
return { (x: Int) in
return f(x)
}
}
func two(f: #escaping (Int) -> Int) -> (Int) -> Int {
return { (x: Int) in
return f(f(x))
}
}
func succ(_ f: Int) -> (#escaping (Int) -> Int) -> (Int) -> Int {
return { (f : #escaping ((Int) -> Int)) -> Int in
return { (x : Int) -> Int in
return f(n(f)(x))
}
}
}
func sum(m: #escaping ((Int) -> (Int) -> Int)) -> ((Int) -> (Int) -> Int) -> (Int) -> (Int) -> Int {
return { (n: #escaping ((Int) -> Int)) -> (Int) -> (Int) -> Int in
return { (f: Int) -> (Int) -> Int in
return { (x: Int) -> Int in
return m(f)(n(f)(x))
}
}
}
You're using currying for multi-parameter functions. That isn't a very natural way to express things in Swift and it's making things complicated. (Swift is not a functional programming language.)
As your linked article says, "All Church numerals are functions that take two parameters." So do that. Make it a two parameter function.
typealias Church = (_ f: ((Int) -> Int), _ x: Int) -> Int
This is a function that takes two parameters, a function and its argument.
Now you want to wrap the argument in the function N times:
// You could probably write this iteratively, but it is pretty elegant recursively
func numToChurch(_ n: Int) -> Church {
// Church(0) does not apply the function
guard n > 0 else { return { (_, n) in n } }
// Otherwise, recursively apply the function
return { (f, x) in
numToChurch(n - 1)(f, f(x))
}
}
And getting back is just applying the function:
func churchToNum(_ church: Church) -> Int {
return church({$0 + 1}, 0)
}
Just building up on this, you can curry it (and I think I'm just saying what #kennytm has also answered). Currying is just slightly more complicated in Swift:
typealias Church = (#escaping (Int) -> Int) -> (Int) -> Int
func numToChurch(_ n: Int) -> Church {
// Church(0) does not apply the function
guard n > 0 else { return { _ in { n in n } } }
return { f in { x in
numToChurch(n - 1)(f)(f(x))
}
}
}
func churchToNum(_ church: Church) -> Int {
return church({$0 + 1})(0)
}
There's a very reasonable question: "Why do I need #escaping in the second case, but not in the first?" The answer is that when you pass the function in a tuple, you've already escaped it (by storing it in another data structure), so you don't need to mark it #escaping again.
To your further questions, using a typealias dramatically simplifies this problem and helps you think through your types much more clearly.
So what are the parameters of zero? Nothing. It's a constant. So what should its signature be?
func zero() -> Church
How do we implement it? We apply f zero times
func zero() -> Church {
return { f in { x in
x
} }
}
One and two are nearly identical:
func one() -> Church {
return { f in { x in
f(x)
} }
}
func two() -> Church {
return { f in { x in
f(f(x))
} }
}
What is the signature of succ? It takes a Church and returns a Church:
func succ(_ n: #escaping Church) -> Church {
Because this is Swift, we need a little nudge by adding #escaping and _ to make things more natural. (Swift is not a functional language; it decomposes problems differently. Composing functions is not its natural state, so the over-abundence of syntax should not shock us.) How to implement? Apply one more f to n:
func succ(_ n: #escaping Church) -> Church {
return { f in { x in
let nValue = n(f)(x)
return f(nValue)
} }
}
And again, what is the nature of sum? Well, we're in a currying mood, so that means it's a function that takes a Church and returns a function that takes a Church and returns a Church.
func sum(_ n: #escaping Church) -> (#escaping Church) -> Church
Again, a little extra syntax is needed because Swift. (And as above I've added an extra let binding just to make the pieces a little more clear.)
func sum(_ n: #escaping Church) -> (#escaping Church) -> Church {
return { m in { f in { x in
let nValue = n(f)(x)
return m(f)(nValue)
} } }
}
The deep lesson here is the power of the Church typealias. When you try to think of Church numbers as "functions that blah blah blah" you quickly get lost in the curry and syntax. Instead, abstract them to be "Church numbers" and just think about what every function should take and return. Remember that a Church number is always a function that takes an Int and returns an Int. It never grows or shrinks from that no matter how many times it's been nested.
It's worth taking this example in a couple of other directions because we can play out some deeper ideas of FP and also how Swift should really be written (which are not the same....)
First, writing Church numbers in pointed style is...inelegant. It just feels bad. Church numbers are defined in terms of functional composition, not application, so they should be written in a point-free style IMO. Basically, anywhere you see { f in { x in ...} }, that's just ugly and over-syntaxed. So we want functional composition. OK, we can dig into some experimental stdlib features and get that
infix operator ∘ : CompositionPrecedence
precedencegroup CompositionPrecedence {
associativity: left
higherThan: TernaryPrecedence
}
public func ∘<T, U, V>(g: #escaping (U) -> V, f: #escaping (T) -> U) -> ((T) -> V) {
return { g(f($0)) }
}
Now, what does that do for us?
func numToChurch(_ n: Int) -> Church {
// Church(0) does not apply the function
guard n > 0 else { return zero() }
return { f in f ∘ numToChurch(n - 1)(f) }
}
func succ(_ n: #escaping Church) -> Church {
return { f in f ∘ n(f) }
}
func sum(_ n: #escaping Church) -> (#escaping Church) -> Church {
return { m in { f in
n(f) ∘ m(f)
} }
}
So we don't need to talk about x anymore. And we capture the essence of Church numbers much more powerfully, IMO. Summing them is equivalent to functional composition.
But all that said, IMO this is not great Swift. Swift wants structure and methods, not functions. It definitely doesn't want a top-level function called zero(). That's horrible Swift. So how do we implement Church numbers in Swift? By lifting into a type.
struct Church {
typealias F = (#escaping (Int) -> Int) -> (Int) -> Int
let applying: F
static let zero: Church = Church{ _ in { $0 } }
func successor() -> Church {
return Church{ f in f ∘ self.applying(f) }
}
static func + (lhs: Church, rhs: Church) -> Church {
return Church{ f in lhs.applying(f) ∘ rhs.applying(f) }
}
}
extension Church {
init(_ n: Int) {
if n <= 0 { self = .zero }
else { applying = { f in f ∘ Church(n - 1).applying(f) } }
}
}
extension Int {
init(_ church: Church) {
self = church.applying{ $0 + 1 }(0)
}
}
Int(Church(3) + Church(7).successor() + Church.zero) // 11
#escaping is part of the argument type, so you need to do it like:
func numToChurch(n: Int) -> (#escaping (Int) -> Int) -> (Int) -> Int {
// ^~~~~~~~~
Complete, working code:
func numToChurch(n: Int) -> (#escaping (Int) -> Int) -> (Int) -> Int {
// ^~~~~~~~~ ^~~~~~
return { (f: #escaping (Int) -> Int) -> (Int) -> Int in
// ^~~~~~~~~
if n == 0 {
return { x in x }
} else {
return { (x : Int) -> Int in
return f(numToChurch(n: n - 1)(f)(x))
}
}
}
}
func churchToNum(f: (#escaping (Int) -> Int) -> (Int) -> Int) -> Int {
// ^~~~~~~~~
return f({ (i : Int) -> Int in
return i + 1
})(0)
}
let church = numToChurch(n: 4)
let num = churchToNum(f: church)
Note:
Your return type of numToChurch is wrong even without the #escaping part. You are missing a -> Int.
I have added the base n == 0 case in numToChurch, otherwise it will be an infinite recursion.
Since the result of numToChurch has an escaping closure, the same annotation needs to be added to that of churchToNum as well.