How to Declare Exponent/Power Operator with New Precedencegroup in Swift 3

How to declare exponent/power operator with new precedencegroup in Swift 3?

Your code already compiles and runs – you don't need to define a precedence relationship or an associativity if you're simply using the operator in isolation, such as in the example you gave:

10 ^^ -12
10 ^^ -24

However, if you want to work with other operators, as well as chaining together multiple exponents, you'll want to define a precedence relationship that's higher than the MultiplicationPrecedence and a right associativity.

precedencegroup ExponentiativePrecedence {
associativity: right
higherThan: MultiplicationPrecedence
}

Therefore the following expression:

let x = 2 + 10 * 5 ^^ 2 ^^ 3

will be evaluated as:

let x = 2 + (10 * (5 ^^ (2 ^^ 3)))
// ^^ ^^ ^^--- Right associativity
// || \--------- ExponentiativePrecedence > MultiplicationPrecedence
// \--------------- MultiplicationPrecedence > AdditionPrecedence,
// as defined by the standard library

The full list of standard library precedence groups is available on the evolution proposal.

Defining Exponent operator

You have to import the module where the function pow is defined:

import Foundation

Exponentiation operator in Swift

There isn't an operator but you can use the pow function like this:

return pow(num, power)

If you want to, you could also make an operator call the pow function like this:

infix operator ** { associativity left precedence 170 }

func ** (num: Double, power: Double) -> Double{
return pow(num, power)
}

2.0**2.0 //4.0

Swift3 : how to handle precedencegroup now operator should be declare with a body?

As per SE-0077, the precedence of an operator is no longer determined by a magic number – instead you now use the higherThan and (if the group resides in another module) lowerThan precedencegroup relationships in order to define precedence relative to other groups.

For example (from the evolution proposal):

// module Swift
precedencegroup Additive { higherThan: Range }
precedencegroup Multiplicative { higherThan: Additive }

// module A
precedencegroup Equivalence {
higherThan: Comparative
lowerThan: Additive // possible, because Additive lies in another module
}
infix operator ~ : Equivalence

1 + 2 ~ 3 // same as (1 + 2) ~ 3, because Additive > Equivalence
1 * 2 ~ 3 // same as (1 * 2) ~ 3, because Multiplicative > Additive > Equivalence
1 < 2 ~ 3 // same as 1 < (2 ~ 3), because Equivalence > Comparative
1 += 2 ~ 3 // same as 1 += (2 ~ 3), because Equivalence > Comparative > Assignment
1 ... 2 ~ 3 // error, because Range and Equivalence are unrelated

Although in your case, as it appears that your operator is used for multiplication, you could simply use the standard library's MultiplicationPrecedence group, which is used for the * operator:

infix operator × : MultiplicationPrecedence

It is defined as:

precedencegroup MultiplicationPrecedence {
associativity: left
higherThan: AdditionPrecedence
}

For a full list of standard library precedence groups, as well as more info about this change, see the evolution proposal.

Defining Exponent operator

You have to import the module where the function pow is defined:

import Foundation

How to get the Power of some Integer in Swift language?

If you like, you could declare an infix operator to do it.

// Put this at file level anywhere in your project
infix operator ^^ { associativity left precedence 160 }
func ^^ (radix: Int, power: Int) -> Int {
return Int(pow(Double(radix), Double(power)))
}

// ...
// Then you can do this...
let i = 2 ^^ 3
// ... or
println("2³ = \(2 ^^ 3)") // Prints 2³ = 8

I used two carets so you can still use the XOR operator.

Update for Swift 3

In Swift 3 the "magic number" precedence is replaced by precedencegroups:

precedencegroup PowerPrecedence { higherThan: MultiplicationPrecedence }
infix operator ^^ : PowerPrecedence
func ^^ (radix: Int, power: Int) -> Int {
return Int(pow(Double(radix), Double(power)))
}

// ...
// Then you can do this...
let i2 = 2 ^^ 3
// ... or
print("2³ = \(2 ^^ 3)") // Prints 2³ = 8

How do I make my exponentiation operator work with all numeric types in Swift?

Here is a more type-safe implementation, using operator overloading. For integer types,
you can define ^^ as

infix operator ^^ { associativity left precedence 170 }

func ^^<T : IntegerType, U : IntegerType> (base: T, var power: U) -> T {

if power < 0 { return 0 }

var result : T = 1
var square : T = base

if power > 0 {
if power % 2 == 1 { result *= square }
power /= 2
}
while power > 0 {
square *= square
if power % 2 == 1 { result *= square }
power /= 2
}

return result
}

(I have chosen a more efficient variant called "exponentiation by repeated squaring and multiplication".)

For floating point types, define a protocol the covers all types that can be
converted from and to Double:

protocol DoubleConvertible {
init(_ value: Double)
var doubleValue : Double { get }
}

and make Float, Double and CGFloat conform to that protocol:

extension Double : DoubleConvertible {
var doubleValue : Double { return self }
}

extension Float : DoubleConvertible {
var doubleValue : Double { return Double(self) }
}

extension CGFloat : DoubleConvertible {
var doubleValue : Double { return Double(self) }
}

Now the floating point exponentiation can simply be defined as

func ^^<T : DoubleConvertible, U:DoubleConvertible> (base: T, power: U) -> T {

return T(pow(base.doubleValue, power.doubleValue))
}

Examples:

let x1 = 2^^3               // Int
let x2 = UInt64(2)^^3 // UInt64
let x3 = 2.0 ^^ 3 // Double
let x4 = Float(2.0) ^^ 3 // Float
let x5 = "a" ^^ "b" // Compiler error

Update for Swift 4:

IntegerType has become BinaryInteger (SE-0104 Protocol-oriented integers) and
the syntax for declaring operators has changed
(SE-0077 Improved operator declarations.)

Here is an implementation for all integer and floating point
bases with Int exponents:

precedencegroup ExponentiationPrecedence { associativity: right higherThan: MultiplicationPrecedence }
infix operator ^^: ExponentiationPrecedence

func ^^<T : BinaryInteger>(base: T, power: Int) -> T {
if power < 0 { return 0 }
var power = power
var result: T = 1
var square = base

if power > 0 {
if power % 2 == 1 { result *= square }
power /= 2
}
while power > 0 {
square *= square
if power % 2 == 1 { result *= square }
power /= 2
}
return result
}

func ^^(base: Float, power: Int) -> Float {
return pow(base, Float(power))
}

func ^^(base: Double, power: Int) -> Double {
return pow(base, Double(power))
}

func ^^(base: CGFloat, power: Int) -> CGFloat {
return pow(base, CGFloat(power))
}

Examples:

let x1 = 2^^3            // Int
let x2 = UInt64(2)^^3 // UInt64
let x3 = 2.0 ^^ -3 // Double
let x4 = Float(2.0) ^^ 3 // Float
// let x6 = "a" ^^ 5 // Compiler error

See SE-0104 Protocol-oriented integers
about the new protocol hierarchy introduced in Swift 4.

Can I make a Swift data type infix operator?

You could do this with generics:

struct MyStruct<T>
{
var someNum: T
}

You can then explicitly state the dataType you wish to use by specifying the type on creation: let a = MyStruct<Int>(someNum: 4).

One thing Swift does that makes this all absolutely beautiful is derive the data type from the constructor, so you can also just do this:

let intStruct   = MyStruct(someNum: 4)
let floatStruct = MyStruct(someNum: 5.0)

Precedence group higher than closure

We first set up a complete and verifiable example:

precedencegroup LongArrowPrecedence {
associativity: left
higherThan: AssignmentPrecedence
}

infix operator --> : LongArrowPrecedence

func -->(lhs: Int, rhs: Int) -> (() -> ()) -> () {
return { print(lhs+rhs, terminator: ""); $0() }
}

As well as examples of the paranthesis-embraced valid calls using this operator, immediately followed by a call to the closure which --> returns.

let foo = 1
let bar = 2

// OK
(foo --> bar) {
print(" is the magic number")
} // 3 is the magic number

// OK
((-->)(foo, bar)) {
print(" is the magic number")
} // 3 is the magic number

This doesn't tell us much, but if we study the following failing cases

// ERROR: cannot call value of non-function type 'Int'
foo --> bar {
print(" is the magic number")
} // 3 is the magic number

// ... equivalent to
// ERROR: cannot call value of non-function type 'Int'
foo --> bar({
print(" is the magic number")
}) // 3 is the magic number

We realize that the issue here is not "precedence lower than a closure", but rather that a function-call-argument-clause (a set of parantheses following any postfix-expression­) will attempt a call to that postfix-expression­, as if the postfix-expression was a method/function/closure. If the postfix-expression is not callable, or if the call within the function-call-argument-clause does not match any overload of the callable, then the compiler will produce an error.

42()           // ERROR: cannot call value of non-function type 'Int'
let foo = 42
foo() // ERROR: cannot call value of non-function type 'Int'

func bar() {} // ERROR: argument passed to call that takes no arguments
bar(42)

Hence, the trailing closure supplied to the closure returned from --> is not relevant here: it's simply an argument to the returned closure, whereas the key issue is that Swift will apply a function-call-argument-clause to the postfix-expression­ which immediately precedes the clause. In you example, bar constitutes that postfix expression, and only if you wrap foo --> bar in parantheses will the combined wrapped expression constitute the postfix-expression­ onto which the following function-call-argument-clause is applied.

Postfix Expressions

Postfix expressions are formed by applying a postfix operator or other
postfix syntax to an expression. Syntactically, every primary
expression is also a postfix expression.

Primary Expressions

Primary expressions are the most basic kind of expression. They can be
used as expressions on their own, and they can be combined with other
tokens to make prefix expressions, binary expressions, and postfix
expressions.

You will not be able to circumvent this, as operator precedence is not applicable to the function-call-argument-clause; the latter (and its "precedence") is defined by the grammar of a function call expression.



Related Topics



Leave a reply



Submit