Can anonymous function call be called?
I just go through the Tour of Go and get to exercise on the go. Its obvious recursion, but closing the pipe is a special case after the call stack is completely shut down. Anyway, I ended up implementing it by doing this:
// Walk walks the tree t sending all values
// from the tree to the channel ch.
func Walk(t *tree.Tree, ch chan int) {
var walker func(t *tree.Tree, ch chan int)
walker = func(t *tree.Tree, ch chan int) {
if (t.Left != nil) {
walker(t.Left, ch)
}
ch <- t.Value
if (t.Right != nil) {
walker(t.Right, ch)
}
}
walker(t, ch)
close(ch)
}
My impression so far is that they prefer to avoid saying things if they can, so the declaration var walker
before definition seems to be off. Perhaps I missed some details that would allow a function to reference itself without a declaration? It would be slightly better if it were possible:
// Walk walks the tree t sending all values
// from the tree to the channel ch.
func Walk(t *tree.Tree, ch chan int) {
func(t *tree.Tree, ch chan int) {
if (t.Left != nil) {
__me__(t.Left, ch)
}
ch <- t.Value
if (t.Right != nil) {
__me__(t.Right, ch)
}
}(t, ch)
close(ch)
}
It's a simple trivia question, but I'm new enough to a language I can't find an answer in ...
source to share
I agree with @ milo-chirstiansen that an anonymous function cannot reference its instance in its declaration.
If you're trying to understand Go's idiomatic code, it might look a little different, eliminating the anonymous function:
// Walk walks the tree t sending all values
// from the tree to the channel ch.
func Walk(t *tree.Tree, ch chan int) {
Walker(t, ch)
close(ch)
}
// Walker does the things, made to be called recursively
func Walker(t *tree.Tree, ch chan int) {
if t.Left != nil {
Walker(t.Left, ch)
}
ch <- t.Value
if t.Right != nil {
Walker(t.Right, ch)
}
}
You may find this interesting ...
Go allows some cool things that are not possible in other languages. This sometimes requires thinking a little differently about your code.
Frances Campoy gave a speech at GopherCon 2016 about her legendary concept story nil
in Go. One of his examples of how to nil
be used nicely and idiomatically includes a solution to get the sum for a binary tree. Below is a link starting with this part of his conversation and I would recommend checking it out if you have time. ref: https://youtu.be/ynoY2xz-F8s?t=16m28s
I understand that you have no control over the Tree structure in your example, but if you did, this is how your code looks like: https://play.golang.com/p/iM10NQXfgw
package main
import "fmt"
// A Tree is a binary tree with integer values.
type Tree struct {
Left *Tree
Value int
Right *Tree
}
// Walk loads value into channel; caller is responsible for providing and closing chan
func (t *Tree) Walk(ch chan int) {
// Super interesting: Go supports the calling of a func on a nil instance of a struct
if t == nil {
return // return nothing
}
t.Left.Walk(ch) // recursively call Walk on left node
ch <- t.Value
t.Right.Walk(ch) // recursively call Walk on right node
}
func main() {
// Initial value for our tree; I'm not being very idiomatic with this
tree := &Tree{
Left: &Tree{Value: 2},
Value: 1,
Right: &Tree{Left: &Tree{Value: 4}, Value: 3},
}
ch := make(chan int)
// Load values into chan in separate goroutine
// to prevent blocking
go func() {
tree.Walk(ch)
close(ch)
}()
// Write each val added to chan until all values
// have been written and chan is closed
for val := range ch {
fmt.Println(val)
}
}
1
2
3
4
source to share
This can be avoided by combining runtime.Caller
and reflect.Call
.
But that nothing even looks like an idiomatic "Go", so I don't think this applies to your practical situation, although it does concern the letter of your question. :)
source to share