Can we overload = (assignment operator) in swift? [duplicate] - swift

I would like to override the '=' operator for a CGFloat like the follow try :
func = (inout left: CGFloat, right: Float) {
left=CGFloat(right)
}
So I could do the following:
var A:CGFloat=1
var B:Float=2
A=B
Can this be done ? I get the error Explicitly discard the result of the closure by assigning to '_'

That's not possible - as outlined in the documentation:
It is not possible to overload the default assignment operator (=). Only the compound assignment operators can be overloaded. Similarly, the ternary conditional operator (a ? b : c) cannot be overloaded.
If that doesn't convince you, just change the operator to +=:
func +=(left: inout CGFloat, right: Float) {
left += CGFloat(right)
}
and you'll notice that you will no longer get a compilation error.
The reason for the misleading error message is probably because the compiler is interpreting your attempt to overload as an assignment

You can not override assignment but you can use different operators in your case. For example &= operator.
func &= (inout left: CGFloat, right: Float) {
left = CGFloat(right)
}
So you could do the following:
var A: CGFLoat = 1
var B: Float = 2
A &= B
By the way operators &+, &-, &* exist in swift. They represent C-style operation without overflow. More

This is not operator overload approach. But the result may be what you are expecting
// Conform to `ExpressibleByIntegerLiteral` and implement it
extension String: ExpressibleByIntegerLiteral {
public init(integerLiteral value: Int) {
// String has an initializer that takes an Int, we can use that to
// create a string
self = String(value)
}
}
extension Int: ExpressibleByStringLiteral {
public init(stringLiteral value: String) {
self = Int(value) ?? 0
}
}
// No error, s2 is the string "4"
let s1: Int = "1"
let s2: String = 2
print(s1)
print(s2)
print(s1 + 2)

Related

Is it possible to use kotlin infix functions and swift infix operators the same way (with equal naming)?

I have a infix function in kotlin that can be called like this:
"name" eq "XY"
Now I am trying to do the same in swift. I already thought I could do it like the following, but that doesn't seem to be working:
class Condition {
var left: String = ""
var center: String = ""
var right: String = ""
init(left: String, center: String, right: String) {
self.left = left
self.center = center
self.right = "\(right)"
}
var toString: String {
return "\(left) \(center) \(right)"
}
}
func eq(field: String, value: String) -> Condition {
return Condition(left: field, center: "=", right: value)
}
infix operator eq
func eq(lhs: String, rhs: String) -> Condition {
return eq(field: lhs, value: rhs)
}
print(("name" eq "XY").toString)
error: 'eq' is considered to be an identifier, not an operator
infix operator eq
Is there a way to get this working?
Since I am not finding any solution, I will do it like the following:
I won't use kotlin infix functions. On Swift-side I'll write String extensions.
This way I can use the function on both sides like this:
("name".eq("XY")).toString
If anybody knows something cleaner, let me know :)

Custom operator function for mathematic operation in Swift

I want define a new function for Int, which I can do the same job like +, the function name is plus, as far as I see in the codes, I made no mistake but I believe I have to take some more steps that Swift accept this function as a math function, Swift throw me compiler error like this: can not find "plus"
need help for overcome to issue, thanks.
extension Int {
static func plus (lhs: Int, rhs: Int) -> Int {
return lhs + rhs
}
}
use case:
let value: Int = 1 plus 2
ps: I know that plus is under group of Int, but I want it be accessible alone.
You can use symbols to override operators like following. But you need to define precedencegroup first and then create infix operator. Infix operator works with left hand side and right hand side.
precedencegroup SumOperatorPrecedence {
lowerThan: MultiplicationPrecedence
higherThan: AdditionPrecedence
associativity: left
assignment: false
}
infix operator *&:SumOperatorPrecedence
extension Int {
static func *&(lhs: Int, rhs: Int) -> Int {
return lhs + rhs
}
}
let f = 2 *& 3
If you want to add a number with itself, then you can do this:
extension Int {
func plus (rhs: Int) -> Int {
return self + rhs
}
}
Now, you can call it on any Integer. Like:
2.plus(rhs: 10) // prints 12

Is it possible to define [Int] * Int using custom operator in Swift?

I want to define a new operator and multiply each element of the array [Int] by Int, such as [3, 2, 10] * 10.
However, because Int is neither protocol nor class (it's struct), I first defined the following:
protocol Numeric {}
extension Int: Numeric {}
extension Double: Numeric {}
extension Float: Numeric {}
And then, I tried defining the operator, like:
func *<T: Numeric> (left: [T], right: T) -> [T] {
var newArray: [T] = []
for i in left {
newArray.append(i * right)
}
return newArray
}
However, this spits out an error: Cannot convert value of type 'T' to expected argument type '[_]'.
I'm not sure what the type [_] means, which I don't expect, but I guess the problem comes from that I don't have an operator defined that takes T and T, both of which are Numeric in this case.
So I defined another operator, like:
func *<T: Numeric> (left: T, right: T) -> T {
return left * right
}
However, while this has been compiled without problems, the runtime error occurred with a lot of a lot of static * infix <A where ...> (A, A) -> A.
I'm not sure why this operator was executed so many times, but now I wonder if it is possible in the first place to define a custom * operator, although the Int does already have * operator defined.
So is it still possible to define [Int] * Int operator in Swift?
You have to require the multiplication operation in the Numeric
protocol:
protocol Numeric {
func *(lhs: Self, rhs: Self) -> Self
}
Otherwise the multiplication in newArray.append(i * right) is
not defined.
Your
func *<T: Numeric> (left: T, right: T) -> T {
return left * right
}
(which calls itself recursively, resulting in a stack overflow) is then not needed.
The implementation of your new operator itself can be simplified
(as already described in a now deleted answer) to
func *<T: Numeric> (left: [T], right: T) -> [T] {
return left.map { $0 * right }
}

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

Swift's pow() function won't accept Doubles as arguments

I created this infix operator ^^ as a substitute to using the pow function:
infix operator ^^ { associativity left precedence 155 }
func ^^ <T: IntegerLiteralConvertible>(left: T, right: T) -> T {
return pow(left as Double, right as Double)
}
I used the IntegerLiteralConvertible protocol as a type constraint for the generics left and right, because from my understanding this diagramm shows, that it basically includes all number types.
In order to use the pow function I have to downcast left and right to Double though, which I did using the as operator. It's not the safest approach, but that's besides the point.
When implementing the function this way swift tells me:
<stdin>:4:12: error: cannot invoke 'pow' with an argument list of type '(Double, Double)'
return pow(left as Double, right as Double)
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Now as far as I know pow takes two Doubles as parameters, so why is it complaining about this?
why is it complaining about this?
Because pow returns Double. And Double is not identical to T. The error message is misleading, but it means "Cannot find pow that accepts (Double, Double) and returns T type"
I think you are misunderstanding "cast" in Swift. In Swift as does not convert numeric types.
let intVal:Int = 12
let doubleVal:Double = intVal as Double
// ^ [!] error: 'Int' is not convertible to 'Double'
And If the type of operand is not predictable at compile time, invalid casting causes runtime error:
func foo<T: IntegerLiteralConvertible>(x: T) {
x as Double // <-- Execution was interrupted
}
foo(12 as Int)
Instead, we must explicitly "convert" them. see the document: Numeric Type Conversion
let intVal:Int = 12
let doubleVal:Double = Double(intVal)
This works only because Double has init(_ v: Int) initializer. The following code does not compile:
func foo<T: IntegerLiteralConvertible>(x: T) {
Double(x)
// ^~~~~~~~~ [!] error: cannot invoke 'init' with an argument of type 'T'
}
Because Double does not have init<T:IntegerLiteralConvertible>(_ val:T) initializer.
So, if you want to use pow(), you must convert T to Double for arguments, and convert Double to T for returning value. And there is no simple solution for that.
Thanks #Martin R. This comes from the only question I have posted so far at S.O.
import Cocoa
Protocols
protocol Fraction { init(_ value:Double) ; var asDouble : Double { get } }
protocol Text { init(_ value:String) ; var asString : String { get } }
Extensions
extension String : Text { var asString : String { return self } }
extension Double : Fraction { var asDouble : Double { return self } }
extension Float : Fraction { var asDouble : Double { return Double(self) } }
extension CGFloat : Fraction { var asDouble : Double { return Double(self) } }
infix operator ^^
infix operator ^^ { associativity left precedence 170 }
func ^^<T:IntegerType, U:IntegerType> (var base:T, var power:U) -> T {
if power < 0 { return 0 }
var result: T = 1
if power > 0 {
if power % 2 == 1 { result *= base }
power /= 2
}
while power > 0 {
base *= base
if power % 2 == 1 { result *= base }
power /= 2
}
return result
}
func ^^<T:Fraction, U:Fraction> (base: T, power: U) -> T {
return T(pow(base.asDouble, power.asDouble))
}
func ^^<T:Text, U:IntegerType> (base:T, var power:U) -> T {
if power <= 0 { return "" as T }
if power == 1 { return base as T }
return power > 1 ? {var result = ""; for x in 1...power { result+=base.asString };return result as T}() : "" as T
}
func ^^<T:Text, U:Text> (base:T, var power:U) -> T {
return "" as T
}
testing
println(1 ^^ -1) // "0" Int
println(1 ^^ 0) // "1" Int
println(1 ^^ 1) // "1" Int
println(1 ^^ 2) // "1" Int
println(2 ^^ -1) // "0" Int
println(2 ^^ 0) // "1" Int
println(2 ^^ 1) // "2" Int
println(2 ^^ 2) // "4" Int
println(2 ^^ 8) // "256" Int
println(2 ^^ 16) // "65536" Int
println(2 ^^ 32) // "4294967296" Int
println(2 ^^ 62) // "4611686018427387904"
println(UInt(2) ^^ 8) // "256" UInt
println(UInt64(2) ^^ 8) // "256" UInt64