DenseVector_Double

The example in the Swift documentation for DenseVector_Double:


var values = [2.20, 2.85, 2.79, 2.87]
let vector = DenseVector_Double(count: Int32(values.count),
data: &values)

stride(from: 0, to: vector.count, by: 1).forEach {i in
print(vector.data[Int(i)])
}


worked fine previously (prior to 5.2 I believe).


It now has a warning:

"Inout expression creates a temporary pointer, but argument 'data' should be a pointer that outlives the call to 'init(count:data:)'"


What would need to be done to fix the example and avoid the error message?

Accepted Reply

Yeah, as Claude31 says, the documentation is definitely wrong here.

DenseVector_Double
is a C structure containing a pointer and a count. When you set up a structure like this, you must ensure that the pointer is valid for the lifetime of the structure. Using
&
like this creates a pointer that only lasts for the duration of the call, which in this case is the structure’s initialiser.

The best way to fix this depends on how you’re using the data. For this simple example, you could write this:

var values = [2.20, 2.85, 2.79, 2.87]
values.withUnsafeMutableBufferPointer { buf in
    let vector = DenseVector_Double(
        count: Int32(buf.count),
        data: buf.baseAddress!
    )
    stride(from: 0, to: Int(vector.count), by: 1).forEach { i in
        print(vector.data[i])
    }
}

However, it’s likely that any real code would need something more complex.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Replies

5.2.1 mean Swift 5.2.1 ?


Would this provide a hint ?

https://stackoverflow.com/questions/60858060/byte-array-pointer-scope-in-swift


In such a case, you should file a bug against documentation which is misleading.

Yeah, as Claude31 says, the documentation is definitely wrong here.

DenseVector_Double
is a C structure containing a pointer and a count. When you set up a structure like this, you must ensure that the pointer is valid for the lifetime of the structure. Using
&
like this creates a pointer that only lasts for the duration of the call, which in this case is the structure’s initialiser.

The best way to fix this depends on how you’re using the data. For this simple example, you could write this:

var values = [2.20, 2.85, 2.79, 2.87]
values.withUnsafeMutableBufferPointer { buf in
    let vector = DenseVector_Double(
        count: Int32(buf.count),
        data: buf.baseAddress!
    )
    stride(from: 0, to: Int(vector.count), by: 1).forEach { i in
        print(vector.data[i])
    }
}

However, it’s likely that any real code would need something more complex.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thank you, this helps, and certainly works with the documented example!

(As you say, it depends on how the data are being used, and my example is more complex than the one in the documentation...

I need to try to understand how this works using the newly defined dense vector later in the code, where it now does not seem think the vector has been defined. For example, in the code you provided, the vector is printed, via the stride command, within the braces of the values.withUnsaftMutableBufferPointer construct. But if the brace ends before the stride command, the error is that "vector" is unresolved. I think my lack of understanding is from coming from Fortran to Swift, with need of0 more study of structs and classes...)

Anyway, many thanks!