Type Error in Swift :Cannot convert value of type '[UInt64]' to expected argument type 'inout UInt64' - swift

New to Swift, I'm getting this error:
Cannot convert value of type '[UInt64]' to expected argument type 'inout UInt64'
I don't understand the "inout" typing
/// non crypto hash
func strHash(_ str: String) -> UInt64 {
var result = UInt64 (5381)
let buf = [UInt8](str.utf8)
for b in buf {
result = 127 * (result & 0x00ffffffffffffff) + UInt64(b)
}
return result
}
let myString: String = "Hello World"
let words = myString.components(separatedBy: " " )
print(words)
var hashArry = [UInt64]()
for w in words {
hashArry += strHash(w) // <<<<<<<<< Here
}

Well, you cannot use += as you might have expected.
Use
hashArray.append(strHash(w))
instead. And do not wonder about the sometimes very confusing compiler error messages :-)

Related

How to prove "copy-on-write" on String type in Swift

As the title said, I tried to prove myself that COW(copy on write) is supported for String in Swift. But I cannot find a proof. I proved the COW on Array and Dictionary after trying the following codes:
func address(of object: UnsafeRawPointer) -> String {
let addr = Int(bitPattern: object)
return String(format: "%p", addr)
}
var xArray = [20, 30, 40, 50, 60]
var yArray = xArray
// These two addresses were the same
address(of: xArray)
address(of: yArray)
yArray[0] = 200
// The address of yArray got changed
address(of: yArray)
But for String type, it was not working.
var xString = "Hello World"
var yString = xString
// These two addresses were different
address(of: xString)
address(of: yString)
And I dumped the test function from the official Swift code repo.
func _rawIdentifier(s: String) -> (UInt, UInt) {
let tripe = unsafeBitCast(s, to: (UInt, UInt, UInt).self)
let minusCount = (tripe.0, tripe.2)
return minusCount
}
But this function seems to only cast the actual value pointed to not the address. So two different String variables with the same value would have the same rawIdentifier. Still cannot prove COW to me.
var xString = "Hello World"
var yString = "Hello" + " World"
// These two rawIdentifiers were the same
_rawIdentifier(s: xString)
_rawIdentifier(s: yString)
So how does COW work on String type in Swift?
The compiler creates only a single storage for both
"Hello World" and "Hello" + " World".
You can verify that for example by examining the assembly code
obtained from
swiftc -emit-assembly cow.swift
which defines only a single string literal
.section __TEXT,__cstring,cstring_literals
L___unnamed_1:
.asciz "Hello World"
As soon as the string is mutated, the address of the string storage
buffer (the first member of that "magic" tuple, actually _baseAddress
of struct _StringCore, defined in StringCore.swift) changes:
var xString = "Hello World"
var yString = "Hello" + " World"
print(_rawIdentifier(s: xString)) // (4300325536, 0)
print(_rawIdentifier(s: yString)) // (4300325536, 0)
yString.append("!")
print(_rawIdentifier(s: yString)) // (4322384560, 4322384528)
And why does your
func address(of object: UnsafeRawPointer) -> String
function show the same values for xArray and yArray, but
not for xString and yString?
Passing an array to a function taking a unsafe pointer passes the
address of the first array element, that is the same for both
arrays if they share the storage.
Passing a string to a function taking an unsafe pointer passes a
pointer to a temporary UTF-8 representation of the string.
That address can be different in each call, even for the same string.
This behavior is documented in the "Using Swift with Cocoa and
Objective-C" reference for UnsafePointer<T> arguments, but apparently
works the same for UnsafeRawPointer arguments.

Type 'String.CharacterView.IndexDistance' (aka 'Int') does not conform to protocol 'Sequence'

I am attempting to make a morse code converter in a Swift 3 playground. The function I am using does not successfully initiate the translation process, saying "Type 'String.CharacterView.IndexDistance' (aka 'Int') does not conform to protocol 'Sequence'".
func convertStringToMorse(_ input: String) -> String {
let stringToConvert = input
var charsInString = input.characters.count
var returnString = ""
for char in charsInString {
let returnChar = convertLetterToMorse(char)
if returnChar != "" {
returnString += returnChar + " "
}
}
return returnString
}
The error happens in the for char in charsInString line, specifically at charsInString. How do I fix this?
Delete the .count.
input.characters.count is an Int representing the number of characters.
input.characters represents the sequence of characters.
You can't use an Int in a for-in loop. You would need a collection or sequence.

String index in Swift 2.0: How can I work around indexing a string?

I am trying to get the contents of a string:
var oldString = "hi this \t is my \t string"
oldString = String(oldString.componentsSeparatedByString("\t"))
print(oldString[1])
I get the ERROR : " 'subscript' is unavailable:cannot subscript String
with an Int..."
How would I access a string that is contained in another string?
The only way I have come up with is to get character by character using:
for index in content.characters.indices{
print(String(oldString[index]))
}
The code above results in:
h,
i,
t,
h,
..
I need:
hi this,
is my,
string
Thank you in advance!
You should read the error message and figure out where does the error message come from.
Your String(oldString.componentsSeparatedByString("\t")) gives you a String not [String].
What you need to do is assigning oldString.componentsSeparatedByString("\t") to an array:
let stringArray = oldString.componentsSeparatedByString("\t")
for str in stringArray {
print(str)
}
In swift you can extend any type and add overloads for different operations. In the example below we've created an extension that allows you to subscript String returning each word and get an array from your string.
Simply paste this into a playground to test:
extension String {
func array() -> [String] {
return self.componentsSeparatedByString("\t")
}
subscript (i: Int) -> String {
return self.componentsSeparatedByString("\t")[i]
}
}
Once you've added your extension, you can use it throughout your application like so:
var str = "hi this \t is my \t string"
print(str[0]) //prints hi this
for i in str.array() {
print(i)
}
prints:
hi this
is my
string
var oldString = "hi this \t is my \t string"
let stringArray = oldString.componentsSeparatedByString("\t")
//In case you also need the index while iterating
for (index, value) in stringArray.enumerate(){
print("index is \(index) and string is \(value)")
}
for str in stringArray{
print(str)
}
Output will be as follows
index is 0 and string is hi this
index is 1 and string is is my
index is 2 and string is string
hi this
is my
string

Swift: Subscript with Ranges error

I am playing with subscripts in Swift, following the book "Mastering Swift 2":
// SUBSCRIPTS WITH RANGES
struct MathTableWithRanges{
var num : Int
subscript(index : Int)->Int{
return num * index
}
subscript(aRange: Range<Int>)->[Int]{
var retArray : [Int] = []
for i in aRange{
retArray.append(self[i])
}
return retArray
}
}
// Test code
var table = MathTable(num: 5)
var myRange : Range<Int> = 2...5
print(table[myRange])
Expected output: 10,15, 20, 25
Error: Cannot convert value of type Range to expected argument type Int
Note: If I hard code the Range:
print(table[2...5])
I get a different error:
Binary operator '...' cannot be applied to two Int operands
I haven't got the book you are using, but this line:
var table = MathTable(num: 5)
Should probably be this:
var table = MathTableWithRanges(num: 5)

Swift Optional Type Syntax

According to Apple's Swift guide, when you have the following Array and the following function to search through an Array:
let namesArray = ["John", "Lisa", "Bill", "Jennifer"]
// Note this function is set-up to return an OPTIONAL Int:
func findName (personName:String, arrayToSearchIn:String[]) -> Int? {
for (indexOfName, nameValue) in enumerate(arrayToSearchIn) {
if nameValue == personName {
return indexOfName
}
}
return nil
}
...so you can capture the Optional Int returned by this function - and then check to see if its nil or not - in the following manner:
let nameIndex: Int? = findName("Lisa", arrayToSearchIn: namesArray)
if nameIndex {
println("found \(namesArray[nameIndex!])")
}
else {
println("NOT found")
}
This is all good - but their next example, in which they streamline the code by collapsing the 2 statements into one - confuses me because they suddenly drop the Optional "?" and "!" from their syntax:
if let nameIndex = findName("Lisa", arrayToSearchIn: namesArray) {
println("found \(namesArray[nameIndex])")
}
And this works perfectly well.
So why is it that in the first example nameIndex was declared with a "?" - like so:
nameIndex:Int?
and the forced-unwrapping occurs using a "!"
[nameIndex!]
but in the second example neither "?" or "!" one is used in the syntax?
The handling of the declaration in an if let is special; one should treat it as its own language construct (not as a simple combination of if and let). In
if let nameIndex = findName("Lisa", arrayToSearchIn: namesArray) {
println("found \(namesArray[nameIndex]")
}
the type of nameIndex does not need to be expressed because it can be inferred as the return type of findName() which is Int?. In the body of the if let ... the value of nameIndex is not bound to an optional and thus unwrapping is not needed - the value will be an Int.
Here is an example of how the if let binding is treated. Notice that an explicit declaration of the type is essentially ignored:
> func test () -> Int? { return 111 }
> if let x : Int? = test () { return x }
$R6: Int? = 111
> if let x : Int = test () { return x }
$R7: Int = 111
> if let x = test () { return x }
$R8: Int = 111
but if you try to be so 'flexible' outside of an if let, you draw an error from the compiler:
> let y : Int = test ()
<REPL>:33:15: error: value of optional type 'Int?' not unwrapped;
did you mean to use '!' or '?'?
? is the operator to explicitly declare an optional type. ! is the operator to force-unwrap an optional. The syntax in the example is a special Swift shorthand for checking and unwrapping in one concise line. It says, “assign nameIndex to the result of findName(...), and if it is not nil, run the following code: ...”