Is there a reason why the shift operators (>> and <<) don't work on BitwiseOperationsType? - swift

I was thinking of making an integer power function in Swift based on this StackOverflow answer:
func **<T : IntegerType>(var base: T, var exponent: T) -> T {
var result: T = 1
assert(exponent >= 0, "Exponent cannot be negative")
while exponent > 0 {
if exponent & 1 != 0 {
result *= base
}
exponent = exponent >> 1
base *= base
}
return result
}
I figured I could use generics to implement the function so that it would work with any integer type.
Unfortunately, I get an error when I attempt to use exponent >> 1:
Binary operator '>>' cannot be applied to two 'T' operands
Checking the function definitions for >>, I see that there is one for each of the ten integer types, but no other ones are defined. I was surprised therefore that all the other operators were working, such as &, but I noticed that & was actually defined to work on all types which conform to BitwiseOperationsType, which IntegerType appears to conform to.
Is there a reason why the >> and << operators are not implemented for BitwiseOperationsType?

Related

Is it possible to divide two numerics in swift?

func divtwoval<T: Numeric>(_a: T,_b: T){
let c = _a / _b
print(c)
}
I tried to divide two numeric generics but it doesent work.
I get this error message: error: binary operator '/' cannot be applied to two 'T' operands.
How do I divide this generics?
If you check the documentation of Numeric, it clearly shows its values only need to support multiplication.
The division operator (/) is defined on the BinaryInteger and FloatingPoint protocols separately, since they have different semantics, so you cannot divide any numeric types by each other.

operator or method in swift which work as walrus operator of python

walrus operator of python language ( := )
work:- assign the value & also return that value.
language like swift at value assign it return nothing.
how to implement walrus operator kind a thing in swift language ?
I think it done by make function, pass address of variable & value.
assign value in that address & return value.
Is this work or any other way for this?
Joakim is correct.
Swift doesn't have a unary operator like C.
In C, you could do:
b = 10;
while (b>0) {
print(b--);
}
In Swift, there isn't a unary ++ or -- operator, so you would do:
var b = 10
while (b > 0) {
print b
b -= 1
}
but, really, in Swift, you'd do this instead
for b in (0...10).reversed() {
print b
}
See Reverse Range in Swift

Binary operator '*' cannot be applied to operands of type 'Float' and 'Float!'

When I do the following:
let gapDuration = Float(self.MONTHS) * Float(self.duration) * self.gapMonthly;
I get the error:
Binary operator '*' cannot be applied to operands of type 'Float' and 'Float!'
But when I do:
let gapDuration = 12 * Float(self.duration) * self.gapMonthly;
Everything is working fine.
I have no Idea what this error is telling me.
self.gapMonthly is of type Float! and self.duration and self.MONTHS are of type Int!
I would consider this a bug (at the very least, the error is misleading), and appears to be present when attempting to use a binary operator on 3 or more expressions that evaluate to a given type, where one or more of those expressions is an implicitly unwrapped optional of that type.
This simply stretches the type-checker too far, as it has to consider all possibilities of treating the IUO as a strong optional (as due to SE-0054 the compiler will treat an IUO as a strong optional if it can be type-checked as one), along with attempting to find the correct overloads for the operators.
At first glance, it appears to be similar to the issue shown in How can I concatenate multiple optional strings in swift 3.0? – however that bug was fixed in Swift 3.1, but this bug is still present.
A minimal example that reproduces the same issue would be:
let a: Float! = 0
// error: Binary operator '*' cannot be applied to operands of type 'Float' and 'Float!'
let b = a * a * a
and is present for other binary operators other than *:
// error: Binary operator '+' cannot be applied to operands of type 'Float' and 'Float!'
let b = a + a + a
It is also still reproducible when mixing in Float expressions (as long as at least one Float! expression remains), as well as when explicitly annotating b as a Float:
let b: Float = a * a * a // doesn't compile
let a: Float! = 0
let b: Int = 0
let c: Int = 0
let d: Float = a * Float(b) * Float(c) // doesn't compile
A simple fix for this would be to explicitly force unwrap the implicitly unwrapped optional(s) in the expression:
let d = a! * Float(b) * Float(c) // compiles
This relieves the pressure on the type-checker, as now all the expressions evaluate to Float, so overload resolution is much simpler.
Although of course, it goes without saying that this will crash if a is nil. In general, you should try and avoid using implicitly unwrapped optionals, and instead prefer to use strong optionals – and, as #vadian says, always use non-optionals in cases where the value being nil doesn't make sense.
If you need to use an optional and aren't 100% sure that it contains a value, you should safely unwrap it before doing the arithmetic. One way of doing this would be to use Optional's map(_:) method in order to propagate the optionality:
let a: Float! = 0
let b: Int = 0
let c: Int = 0
// the (a as Float?) cast is necessary if 'a' is an IUO,
// but not necessary for a strong optional.
let d = (a as Float?).map { $0 * Float(b) * Float(c) }
If a is non-nil, d will be initialized to the result of the unwrapped value of a multiplied with Float(b) and Float(c). If however a is nil, d will be initialised to nil.

How to prevent this Cyclic polynomial hash function from using a type constraint?

I am trying to implement the Cyclic polynomial hash function in f#. It uses the bit-wise operators ^^^ and <<<. Here is an example of a function that hashes an array:
let createBuzhash (pattern : array<'a>) =
let n = pattern.Length
let rec loop index pow acc =
if index < n then
loop (index+1) (pow-1) (acc ^^^ ((int pattern.[index]) <<< pow))
else
acc
loop 0 (n-1) 0
My problem is that the type of 'a will be constrained to an int, while i want this function to work with any of the types that work with bit-wise operators, for example a char. I tried using inline, but that creates some problems farther down in my library. Is there a way to fix this without using inline?
Edit for clarity: The function will be part of a library, and another hash function is provided for types that don't support the bit-wise operators. I want this function to work with arrays of numeric types and/or chars.
Edit 2 (problem solved) : The problem with inline was the way how i loaded the function from my library. instead of
let hashedPattern = library.createBuzhash targetPattern
I used this binding:
let myFunction = library.createBuzhash
let hashedPattern = myFunction targetPattern
that constraints the input type for myFunction to int, although the createBuzhash function is an inline function in the library. Changing the way I call the function fixed the type constraint problem, and inline works perfectly fine, as the answer below suggests.
In the implementation, you are converting the value in the array to an Integer using the int function as follows: int pattern.[index]
This creates a constraint on the type of array elements requiring them to be "something that can be converted to int". If you mark the function as inline, it will actually work for types like char and you'll be able to write:
createBuzhash [|'a'; 'b'|]
But there are still many other types that cannot be converted to integer using the int function.
To make this work for any type, you have to decide how you want to handle types that are not numeric. Do you want to:
Provide your own hashing function for all values?
Use the built-in .NET GetHashCode operation?
Only make your function work on numeric types and arrays of numeric types?
One option would be to add a parameter that specifies how to do the conversion:
let inline createBuzhash conv (pattern : array<'a>) =
let n = pattern.Length
let rec loop index pow acc =
if index < pattern.Length then
loop (index+1) (pow-1) (acc ^^^ ((conv pattern.[index]) <<< pow))
else
acc
loop 0 (n-1) 0
When calling createBuzhash, you now need to give it a function for hashing the elements. This works on primitive types using the int function:
createBuzhash int [| 0 .. 10 |]
createBuzhash int [|'a'; 'b'|]
But you can also use built-in F# hashing mechanism:
createBuzhash hash [| (1,"foo"); (2,"bar") |]
And you can even handle nested arrays by passing the function to itself:
createBuzhash (createBuzhash int) [| [| 1 |]; [| 2 |] |]

Swift float multiplication error

This code fails:
let element: Float = self.getElement(row: 1, column: j)
let multiplier = powf(-1, j+2)*element
with this error:
Playground execution failed: :140:51: error: cannot invoke '*' with an argument list of type '(Float, Float)'
let multiplier = powf(-1, j+2)*element
Bear in mind that this occurs in this block:
for j in 0...self.columnCount {
where columnCount is a Float. Also, the first line does execute and so the getElement method indeed returns a Float.
I am completely puzzled by this as I see no reason why it shouldn't work.
There is no implicit numeric conversion in swift, so you have to do explicit conversion when dealing with different types and/or when the expected type is different than the result of the expression.
In your case, j is an Int whereas powf expects a Float, so it must be converted as follows:
let multiplier = powf(-1, Float(j)+2)*element
Note that the 2 literal, although usually considered an integer, is automatically inferred a Float type by the compiler, so in that case an explicit conversion is not required.
I ended up solving this by using Float(j) instead of j when calling powf(). Evidently, j cannot be implicitly converted to a Float.