I am new to golang. But I couldn't find an answer to this.
In python I can do,
array = [1, 2, 3, None, 5]
But in go when I write
var array = [5]int {1, 2, 3, nil, 5}
The compiler gives me the following error:
cannot convert nil to type int
How can I create an array in golang which is a mix of integer and nil values?
First a bit of theory. Python is a dynamically typed language. While each individual value has a type, your variables can be assigned values of any type without a problem. As a consequence, python collections can contain multiple types of values and don't complain. The following is a valid python tuple (1, 'a', None, True). Go is a statically typed language. If your variable is defined as an integer you cannot assign any non-integer value to it. As a consequence, collections in Go have a type and can only contain a single type of object.
Now to practice. There are a few ways to do what you want. The classical C way would be to pick an integer value you are never going to encounter and use that as a null value. A 0 or a -1 or something. This is not very robust though.
A more idiomatic way is to define your own type.
package main
import "fmt"
type NilInt struct {
value int
null bool
}
func (n *NilInt) Value() interface{} {
if n.null {
return nil
}
return n.value
}
func NewInt(x int) NilInt {
return NilInt{x, false}
}
func NewNil() NilInt {
return NilInt{0, true}
}
func main() {
var x = []NilInt{NewNil(), NewInt(10), NewNil(), NewInt(5)}
for _, i := range x {
fmt.Printf("%v ", i.Value())
}
}
Every type in go has a "zero value" which it is assigned when it is created to make sure it is always initialized. For int the "zero value" is 0, for strings "". There are some things that can have nil as their value though:
pointers
interfaces
maps
slices
channels
function types
Only the first is really relevant here though. If you want an int that is nil you have to declare it as a pointer to that int. As slices can't have mixed types you then need to make the slice a slice of type pointer to int: *int. So you could have a slice of pointers to ints that included a nil value:
zero := 0
ints := []*int{&zero, nil}
for _, anInt := range ints {
if anInt != nil {
fmt.Println(*anInt)
} else {
fmt.Println(anInt)
}
}
The *anInt in the println dereferences the pointer turning it into an int rather than a pointer to an int.
https://play.golang.org/
Related
It is legal to say this (arr is an Array):
let arrenum = Array(arr.enumerated())
So why isn't it legal to say this?
extension Array {
func f() {
let arrenum = Array(self.enumerated())
// error: type of expression is ambiguous without more context
}
}
EDIT It seems this is a workaround:
extension Array {
func f() {
typealias Tup = (offset:Index, element:Element)
let arrenum = Array<Tup>(self.enumerated())
}
}
But why is that needed? (And is it right?)
This is a known bug (SR-1789). Swift currently has a feature where you can refer to a generic type within its own body without having to repeat its placeholder type(s) – the compiler will infer them for you to be the same as the type of self.
For example:
struct S<T> {
func foo(_ other: S) { // parameter inferred to be `S<T>`.
let x = S() // `x` inferred to be `S<T>`.
}
}
extension S {
func bar(_ other: S) {} // same in extensions too.
}
This is pretty convenient, but the bug you're running into is the fact that Swift will always make this inference, even if it's incorrect.
So, in your example:
extension Array {
func f() {
let arrenum = Array(self.enumerated())
// error: type of expression is ambiguous without more context
}
}
Swift interprets the code as let arrenum = Array<Element>(self.enumerated()), as you're in the body of Array<Element>. This is incorrect, because enumerated() yields a sequence of offset-element tuple pairs – Swift should have inferred Array to be Array<(offset: Int, element: Element)> instead.
One workaround, which you've already discovered, is to explicitly specify the placeholder type in order to prevent the compiler from making this incorrect inference.
extension Array {
func f() {
let arrenum = Array<(offset: Int, element: Element)>(self.enumerated())
}
}
Another possible workaround appears to be using the fully-qualified type, for example:
extension Array {
func f() {
let arrenum = Swift.Array(self.enumerated())
}
}
as it appears Swift doesn't do the same inference for fully-qualified types (I'm not sure if you should rely on this fact though).
Finally it's worth noting that instead of doing a call to Array's initialiser, you could use map(_:) instead to avoid the issue entirely:
extension Array {
func f() {
let arrenum = self.enumerated().map { $0 }
}
}
which, like the initialiser call, will give you back an array of offset-element pairs.
I want to create a struct in swift that has a small fixed number of values (say 16 floats) as instance data. It is required that this struct not store these values on the heap, so that the address of an instance of the struct is the address of the instance vars. It is also a requirement that these values be accessible internally to the struct via subscript, as Arrays are.
In C you would simply define this kind of thing thusly:
struct Matrix4x4 {
float elements[16];
...
} myMatrix;
With this code, sizeof(Matrix4x4) == 64 and also &myMatrix == &myMatrix.elements[0]; In swift, if I analogously define the elements variable as type [Float], the matrix instance only contains a pointer to the array, since the Array<Float> instance is an object stored on the heap.
Is there a way in swift to get static allocation of the instance vars without abandoning the convenience and efficiency of array-like subscripting access?
At present, this is not possible in "pure Swift". There is a long discussion
on the swift-evolution mailing list starting at
[swift-evolution] Proposal: Contiguous Variables (A.K.A. Fixed Sized Array Type)
which asks for such a feature, e.g. to pass a matrix structure to C functions.
As far as I can see, the suggestion was well-received, but nothing concrete is planned
as of now, and it is not listed in the
currently active Swift proposals.
A C array
float elements[16];
is imported to Swift as a tuple with 16 components:
public var elements: (Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float)
and at present this seems to be the only way to define a fixed-sized structure with a given memory layout.
Joe Groff from Apple writes at
[swift-users] Mapping C semantics to Swift
Swift structs have unspecified layout. If you depend on a specific layout, you should define the struct in C and import it into Swift for now.
and later in that discussion:
You can leave the struct defined in C and import it into Swift. Swift will respect C's layout.
If the matrix type is defined in a C header file (for the sake of simplicity I am using
a 2x2 matrix as example now)
// matrix.h:
typedef struct Matrix2x2 {
float elements[4];
} Matrix2x2;
then it is imported to Swift as
public struct Matrix2x2 {
public var elements: (Float, Float, Float, Float)
public init()
public init(elements: (Float, Float, Float, Float))
}
As mentioned above, Swift preserves the C memory layout, so that the matrix, its
elements, and the first element all have the same address:
var mat = Matrix2x2(elements: (1, 2, 3, 4))
print(sizeofValue(mat)) // 16
withUnsafePointer(&mat) { print($0) } // 0x00007fff5fbff808
withUnsafePointer(&mat.elements) { print($0) } // 0x00007fff5fbff808
withUnsafePointer(&mat.elements.0) { print($0) } // 0x00007fff5fbff808
However, tuples are not subscriptable, and that makes sense if the tuple members have
different types. There is another discussion on the swift-evolution mailing list
[swift-evolution] CollectionType on uniform tuples [forked off Contiguous Variables]
to treat "uniform tuples" as collections, which would allow subscripting.
Unfortunately, this hasn't been implemented yet.
There are some methods to access tuple members by index, e.g. using Mirror()
or withUnsafe(Mutable)Pointer().
Here is a possible solution for Swift 3 (Xcode 8), which seems to work well
and involves only little overhead. The "trick" is to define C functions which
return a pointer to the element storage:
// matrix.h:
// Constant pointer to the matrix elements:
__attribute__((swift_name("Matrix2x2.pointerToElements(self:)")))
static inline const float * _Nonnull matrix2x2PointerToElements(const Matrix2x2 * _Nonnull mat)
{
return mat->elements;
}
// Mutable pointer to the matrix elements:
__attribute__((swift_name("Matrix2x2.pointerToMutableElements(self:)")))
static inline float * _Nonnull pointerToMutableElements(Matrix2x2 * _Nonnull mat)
{
return mat->elements;
}
We need two variants to make the proper value semantics work (subscript setter requires
a variable, subscript getter works with constant or variable).
The "swift_name" attribute makes the compiler import these functions as member
functions of the Matrix2x2 type, compare
SE-0044 Import as member
Now we can define the subscript methods in Swift:
extension Matrix2x2 {
public subscript(idx: Int) -> Float {
get {
precondition(idx >= 0 && idx < 4)
return pointerToElements()[idx]
}
set(newValue) {
precondition(idx >= 0 && idx < 4)
pointerToMutableElements()[idx] = newValue
}
}
}
and everything works as expected:
// A constant matrix:
let mat = Matrix2x2(elements: (1, 2, 3, 4))
print(mat[0], mat[1], mat[2], mat[3]) // 1.0 2.0 3.0 4.0
// A variable copy:
var mat2 = mat
mat2[0] = 30.0
print(mat2) // Matrix2x2(elements: (30.0, 2.0, 3.0, 4.0))
Of course you could also define matrix-like subscript methods
public subscript(row: Int, col: Int) -> Float
in a similar manner.
As the answer above alludes, you can use combo of withUnsafeMutableBytes() and assumingMemoryBound(to:) to treat the C array as a swift array within the scope of the call.
withUnsafeMutableBytes(of: &mymatrix.elements) { rawPtr in
let floatPtr = rawPtr.baseAddress!.assumingMemoryBound(to: Float.self)
// Use the floats (with no bounds checking)
// ...
for i in 0..<10 {
floatPtr[i] = 42.0
}
}
I'm writing a wrapper around a C mathematical library. Every function takes one or two functions as arguments. However, the arguments for those child functions (as well as the parent functions) are not Swifty -hence the wrapper.
I've cleaned up the example code to just show the three main pieces: the c-library function, the desired Swift function that would be passed to the wrapper (body not shown, but wrapping around the c-library function), and the required C function form.
//C library function, that calls the passed function dozens, hundreds or thousands of times, each time it changes the data provided in p, and uses the output from x
//The Swift arrays are passed as pointers, and the length of the and x array are m and n respectively
returnValue = cLibraryFunc(passedFunc, &p, &x, Int32(m), Int32(n), Int32(itmax), &opts, &info, &work, &covar, &adata)
//I would like to create a Swift function that would look like this (internals could be any myriad of things that takes inputs p and adata and returns data in x:
func desiredSwifty(p: inout [Double], x: inout [Double], m: Int, n: Int, adata: inout [Double]) {
//very simple example
//this example knows the length of p (so m as well)
//and assumes that adata length is the same as the x length (n)
//obviously, it could ifer m and n from p.count and x.count
for i in 0..<n {
x[i] = p[0] + p[1]*adata[i] + p[2]*pow(adata[i], 2)
}
}
//And the wrapper would "convert" it -internally- into the form that the C library function requires:
func requiredC(p: UnsafeMutablePointer<Double>?, x: UnsafeMutablePointer<Double>?, m: Int32, n: Int32, adata: UnsafeMutablePointer<Void>?) {
//same thing, but using pointers, and uglier
//first, have to bitcast the void back to a double
let adataDouble : UnsafeMutablePointer<Double> = unsafeBitCast(adata, to: UnsafeMutablePointer<Double>.self)
for i in 0..<Int(n) {
x![i] = p![0] + p![1]*adataDouble[i] + p![2]*pow(adataDouble[i], 2)
}
}
addition
I should add that I have access to the c source code, so I could possibly add some dummy parameters (possibly to find a way to pass context in). But given that the docs seem to indicate that one can't grab context with a c function pointer, this may be of no use.
(Note: the following example uses Swift 3 on Xcode 8 beta 2.)
Your question is about C functions taking another C function as an argument, so let us reduce the question to that problem. Here is a simple C function which takes a single argument which is
again a C function which takes a pointer to an array of doubles
and an integer count:
// cfunction.h:
void cFunc(void (*func)(double *values, int count));
// cfunction.c:
void cFunc(void (*func)(double *values, int count)) {
double x[] = { 1.2, 3.4, 5,6 };
func(x, 3);
}
This function is imported to Swift as
func cFunc(_ func: (#convention(c) (UnsafeMutablePointer<Double>?, Int32) -> Swift.Void)!)
Here #convention(c) declares the block to have C-style calling
conventions. In particular, from Swift you can pass only a global function or a closure which does not capture any context.
A simple example for a Swift wrapper is
func swiftyFunc(passedFunc: (#convention(c) (UnsafeMutablePointer<Double>?, Int32) -> Void)) {
cFunc(passedFunc)
}
which you can use like this:
func functionToPass(values: UnsafeMutablePointer<Double>?, count: Int32) {
let bufPtr = UnsafeBufferPointer(start: values, count: Int(count))
for elem in bufPtr { print(elem) }
}
swiftyFunc(passedFunc: functionToPass)
or with a closure argument:
swiftyFunc { (values, count) in
let bufPtr = UnsafeBufferPointer(start: values, count: Int(count))
for elem in bufPtr { print(elem) }
}
Do you know that you can get a mutable pointer to a var just by using the & operator? It does the "right thing" on arrays too.
func foo(_ x: UnsafeMutablePointer<Int>) {
print(x)
}
func bar(_ x: UnsafeMutablePointer<Int>) {
print(x)
}
var array = [0]
foo(&array)
var int = 0
bar(&int)
(Tested on Swift 2, but most likely still valid on Swift 3.)
I suspect that this could drastically reduce your need for wrappers.
I'm trying to implement a padding function for Array:
extension Array {
func dataWithPadding(offset: Int, length: Int, paddingLength: Int) -> NSData {
var arr = Array(self[offset..<(offset + length)])
arr = arr.reverse()
for (var i = 0; i < paddingLength; i++) {
arr.append(0)
}
let d = NSData(bytesNoCopy: &arr, length: length)
return d
}
}
This errors at arr.append with:
Cannot invoke 'append' with an argument list of type '(Int)'
I try to change the declaration into:
var arr[UInt8] = Array(self[offset..<(offset + length)])
However, this also errors:
Cannot assign to immutable expression of type '[UInt8].Type' (aka 'Array.Type')
The weird part: I try to run the original code with arr.append commented out, and use lldb to directly run arr.append(0), it actually works.
I'm using Xcode 7.2.
Since your Array extension puts no constraint on which types of arrays (element types) that can be used with it, .append(0) cannot be invoked; not all types can be converted into from integer literals. Hence, it's not weird that you cannot use .append(0) in the "generic" array extension, whereas you naturally can use it directly on an array that Swift can infer to have integer literal convertible elements, e.g. [Int]. Consider the following example:
var arr : [UInt8] = []
arr.append(0)
var arr2 : [String] = []
arr2.append(0) // error
In the example above, both arrays would have access to your extension dataWithPadding, but both can naturally not make use of arr.append(0) in the extension, hence the error message
Cannot invoke 'append' with an argument list of type '(Int)'
Now, a simple fix is to add a type constraint for the array elements to IntegerLiteralConvertible, after which you extension is valid, and accessible for all arrays that have elements which conform to IntegerLiteralConvertible.
extension Array where Element: IntegerLiteralConvertible {
func dataWithPadding(offset: Int, length: Int, paddingLength: Int) -> NSData {
var arr = Array(self[offset..<(offset + length)])
arr = arr.reverse()
for (var i = 0; i < paddingLength; i++) {
arr.append(0)
}
let d = NSData(bytesNoCopy: &arr, length: length)
return d
}
}
Alternatively, make use of the less general SignedNumberType, UnSignedIntegerType or IntegerType as type constraint for Element; these conform also to e.g. Comparable and Equatable, in case you'd like to compare and perform operations on your generic elements in the extension.
Finally note that you can naturally use your own custom protocol as type constraint for Element in your extension, allowing you to include additional blueprints (below, foo() method) accessible for your Element:s in the extension
protocol MyIntegerLiteralInitializableTypes: IntegerLiteralConvertible {
func foo()
}
extension MyIntegerLiteralInitializableTypes {
func foo() {
print("I am of type \(self.dynamicType)!")
}
}
/* For the Array<Type>:s you want to have access to .dataWithPadding,
extend those 'Type':s to MyIntegerLiteralInitializableTypes */
extension Int8 : MyIntegerLiteralInitializableTypes { }
extension UInt8 : MyIntegerLiteralInitializableTypes { }
extension Array where Element: MyIntegerLiteralInitializableTypes {
func dataWithPadding(offset: Int, length: Int, paddingLength: Int) -> NSData {
self.first?.foo() /* I am of type ...! */
var arr = Array(self[offset..<(offset + length)])
arr = arr.reverse()
for (var i = 0; i < paddingLength; i++) {
arr.append(0)
}
let d = NSData(bytesNoCopy: &arr, length: length)
return d
}
}
It's also probably a good idea to add #warn_unused_result to your dataWithPadding(...) function signature, as a call to it without assigning the return will yield a runtime exception ("... malloc: ...: pointer being freed was not allocated").
I would like to have an array / slice in Go with a variadic number of elements (not known at compile time) and be able to dinamically add new elements of different types, for instance:
data[0] := "string"
data[1] // slice
data[1][0] := "another string"
data[1][1] := 42 // int
Is this possible somehow?
It's a bit ugly but possible using empty interfaces, interface{}:
package main
import "fmt"
func main() {
variadic := []interface{}{}
variadic = append(variadic, "foo")
variadic = append(variadic, []interface{}{"bar", 42})
//this will print "foo"
fmt.Println(variadic[0])
//note that you have to cast variadic[1] to an array before accessing it
fmt.Println(variadic[1].([]interface{})[0])
}
If you allow the assumption that each element must be an array of anything with varying length, it's a bit less ugly:
package main
import "fmt"
func main() {
variadic := [][]interface{}{}
variadic = append(variadic, []interface{}{"foo"})
variadic = append(variadic, []interface{}{"bar", 42})
fmt.Println(variadic[0])
fmt.Println(variadic[1][0])
fmt.Println(variadic[1][1])
}