convert array from int8 to int in go - go

I have a problem to call function
sort.SearchInts(arrInt, 10)
because array (arrInt) has a type int8 and I need convert array to type int.
I guess I could go the long way and search an element in a for loop, but it sounds ugly and I guess there are better ways to do it.

An array is a contiguous sequence of items of the same size in memory:
Array of int8: [1 byte][1 byte][1 byte][1 byte][1 byte]...
If we need array of ints (tipically 8 bytes in amd64) we have:
Array of int: [8 bytes][8 bytes][8 bytes][8 bytes][8 bytes]...
There is no way to simply convert or cast from one type to the other, the only way to get the array of ints is creating a new array of int and converting all values from int8 to int.
On the other hand, if you only need to search in an array, doing all the conversion is overkill, the best approach is creating a function SearchInt8.
Here is where generics are useful, the same algorithm will be aplicable to types with the same operations but Golang lack of generics. To get this result, golang comes with the function sort.Search (https://golang.org/pkg/sort/#Search) that accepts as second argument the function to implement the comparation for your type.
Reminder: to use Search functions, the array should be already sorted.

sort.SearchInts is just a convenience wrapper of sort.Search for slices of ints.
It's implemented like this:
func SearchInts(a []int, x int) int {
return Search(len(a), func(i int) bool { return a[i] >= x })
}
So you can create a custom "SearchInt8s" function that does the same for int8 arguments:
func SearchInt8s(a []int8, x int8) int {
return sort.Search(len(a), func(i int) bool { return a[i] >= x })
}
Or (as another answer already said), just use sort.Search directly:
sort.Search(len(arrInt), func(i int) bool { return arrInt[i] >= 10 })
Do note that the slice must be sorted before calling this, since this family of functions perform a binary search in a sorted slice.

sort.Search(len(arrInt), func(i int) bool { return arrInt[i] >= 10 })

Related

invalid operation: cannot index T when modeling slices of arbitrary dimensions

I am try to do a matrix subtraction with unknow size of matrix. here is the code:
type ArrayLike interface {
[]interface{} | [][]interface{} | [][][]interface{} | [][][][]interface{}
}
func subMatrix[T ArrayLike](A, B T, shape []int) interface{} {
dim := shape[0]
if len(shape) == 1 {
retObj := make([]interface{}, dim)
for i := 0; i < dim; i++ {
Av := A[i].(float64)
Bv := B[i].(float64)
retObj[i] = Av - Bv
}
return retObj
} else {
retObj := make([]interface{}, dim)
for i := 0; i < dim; i++ {
retObj[i] = subMatrix(Av[i], Bv[i], shape[1:])
}
return retObj
}
}
It complains about
invalid operation: cannot index A (variable of type T constrained by []interface{}|[][]interface{}|[][][]interface{}|[][][][]interface{})compilerNonIndexableOperand
Does anyone know how to do this job?
You can't do this, not with generics and not with interface{}/any alone. The main issue is that you can't statically model slices with arbitrary dimensions — i.e. arbitrary types. Let's go in order:
The error message you got is because you can't index a type parameter with a union constraint like that. Specs, Index expressions:
For a of type parameter type P:
[...]
The element types of all types in P's type set must be
identical. [...]
The element types of ArrayLike's type set are not identical. The element type of []interface{} is interface{}, the one of [][]interface{} is []interface{} and so on.
There is a placebo solution to the indexing error, outlined here, basically it involves changing the type of the arguments A and B to a slice []T. Then you can index A[i] and B[i].
However this isn't enough. At this point, there's no way to pass correct arguments to the recursive call. The type of the expression A[i] is now T, but subMatrix wants []T.
Even dropping type parameters and declaring the args A and B as any doesn't work, because on the recursive call you still want to index them. In order to index, you have to assert any to something that's indexable, but what would that be? At each recursion the types would have one less dimension, so a statically typed assertion would eventually panic.
The only way to solve this is (probably?) with reflection, but honestly I don't see a practical utility to do that.
You can, and should, write a generic function for each matrix dimension:
import "golang.org/x/exp/constraints"
type Number interface {
constraints.Integer | constraints.Float
}
func Sub2DMatrix[T Number](a, b [][]T) {
for i := range a {
for j := range a[i] {
a[i][j] -= b[i][j]
}
}
}

sorting a GO struct by date which is defined via proto message

I have defined a message in proto file:
my.proto
--------
message Holiday {
string title = 1;
google.protobuf.Timestamp date = 2;
}
After compiling, it creates my.pb.go
Now in my go code, I have an slice of Holiday.
main.go
-------
holidays := []my.Holiday{...}
I have to sort this slice by Holiday.date. As per the doc if I want to sort using sort.Sort then I have to implement Len, Swap & Less method. But I cannot define these receiver method in my go code because Holiday is coming from the different package (my.pb.go).
Is there any way to sort this?
Thanks,
You could just use sort.Slice, which doesn't require implementing sort.Interface.
Slice sorts the slice x given the provided less function. It panics if x is not a slice.
sort.Slice(holidays, func(i, j int) bool {
return holidays[i].GetDate().Before(holidays[j].GetDate())
})
The SortKeys example in the sort.Sort documentation shows how to accomplish this by using an ad-hoc struct:
// A Planet defines the properties of a solar system object.
type Planet struct {
name string
mass earthMass
distance au
}
// By is the type of a "less" function that defines the ordering of its Planet arguments.
type By func(p1, p2 *Planet) bool
// Sort is a method on the function type, By, that sorts the argument slice according to the function.
func (by By) Sort(planets []Planet) {
ps := &planetSorter{
planets: planets,
by: by, // The Sort method's receiver is the function (closure) that defines the sort order.
}
sort.Sort(ps)
}
// planetSorter joins a By function and a slice of Planets to be sorted.
type planetSorter struct {
planets []Planet
by func(p1, p2 *Planet) bool // Closure used in the Less method.
}
// Len is part of sort.Interface.
func (s *planetSorter) Len() int {
return len(s.planets)
}
// Swap is part of sort.Interface.
func (s *planetSorter) Swap(i, j int) {
s.planets[i], s.planets[j] = s.planets[j], s.planets[i]
}
// Less is part of sort.Interface. It is implemented by calling the "by" closure in the sorter.
func (s *planetSorter) Less(i, j int) bool {
return s.by(&s.planets[i], &s.planets[j])
}
Given that sort.Sort only takes a sort.Interface, it doesn't care about what data structure you are using or what type you are actually swapping.
The sort package documentation shows two examples that answer the question.
The first package example declares a slice type with the required methods:
type Person struct {
Name string
Age int
}
type ByAge []Person
func (a ByAge) Len() int { return len(a) }
func (a ByAge) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age }
...
sort.Sort(ByAge(people))
Notice that the Len, Swap and Less methods are on the slice type defined for sorting, not on the struct type. You can define that type in your own package.
The sort.Slice example shows how to sort with a less function only:
sort.Slice(people, func(i, j int) bool { return people[i].Name < people[j].Name })
In this example, there's no need to define types for the purpose of soring.

Do slices or arrays act as a global scope?

I'm still new to programming. Forgive my lack of computer science knowledge. Not sure if this question is specific to Golang or computer science in general...
I always thought that functions do not alter variables/data held outside their own scope unless you use a return statement back into the other scope, or unless they are higher in the hierarchy of scopes. One may argue that functions f1 and f2 in this example are called from a lower scope. However, this still doesn't explain why I'm getting different results for variable num and nums.
package main
import "fmt"
func f1(a int) {
a = 50 // this will not work, as it shouldn't
}
func f2(a ...int) {
a[0] = 50 // this will work without return statement
a[1] = 50 // this will work without return statement
}
func main() {
num := 2
nums := []int{2, 2}
f1(num)
f2(nums...)
fmt.Printf("function f1 doesn't affect the variable num and stays: %v\n", num)
fmt.Printf("function f2 affects the variable nums and results in: %v", nums)
Questions:
Why doesn't f2 require a return statement to modify nums like num
would within f1?
Golang functions are said to pass values (rather than reference),
shouldn't that force the function to return copies?
Can this happen in other languages? (I think I may have
seen this in other languages).
This is the correct behaviour, since a ...int is equal to a slice e.g.: a []int
func f2(a []int) {
a[0] = 50
a[1] = 50
}
func main() {
b := []int{2, 2}
f2(b)
fmt.Println(b) // [50 50]
}
And a slice is a view to the original data, here 'b'.
"Why doesn't f2 require a return statement to modify nums like num would in f1?"
In f2 you are using the slice, which has a pointer to the original array, so f2 can change the outside array.
"Golang functions are said to pass values (not reference), shouldn't that force to return copies? (If the question is related...)"
In f2 the slice itself is passed by value, meaning pointer and length and capacity of the original array.
"Can this happen in other languages? (I think I may have seen this in other langues)"
Too broad to answer, there are many languages and in general if you have a pointer to the outside world array, yes.
Edit:
package main
import "fmt"
func sum(a ...int) int {
s := 0
for _, v := range a {
s += v
}
return s
}
func f2(a []int) {
c := make([]int, len(a))
copy(c, a)
c[0] = 50
fmt.Println(sum(c...)) // 52
}
func main() {
b := []int{2, 2}
fmt.Println(sum(1, 2, 3, 4)) // 10
fmt.Println(sum(b...)) // 4
f2(b)
fmt.Println(b) // [2 2]
}
Notes:
The sum() function above is a pure function, since it has no side effect.
The new f2 function above is a pure function, since it has no side effect: it makes a copy of a into c then calls the sum.
In go, function arguments are passed by value. That means, if you pass an int (like in f1), compiler will pass the value of f1, essentially copying it. If the function takes a *int and you pass &num, then the compiler passes the value of &num, which is a pointer to num. When the function changes *num, the value of the variable outside the function will change. If the function changes num, the pointer value of num will change, and it will point to a different variable.
As a contrast, Java passes all primitive values as value, and all objects by reference. That is, if you pass an int, there is no way for the function to modify the value of that int that is visible to the caller. If you want to pass an int the function can modify, you put that in a class and pass an instance of that class in Java.
A slice (as in f2) contains a pointer to the underlying array. When you call a function with a slice, the slice header (containing a pointer to the underlying array) is copied, so when the function changes the slice elements, the underlying array elements change.
The question of scope is somewhat different. Scope of a function is all the variables it can see. Those are the global variables (if from different packages, exported global variables), function arguments, and if the function is declared nested within another function, all the variables visible in that function at that point.
1 & 2) Both questions can be answered when looking at how slices work in Go. There's a blog article on it.
In general, all variables are passed by value in Go. You can use pointers (e.g. *int for f1) to pass by reference (or more correct, the address of the pointer).
However, slices are technically also passed by value.
When we look here, we can get an idea how they work:
type SliceHeader struct {
Data uintptr
Len int
Cap int
}
Len and Cap are integers, but Data is a pointer.
When this struct is copied (when passing by value), a copy of Len, Cap and Data will be made. Since Data is a pointer, any modifications made to the value it's pointing to will be visible after your function returns.
You can also read this

What's the reason for having methods outside the definition of the struct?

Why do we have the methods declared outside the type definition of the struct? E.g.:
type antenna struct {
name string
length float32
girth float32
bloodtype string
}
func (p *antenna) extend() {
p.length += 10
}
It seems to me that the method could be part of the struct? (Let's ignore for now that structs are supposed to be value types)
type antenna struct {
name string
length float32
girth float32
bloodtype string
func extend() {
length += 10
}
}
This would be more similar to traditional OOP. I didn't find any good explanations of why it is done the way it is besides "structs are value-types and classes are reference-types". I know the difference, but it's not a satisfactory answer to me. In any way the method has to be called like this:
var x = antenna()
x.extend()
So what's the point of separating the the struct and methods? Having them visually grouped together in the code - as in typical OOP languages - seems useful to me?
TLR: Code reuse, and Consistency.
1 - This enables to reuse methods:
This is the key design principle of the interface type in Go - let me make it more clear with an example: Consider you need to sort an slice of int (try it here):
a := []int{1, 3, 2, 5, 4}
sort.Ints(a) // sort.Sort(sort.IntSlice(a))
fmt.Println(a) // [1 2 3 4 5]
You simply call sort.Ints(a) which then calls Sort(IntSlice(a)) inside the standard library:
type IntSlice []int
func (x IntSlice) Len() int { return len(x) }
func (x IntSlice) Less(i, j int) bool { return x[i] < x[j] }
func (x IntSlice) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
sort.IntSlice attaches the 3 methods of sort.Interface: Len, Less, and Swap to the type []int, to call:
// Sort sorts data in ascending order as determined by the Less method.
// It makes one call to data.Len to determine n and O(n*log(n)) calls to
// data.Less and data.Swap. The sort is not guaranteed to be stable.
func Sort(data Interface) {
n := data.Len()
quickSort(data, 0, n, maxDepth(n))
}
So you are able to reuse methods from the standard library, and you don't need to reimplement it again.
2- You may define your own types, See this example - There is no inside here for this named type - so methods must be outside of this type:
package main
import "fmt"
type num int32
func (p *num) inc() {
*p++
}
func main() {
p := num(100)
p.inc()
fmt.Println(p) // 101
}
The above named type num versus this user defined type: By design this makes the Go language consistent for both types:
type Animal struct {
Name string
moves []move.Direction
}
func (p *Animal) Walk(dir move.Direction) {
p.moves = append(p.moves, dir)
}
See also:
In Go is naming the receiver variable 'self' misleading or good practice?

Is there a way to avoid the implementation of the full sort.Interface for slices of structs?

If I have an array/slice of structs in Go and want to sort them using the sort package it seems to me that I need to implement the whole sort interface which contains 3 methods:
Len
Swap
Less
It seems that Len and Swap should always have the same implementation no matter the type of struct is in the array.
Is there a way to avoid having the implement Len and Swap every time or is this just a limitation from the lack of Generics in Go?
If you are implementing several different comparison operations on the same slice type, you can use embedding to avoid redefining Len and Swap each time. You can also use this technique to add parameters to the sort, for example to sort in reverse or not depending on some run-time value.
e.g.
package main
import (
"sort"
)
type T struct {
Foo int
Bar int
}
// TVector is our basic vector type.
type TVector []T
func (v TVector) Len() int {
return len(v)
}
func (v TVector) Swap(i, j int) {
v[i], v[j] = v[j], v[i]
}
// default comparison.
func (v TVector) Less(i, j int) bool {
return v[i].Foo < v[j].Foo
}
// TVectorBarOrdered embeds TVector and overrides
// its Less method so that it is ordered by the Bar field.
type TVectorBarOrdered struct {
TVector
}
func (v TVectorBarOrdered) Less(i, j int) bool {
return v.TVector[i].Bar < v.TVector[j].Bar
}
// TVectorArbitraryOrdered sorts in normal or reversed
// order depending on the order of its Reversed field.
type TVectorArbitraryOrdered struct {
Reversed bool
TVector
}
func (v TVectorArbitraryOrdered) Less(i, j int) bool {
if v.Reversed {
i, j = j, i
}
return v.TVector[i].Foo < v.TVector[j].Foo
}
func main() {
v := []T{{1, 3}, {0, 6}, {3, 2}, {8, 7}}
sort.Sort(TVector(v))
sort.Sort(TVectorBarOrdered{v})
sort.Sort(TVectorArbitraryOrdered{true, v})
}
Your own answer is right. In your case of an array or slice the implementations of Len() and Swap() are simple. Like len() Go could provide a native swap() here. But the interface which is used now can also be used for more complex data structures like BTrees. It still allows the Sort() function to work (like my parallel quicksort, which uses the same sort interface).
If you want to sort slices (for which Len and Swap always have the same implementation), the sort package now has a function that only requires an implementation of Less:
func Slice(slice interface{}, less func(i, j int) bool)
Although this is an old question, I'd like to point out
the github.com/bradfitz/slice
package.
But as an example or proof of concept only, I would not recommend this actually be used (it's documented with the word "gross"):
It uses gross, low-level operations to make it easy to sort arbitrary slices with only a less function, without defining a new type with Len and Swap operations.
In actual code, I find it completely trivial, quick, short, readable, and non-distracting to just do something like:
type points []point
func (p []points) Len() int { return len(p) }
func (p []points) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
func (p []points) Less(i, j int) bool {
// custom, often multi-line, comparison code here
}
Here gofmt insists on a blank line between the type and func lines
but it has no problem with
multiple one-line functions with no blank lines
and it nicely lines up the function bodies.
I find this a nice readable compact form for such things.
As for your comment that:
It seems that Len and Swap should always have the same implementation no matter the type of struct is in the [slice]
just the other week I need a sort that kept pairs of elements in a slice together (for input to strings.NewReplacer) that required a trivial variation like:
type pairByLen []string
func (p pairByLen) Len() int { return len(p) / 2 }
func (p pairByLen) Less(i, j int) bool { return len(p[i*2]) > len(p[j*2]) }
func (p pairByLen) Swap(i, j int) {
p[i*2], p[j*2] = p[j*2], p[i*2]
p[i*2+1], p[j*2+1] = p[j*2+1], p[i*2+1]
}
This is not supported by an interface like the one in github.com/bradfitz/slice.
Again, I find this layout easy, compact, and readable.
Although (perhaps more so in this case), others may disagree.

Resources