Array and slice data types - arrays

I found myself confused with the array and slice data types.
From Go docs, arrays are described as follows:
There are major differences between the ways arrays work in Go and C. In Go,
Arrays are values. Assigning one array to another copies all the elements.
In particular, if you pass an array to a function, it will receive a copy of the array, not a pointer to it.
The size of an array is part of its type. The types [10]int and [20]int are distinct.
Functions:
As in all languages in the C family, everything in Go is passed by
value. That is, a function always gets a copy of the thing being
passed, as if there were an assignment statement assigning the value
to the parameter. For instance, passing an int value to a function
makes a copy of the int, and passing a pointer value makes a copy of
the pointer, but not the data it points to.
Why does sort.Ints(arrayValue) modify the passed variable when I declared it as an array, not as a slice?
Code
var av = []int{1,5,2,3,7}
fmt.Println(av)
sort.Ints(av)
fmt.Println(av)
return
Output
[1 5 2 3 7]
[1 2 3 5 7]

See "Slices: usage and internals"
var av = []int{1,5,2,3,7}
That is a slice, not an array.
A slice literal is declared just like an array literal, except you leave out the element count.
That explains why the sort function will modify the content of what is referenced by the slice.
As commented below by Kirk, sort.Ints will give you an error if you passed it an array instead of a slice.
func Ints(a []int)

Because you're using a slice, not an array.
That is a slice:
var av = []int{1,5,2,3,7}
And those are arrays:
var av = [...]int{1,5,2,3,7}
var bv = [5]int{1,5,2,3,7}
If you try to compile:
var av = [...]int{1,5,2,3,7}
fmt.Println(av)
sort.Ints(av)
fmt.Println(av)
, you will get an error:
cannot use av (type [5]int) as type []int in function argument
as sort.Ints expects to receive a slice []int.

[]int{1,5,2,3,7} is not an array. An array has it's length in it's type, like [5]int{1,5,2,3,7}.
Make a copy of the slice and sort it instead:
a := []int{1,5,2,3,7}
sortedA := make([]int, len(a))
copy(sortedA, a)
sort.Ints(sortedA)
fmt.Println(a)
fmt.Println(sortedA)

slices are pointer to array . when you copy an array to another or when you pass a array in the function the entire copy of array is copied or passed . This makes a costlier operation if thae array size is large. so we can go for slices.

var av = []int{1,5,2,3,7}
in the above statement you are initializing slice like an array
To create an array the syntax should be
var av = [5]int{1,5,2,3,7}

Related

Why does this code require me to include the size of the array in the function declaration?

I am trying to pass a float64 array to a function that will add the values and return the sum. My code is as follows:
func addThemNumbers(numbers []float64) float64{
sum := 0.0
for _,value := range numbers {
sum += value
}
return sum
}
func main() {
favNums := [2]float64 {0.9, 1.997}
fmt.Println("Sum: ", addThemNumbers(favNums))
}
When I run this, it produces this error:
/main.go:33:40: cannot use favNums (type [2]float64) as type []float64 in argument to addThemNumbers
However, when I specify size 2 in my function, such that addThemNumbers(numbers [2]float64), there is no error and it runs. If there was a type mismatch, I don't understand why specifying the size of the array works. I've seen several examples where specifying the size of the array in the function was not needed, so what am I missing?
[2]float64 is an array. When you declare a function f([2]float64), you can only pass a [2]float64 type value to it, and when you do, it passes a copy of the whole array. An array is a fixed size structure.
[]float64 is a slice. It is essentially a struct containing a pointer to an array, its length, and capacity. A slice contains a pointer to an array, so if you have a function f([]float64), you can pass any size array to it, and a reference to the underlying array will be passed, not a copy of that array.
To convert an array to a slice, you can use arr[:]. In your program:
fmt.Println("Sum: ", addThemNumbers(favNums[:]))
there's a difference between array and slice. I think what you're looking for is a slice.
In the function parameter, you're expecting a slice but rather you passed an array.
There are two ways to deal with it, quickly:
To remove the type mismatch, do mention the size in the parameter so that it accepts an array now (not slice).
Convert your array to a slice
fmt.Println("Sum: ", addThemNumbers(favNums[:]))
Also, please read this article on slices
Actually when we looking at the []float64 & [2]float64 is looking the same. But there's a difference, that is []float64 is a slice & [2]float64 is an array.
So when you change the addThemNumbers(numbers [2]float64), it automatically turns to an array. So you able to run the program without error.
And if you want to convert an array to a slice you can try below code.
func addThemNumbers(numbers []float64) float64{
sum := 0.0
for _,value := range numbers {
sum += value
}
return sum
}
func main() {
favNums := [2]float64 {0.9, 1.997}
fmt.Println("Sum: ", addThemNumbers(favNums[:]))
}

i am facing issue "panic: runtime error: index out of range" when create 2D array with make method in golang

I am new in golang and try to learn with small examples.
So I am trying to create a 2D array and assign a value but I am stuck here can anyone help me. here is my code.
package main
import (
"fmt"
)
func main() {
fmt.Println("Hello, playground")
letters := make([][]string,0,2)
letters[0][0] = "a"
letters[0][1] = "b"
letters[1][0] = "c"
letters[1][1] = "d"
fmt.Println(letters)
}
I am getting error when I run this code
panic: runtime error: index out of range
The Go Programming Language Specification
Array types
An array is a numbered sequence of elements of a single type, called
the element type. The number of elements is called the length and is
never negative.
Slice types
A slice is a descriptor for a contiguous segment of an underlying
array and provides access to a numbered sequence of elements from that
array. A slice type denotes the set of all slices of arrays of its
element type. The value of an uninitialized slice is nil.
Making slices, maps and channels
The built-in function make takes a type T, which must be a slice, map
or channel type, optionally followed by a type-specific list of
expressions. It returns a value of type T (not *T). The memory is
initialized as described in the section on initial values.
Appending to and copying slices
The built-in functions append and copy assist in common slice
operations. For both functions, the result is independent of whether
the memory referenced by the arguments overlaps.
The variadic function append appends zero or more values x to s of
type S, which must be a slice type, and returns the resulting slice,
also of type S.
In Go, arrays and slices are not the same thing. Your make([][]string,0,2) statement creates a 2D slice. Here is your 2D slice with initial values,
package main
import (
"fmt"
)
func main() {
letters := make([][]string, 2)
letters[0] = append(letters[0], "a", "b")
letters[1] = append(letters[1], "c", "d")
fmt.Println(letters)
}
Playground: https://play.golang.org/p/l40xv_7W5h
Output:
[[a b] [c d]]

Is it possible to get length of (static/dynamic) arrays from their references?

I want to pass reference of an array to a function that needs the length of array. I want to know if I have to pass its length as well or I can retrieve it from the array reference.
uses
Vcl.Dialogs, System.SysUtils, System.Types;
type
IntegerArray = array[0..$effffff] of Integer; // defined in System
PIntegerArray = ^IntegerArray; // defined in System
procedure Foo(const P: PIntegerArray);
begin
ShowMessage(IntToStr(Length(P^)));
end;
const
A: array[0..2] of Integer = (1, 2, 3);
var
B: TIntegerDynArray;
initialization
Foo(#A);
B := [4, 5, 6];
Foo(#B[0]);
end.
To accomplish this, you need to declare an open array parameter:
procedure Foo(const A: array of integer);
begin
ShowMessage('Length of array:'+IntToStr(High(A)+1));
end;
Pass both dynamic and static arrays to the procedure, and the arrays length is given by System.High.
Open array : The value, of type Integer, giving the number of elements in the actual parameter, minus one.
Your question amounts to the following:
Given the address of the first element of an array, which could be either static or dynamic, can I find the length of that array?
The answer is no. There are two factors in your way.
You can't tell whether the array is dynamic or static.
Even if you knew the array was static, you would not be able to find its length without compile time knowledge of its type.

Mutability of the Iterator Element in a For-In loop with an Array in Swift

I have some code in Swift 3.0 like so for trying to update the property in a array of elements...
for point in listOfPoints {
var pointInFrame : Float = Float(point.position.x * sensorIncomingViewPortSize.width) + Float(point.position.y)
point.status = getUpdateStatus( pointInFrame )
}
However I get a compile error of:
'Cannot assign to property: 'point' is a 'let' constant' [for line 3]
Is there anyway to make the iterator (point) mutable in Swift, like how you can use 'inout' for a function parameter?
Or are you supposed to do this task another way?
Thanks in Advance.
Stan
Just change it to var instead of let where you declare point. let is a constant.
Another way to accomplish this:
for i in 0 ... myStructArray.count - 1 {
var st = myStructArray[i]
st.someStringVariable = "xxx" // do whatever you need with the struct
st.someIntVariable = 123 // do more stuff
// last step (important!):
myStructArray[i] = st // necessary because structs are VALUE types, not reference types.
}
If you only need to make one change, you can omit the steps of defining the local variable (st in the example) as the array element and then afterwards setting the array element as equal to the local variable. But if you're going to make lots of changes to the element, if may be cleaner to make the local variable, make all the changes to it, and then assign that variable back to the array element.
If the array was of a Class rather than a Struct, that last step of assigning back wouldn't be necessary (reference type -- Class, vs value type -- Struct).

What is the action of the use of a Fortran array constructor func((/array(i)/))

I am reviewing a fortran (95/2003) code which contains a statement of the form
do j=1,size(array)
res(j) = func((/array(j)/))
end do
where func is a function which takes a single array 1-dimensional of size size(array) as argument. I understand that the (/ ... /) is an array constructor. But what is the purpose of the func((/array(j)/)) statement? Note that the sample is reduced of curse and I hope that I didn't remove relevant parts.
As you mentioned, func is some function that accepts an array as input and returns a scalar.
array(j) is just a scalar, so you cannot pass that to func directly. So you construct an array of dimension 1 by (/ array(j) /) and pass that temporary array to your function.
As agentp pointed out [thanks!], the following would also pass a dimension-1 array (to be precise, an array slice of length 1):
func( array(j:j) )

Resources