Ambiguous use of operator '>' - swift

i tried this
simple2 = {s1, s2 in s1 > s2}
and
var simple2 = {$0 > $1}
but still showing me
swift 3 closure Ambiguous use of 'operator >'

The closure must explicitly declare the type of the s1 and s2 parameters and that type must implement > operator. The typical way to do that is to make the signature of that closure ensure that the two parameters are (a) the same type; and (b) conform to the Comparable protocol.
If you want simple2 to take any Comparable type, rather than a closure, you could define a generic function:
func simple2<T: Comparable>(_ s1: T, _ s2: T) -> Bool {
return s1 > s2
}
Then you could call it with any Comparable type.

You need to specify the types of s1 and s2 and $0 and $1. Not even a human can infer what type you want these to be of, let alone the Swift compiler.
> can be applied to multiple types. Here are some of the examples:
Int and Int
Double and Double
CGFloat and CGFloat
You can specify the types like this:
let simple2: (Int, Int) -> Bool = {$0 > $1}

Related

Using Any instead of generics

Generics
Generic code enables you to write flexible, reusable functions and types that can work with any type, subject to requirements that you define. You can write code that avoids duplication and expresses its intent in a clear, abstracted manner.
Generics are one of the most powerful features of Swift, and much of the Swift standard library is built with generic code. In fact, you’ve been using generics throughout the Language Guide, even if you didn’t realize it. For example, Swift’s Array and Dictionary types are both generic collections. You can create an array that holds Int values, or an array that holds String values, or indeed an array for any other type that can be created in Swift. Similarly, you can create a dictionary to store values of any specified type, and there are no limitations on what that type can be.
The Problem That Generics Solve
Here’s a standard, nongeneric function called swapTwoInts(::), which swaps two Int values:
func swapTwoInts(_ a: inout Int, _ b: inout Int) {
let temporaryA = a
a = b
b = temporaryA
}
This function makes use of in-out parameters to swap the values of a
and b, as described in In-Out Parameters.
The swapTwoInts(::) function swaps the original value of b into a,
and the original value of a into b. You can call this function to swap
the values in two Int variables:
var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt)
print("someInt is now \(someInt), and anotherInt is now \(anotherInt)")
// Prints "someInt is now 107, and anotherInt is now 3" The
swapTwoInts(::) function is useful, but it can only be used with Int
values. If you want to swap two String values, or two Double values,
you have to write more functions, such as the swapTwoStrings(::) and
swapTwoDoubles(::) functions shown below:
func swapTwoStrings(_ a: inout String, _ b: inout String) {
let temporaryA = a
a = b
b = temporaryA
}
func swapTwoDoubles(_ a: inout Double, _ b: inout Double) {
let temporaryA = a
a = b
b = temporaryA
}
My question:
Instead of using generics function we could have just used Any type as the argument type right, that will simple as this
func swapTwoInts(_a:inout Any,_b:inout Int){
let temporaryA = a
a = b
b = temporaryA
}
So how to plays important role in swift?
Can I write code without generics like this
var num = 3
var numtwo = 5
print(num)
print(numtwo)
func swap(_ a: inout Any, _ b: inout Any){
let tempA=a
a=b
b=tempA
}
swap(a: &num, b: &numtwo)
In swift, you can assign value to a variable ONLY if the type of the variable is same with the value. So imagine you have this:
var a = 1
var b = 2
func swapTwoValues(_ a: inout Any, _ b: inout Any) {
let temporaryA = a
a = b
b = temporaryA
}
swapTwoValues(&a, &b) // <- Cannot pass immutable value as inout argument: implicit conversion from 'Int' to 'Any' requires a temporary
So compiler forces you to implicitly assign Any for the type of the variables. This is not what you want I think. So you have to tell the compiler that it doesn't matter the type of the arguments. The only thing matters is they both have same type to fulfill compilers need. So to achieve this, you can use generic or some kind of protocol.
func swapTwoValues<T>(_ a: inout T, _ b: inout T) {
let temporaryA = a
a = b
b = temporaryA
}
swapTwoValues(&a, &b) // Done
Tip: You can swap values with tuple in single line of code without using temporaryVar like this: (Even without function and generic and etc.)
(a, b) = (b, a)

Anonymous function with no curly braces and no argument labels?

I saw some code on another question that seems to create an anonymous function (closure expression) with some unusual syntax:
let plus: (Int, Int) -> Int = (+)
I understand the left side—that it's declaring a constant of type (Int, Int) -> Int (a function that takes two Integers and returns an Integer). But what is (+)? How can it declare a function without curly brackets, and how does it refer to the two arguments when there are no argument labels of any kind?
The function takes two arguments, adds them together, and returns the result. If I replace the + operator with a different one (say a *), the operation changes. So is it some kind of shorthand for {$0 + $1}? If so, what is the logic behind this shorthand?
Actually, this is no shorthand.
plus is a variable of type (Int, Int) -> Int. You can assign it any object that is of this type (or any of its subtypes). A literal lambda closure is certainly of this type, but actually a named function or method would also do. And that is exactly what is happening here.
It is assigning the operator method object named + to the variable.
This is mentioned sort-of implicitly in the Closures chapter of the language guide:
Operator Methods
There’s actually an even shorter way to write the closure expression above. Swift’s String type defines its string-specific implementation of the greater-than operator (>) as a method that has two parameters of type String, and returns a value of type Bool. This exactly matches the method type needed by the sorted(by:) method. Therefore, you can simply pass in the greater-than operator, and Swift will infer that you want to use its string-specific implementation:
reversedNames = names.sorted(by: >)
So, what the code is doing is assigning the Operator Method + to the variable plus. + is simply the name of the function assigned to the variable. No magic shorthand involved.
Would you be surprised to see this?
let plus: (Int, Int) -> Int = foo
+ is an infix operator and a function name in Swift. There are many such functions defined on many types (it is overloaded).
You can define + for your own custom type. For example:
struct Foo {
var value: Int
static func +(_ lhs: Foo, _ rhs: Foo) -> Foo {
return Foo(value: lhs.value + rhs.value)
}
}
var f1 = Foo(value: 5)
var f2 = Foo(value: 3)
let f3 = f1 + f2
print(f3.value) // 8
This works:
let plus: (Int, Int) -> Int = (+)
because the signature of the + function has been fully specified, so Swift is able to identify the correct + function.
And if we want to assign our new + function to plus:
let plus: (Foo, Foo) -> Foo = (+)
It's really no different than this:
func add(_ a: Int, _ b: Double) -> Double {
return Double(a) + b
}
let plus: (Int, Double) -> Double = add
print(plus(3, 4.2)) // 7.2
So why the parentheses? Why specify (+) instead of just +?
+ is also a unary operator in Swift.
For example, you can say:
let x = +5
So just trying to say:
let plus: (Int, Int) -> Int = +
confuses the compiler because it is treating the + as a unary prefix operator and it is expecting the + to be followed by something else such as 5. By surrounding it with parentheses, the Swift compiler then stops trying to parse + as a unary operator and treats is just as its function name. Even if + weren't a unary prefix operator, Swift would still be expecting values on either side of the +, so the parentheses tell Swift that you aren't providing any inputs to the function, but just want the function itself.
You can refer to the + function without the parentheses in situations where it isn't ambiguous. For example:
var arr = [1, 2, 3]
let sum = arr.reduce(0, +)
(+) by itself is an operator method. You can declare your own operator like this:
precedencegroup CompositionPrecedence {
associativity: left
higherThan: AssignmentPrecedence
}
infix operator •: CompositionPrecedence
func •(a: Int, b: Int) -> Int {
return a + b
}
Usage will be the same:
var closure: (Int, Int) -> Int = (•)
print("\(closure(1, 2))")

Swift 3 Closure

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 }

Understanding why this Swift tuple assignment isn't allowed

The following code is fine:
func intTest() -> Int? {
var res : Int
res = 5
return res
}
There is no problem returning a non-optional Int from a method with a return type of optional Int.
Now lets see what happens when the return value is a tuple of optional values:
func tupleTest() -> (Int?, Int?) {
var res : (Int, Int)
res = (5, 5)
return res
}
The return res line results in the error:
error: cannot express tuple conversion '(Int, Int)' to '(Int?, Int?)' (aka '(Optional, Optional)')
Why does Swift not allow this?
I certainly understand why this would be an error in the other direction (optional to non-optional) but why can't a tuple accept a non-optional value in the place of an optional when a non-tuple works fine?
I've seen Swift tuple to Optional assignment but that doesn't cover why you can't do the assignment, it just covers how to solve it.
The reason that's happening is because of a type mismatch. Consider the following case:
let myClosure: (Int) -> ()
let myOtherClosure: (Int?) -> ()
The type of myClosure is (Int) -> () while myOtherClosure is of type (Int?) -> () which makes them fundamentally different types, despite the similarity of the parameters. When Swift is looking at these two constants, it's evaluating the type as a whole, not the individual pieces. The same is happening with your tuple; it's looking at the tuple type signature as a whole unit, not breaking down the parameters and recognizing that they're non-optional versions of the same type.
Converting from Int to Int? works because they're the same type, one is just an optional. Going from (Int, Int) to (Int?, Int?) doesn't because the parameters of the tuple are different therefore causing the overall type to be different, hence your error.
Taking a look at one of your examples:
func tupleTest() -> (Int?, Int?) {
let first: Int = 1
let second: Int = 2
let res: (Int?, Int?) = (first, second)
return res
}
This works because even though the values are non-optional integers, the tuple type is marked as (Int?, Int?) whereas:
func tupleTest() -> (Int?, Int?) {
let first: Int = 1
let second: Int = 2
let res = (first, second)
return res
}
doesn't compile because now res is of type (Int, Int). I'm not an expert on the Swift compiler but my guess is that the way the type system works is it doesn't deconstruct each individual part of a function or a tuple and recognize that the corresponding return parameter is the same type, just an optional.

Swift higher order function (Church pair aka cons) with generic parameter types not accepting input parameter types

I was messing around with the functional programming in Swift 2.1, trying to implement the Church encoding pair/cons function (cons = λx λy λf f x y in untyped lambda calculus), which I had read couldn't be done in earlier versions of Swift.
With generics it looks like
func cons<S,T,U>(x:S,_ y:T) -> ((S,T) -> U) -> U
{
return { (f:((S,T) -> U)) -> U in return f(x,y)}
}
cons(1,2)
//error: cannot invoke 'cons' with an argument list of type '(Int, Int)'
//note: expected an argument list of type '(S, T)'
which doesn't work, and gives an error I cannot understand (surely parameter list of type (Int,Int) can match generic type variables (S,T)?)
If you get rid of the generic types, and declare them all Ints, the function works, but of course we want to be able to cons together lists longer than 2; consing a list of length 3 is consing an Int with an (Int,Int) -> Int, for example.
Another option is to type everything as Any (see Type Casting for Any and AnyObject), but I couldn't make that work either.
Do you have any ideas? Is this possible in Swift yet? I'm sure there are simpler ways to implement cons/car/cdr, but I'm specifically interested in the Church encoding, where the list elements are arguments to anonymous functions (lambdas).
func cons<S,T,U>(x:S,_ y:T) -> ((S,T) -> U) -> U
{
return { (f:((S,T) -> U)) -> U in return f(x,y)}
}
let i: ((Int,Int)->Int)->Int = cons(1,2)
let d: ((Int,Int)->Double)->Double = cons(2,3)
let e: ((Double,Int)->String)->String = cons(2.2, 1)
let e: ((Double,Int)->Double)->Double = cons(2.2, 1)
stil one of type is an 'extra' type and could not be inferred by compilator. if you define the types, you can see, that not all combinations are valid. Just define the output type and the compilator should be happy
func cons<S,T, U>(x:S,_ y:T, outptAs: U.Type) -> ((S,T) -> U ) -> U
{
return { (f:((S,T) -> U)) -> U in return f(x,y) }
}
let i = cons(1.2 ,"A", outptAs: Int.self)
let j = cons("alfa","beta", outptAs: Double.self)