Calling function names from a slice and return a value - go

I want to call a number of function names stored in a slice. The code snippet below works so far but I need to return a value from those functions. Unfortunately I don't get it to work because I don't know to to call those functions and store the return value. Any ideas?
This is the code I'm currently working on:
package main
func A(x int) int {
return x + 1
}
func B(x int) int {
return x + 2
}
func C(x int) int {
return x + 3
}
func main() {
x := 10
type fs func(x int) int
f := []fs{A, B, C}
fns := make([]func(), 3)
for a, _ := range f {
a := a
fns[a] = func() {
f[a](x)
}
}
for _, f := range fns {
f()
}
}
Go Playground

You have call it...
for a, _ := range f {
a := a
fns[a] = func() {
f[a](x) // in this
}
}
here is the playground

Related

pythons enumerate in go

let's say that I have generator of fibonachi numbers, and I would like to use enumerate(get_next_fibs(10)) and I would like to have generator of pairs index, number_from_generator, I am struggling to find solution with "named return values"
and it's not how it should be done but it's for purpose of learning specific things about generators
package main
import "fmt"
func get_next_fibs(ii int) func() int {
i := 0
a, b := 0, 1
fc := func() int {
i++
a, b = b, a+b
if ii <= i {
return -1
}
return a
}
return fc
}
func enumerate(iter func() int) func() (index, v int) {
index := 0
fc := func() (index, v int) {
v := iter()
return
index++
}
return fc
}
func main() {
iter := enumerate(get_next_fibs(10))
// iter := get_next_fibs(10)
fmt.Printf("iter = %T\n", iter)
for tuple := iter(); tuple != -1; tuple = iter() {
fmt.Println("tuple:", tuple)
}
}
You have few issues in this code sample:
You can't have index++ after return statement. Use defer if you need to do something after return-ing.
You're missing how variable shadowing works in go. Thus, you're trying to modify a wrong index variable.
Go doesn't have tuples.
...
func enumerate(iter func() int) func() (index, v int) {
counter := 0
return func() (index, v int) {
i := counter
counter++
return i, iter()
}
}
...
func main() {
iter := enumerate(get_next_fibs(10))
fmt.Printf("iter = %T\n", iter)
for i, v := iter(); v != -1; i, v = iter() {
fmt.Printf("i: %d, v: %d\n", i, v)
}
}
Playground link

Can I use Go slice unpacking to streamline this permutation function?

I have written the following Go function that produces all permutations of a boolean list of any size. Playground here.
package main
import (
"fmt"
)
func permutations(m int) [][]bool {
if m == 0 {
panic("CRASH")
}
if m == 1 {
return [][]bool{{true}, {false}}
}
retVal := [][]bool{}
for _, x := range permutations(m - 1) {
slice1 := []bool{true}
slice2 := []bool{false}
for _, y := range x {
slice1 = append(slice1, y)
slice2 = append(slice2, y)
}
retVal = append(retVal, slice1)
retVal = append(retVal, slice2)
}
return retVal
}
func main() {
fmt.Println("Hello, playground")
m := permutations(3)
fmt.Println("m = ", m)
}
Can I streamline this function by using slice unpacking? If so, how?

Slicing while unpacking slice

I have the following code
func Sum(a []int) int {
res := 0
for _, n := range a {
res += n
}
return res
}
func SumAll(ns ...[]int) (sums []int) {
for _, s := range ns {
sums = append(sums, Sum(s))
}
return
}
//SumAllTails sums [:1] in each slice
func SumAllTails(sls ...[]int) []int {
newsls := [][]int{}
for _, sl := range sls {
newsls = append(newsls, sl[1:])
}
return SumAll(newsls...)
}
Ideally I'd like to change the last function to be something like this
func SumAllTails(sls ...[]int) []int {
return SumAll(sls[:][1:]...)
}
This last bit returns each slice but the first one, but what I'd like to do is unpack each slice from position 1 onwards, omitting the value at 0. Is there a way of achieving this in go?
I think the only way to do what you want without going through the slices first is to write a SumAlln function:
func SumAlln(n int, ns ...[]int) (sums []int) {
for _, s := range ns {
sums = append(sums, Sum(s[n:]))
}
return
}
func SumAll(ns...[]int) []int {
return SumAlln(0,ns...)
}
And then call SumAlln.

goroutine value return order [duplicate]

This question already has answers here:
Golang channel output order
(4 answers)
Closed 4 years ago.
Why following codes always return 2,1, not 1,2.
func test(x int, c chan int) {
c <- x
}
func main() {
c := make(chan int)
go test(1, c)
go test(2, c)
x, y := <-c, <-c // receive from c
fmt.Println(x, y)
}
If you want to know what the order is, then let your program include ordering information
This example uses a function closure to generate a sequence
The channel returns a struct of two numbers, one of which is a sequence order number
The sequence incrementer should be safe across go routines as there is a mutex lock on the sequence counter
package main
import (
"fmt"
"sync"
)
type value_with_order struct {
v int
order int
}
var (
mu sync.Mutex
)
func orgami(x int, c chan value_with_order, f func() int) {
v := new(value_with_order)
v.v = x
v.order = f()
c <- *v
}
func seq() func() int {
i := 0
return func() int {
mu.Lock()
defer mu.Unlock()
i++
return i
}
}
func main() {
c := make(chan value_with_order)
sequencer := seq()
for n := 0; n < 10; n++ {
go orgami(1, c, sequencer)
go orgami(2, c, sequencer)
go orgami(3, c, sequencer)
}
received := 0
for q := range c {
fmt.Printf("%v\n", q)
received++
if received == 30 {
close(c)
}
}
}
second version where the sequence is called from the main loop to make the sequence numbers come out in the order that the function is called
package main
import (
"fmt"
"sync"
)
type value_with_order struct {
v int
order int
}
var (
mu sync.Mutex
)
func orgami(x int, c chan value_with_order, seqno int) {
v := new(value_with_order)
v.v = x
v.order = seqno
c <- *v
}
func seq() func() int {
i := 0
return func() int {
mu.Lock()
defer mu.Unlock()
i++
return i
}
}
func main() {
c := make(chan value_with_order)
sequencer := seq()
for n := 0; n < 10; n++ {
go orgami(1, c, sequencer())
go orgami(2, c, sequencer())
go orgami(3, c, sequencer())
}
received := 0
for q := range c {
fmt.Printf("%v\n", q)
received++
if received == 30 {
close(c)
}
}
}

Writing a nested iterator of depth d

How to realize a nested iterator that takes a depth argument. A simple iterator would be when depth = 1. it is a simple iterator which runs like a simple for loop.
func Iter () chan int {
ch := make(chan int);
go func () {
for i := 1; i < 60; i++ {
ch <- i
}
close(ch)
} ();
return ch
}
Output is 1,2,3...59
For depth = 2 Output would be "1,1" "1,2" ... "1,59" "2,1" ... "59,59"
For depth = 3 Output would be "1,1,1" ... "59,59,59"
I want to avoid a nested for loop. What is the solution here ?
I don't know if it is possible to avoid nested loops, but one solution is to use a pipeline of channels. For example:
const ITER_N = 60
// ----------------
func _goFunc1(out chan string) {
for i := 1; i < ITER_N; i++ {
out <- fmt.Sprintf("%d", i)
}
close(out)
}
func _goFuncN(in chan string, out chan string) {
for j := range in {
for i := 1; i < ITER_N; i++ {
out <- fmt.Sprintf("%s,%d", j, i)
}
}
close(out)
}
// ----------------
// create the pipeline
func IterDepth(d int) chan string {
c1 := make(chan string)
go _goFunc1(c1)
var c2 chan string
for ; d > 1; d-- {
c2 = make(chan string)
go _goFuncN(c1, c2)
c1 = c2
}
return c1
}
You can test it with:
func main() {
c := IterDepth(2)
for i := range c {
fmt.Println(i)
}
}
I usually implement iterators using closures. Multiple dimensions don't make the problem much harder. Here's one example of how to do this:
package main
import "fmt"
func iter(min, max, depth int) func() ([]int, bool) {
s := make([]int, depth)
for i := range s {
s[i] = min
}
s[0] = min - 1
return func() ([]int, bool) {
s[0]++
for i := 0; i < depth-1; i++ {
if s[i] >= max {
s[i] = min
s[i+1]++
}
}
if s[depth-1] >= max {
return nil, false
}
return s, true
}
}
func main() {
// Three dimensions, ranging between [1,4)
i := iter(1, 4, 3)
for s, ok := i(); ok; s, ok = i() {
fmt.Println(s)
}
}
Try it out on the Playground.
It'd be a simple change for example to give arguments as a single int slice instead, so that you could have per-dimension limits, if such a thing were necessary.

Resources