Golang function and function variable semantics - go

Why can't I define a recursive function as a variable? I seem to be able to define arbitrary functions except when they recurse.
This is legal:
func f(i int) int {
if i == 0 {
return 1
}
return i * f(i-1)
}
func main() {
fmt.Println(f(2))
}
This is illegal:
var f func(int) int = func(i int) int {
if i == 0 {
return 1
}
return i * f(i-1)
}
func main() {
fmt.Println(f(2))
}
This is legal and I'm guessing it is just because you can figure out f after initialization:
func main() {
var f *func(int) int;
t := func(i int) int {
if i == 0 {
return 1
}
return i * (*f)(i-1)
}
f = &t
fmt.Println((*f)(2))
}
So it looks like it comes down to function and variable declarations of a function type are treated differently though from the reading the documentation I wouldn't expect that to be the case. Did I miss the part of the documentation detailing this?
I would expect the illegal case to work just because it works in other languages. Like in JavaScript:
(function () {
var f = function (i) {
if (i == 0) {
return 1;
}
return i * f(i - 1);
};
console.log(f(2));
})();

The below code would be the preferred way of doing what you describe. Note that you do not have to create an additional variable, nor do you have a pointer to a function:
package main
import "fmt"
func main() {
var f func(int) int
f = func(i int) int {
if i == 0 {
return 1
}
return i * f(i-1)
}
fmt.Println(f(2))
}

Related

Return recursive anonymous functions in golang

I want to be able to return a recursive anonymous function in golang. I have used the code snippet below.
Here foo() doesn't work because the anonymous function has no way of referring to itself.
bar() works as expected.
What would be the right way of doing this, if at all possible?
package main
import (
"fmt"
)
func foo() func(int) int {
return func(x int) int {
if x == 1 {
return 1
}
return x * func(x-1) // this is where the problem lies
}
}
func bar() func(int) int {
return func(x int) int {
return x * 100
}
}
func main() {
a:= foo()
b:= bar()
fmt.Println(a(5))
fmt.Println(b(5))
}
You can declare f first:
func foo() func(int) int {
var f func(x int) int
f = func(x int) int {
if x == 1 {
return 1
}
return x * f(x-1)
}
return f
}

How `type Name *Name` works?

I was looking at some examples on golang.org homepage and found Peano Integers. This example defines the type Number like this:
type Number *Number
First time looking at this code I thought it should not compile, I think I haven't understood how type works in Go.
Can you explain how Go is defining type Number here? This looks very confusing to me.
Go Playground
// Peano integers are represented by a linked
// list whose nodes contain no data
// (the nodes are the data).
// http://en.wikipedia.org/wiki/Peano_axioms
// This program demonstrates that Go's automatic
// stack management can handle heavily recursive
// computations.
package main
import "fmt"
// Number is a pointer to a Number
type Number *Number
// The arithmetic value of a Number is the
// count of the nodes comprising the list.
// (See the count function below.)
// -------------------------------------
// Peano primitives
func zero() *Number {
return nil
}
func isZero(x *Number) bool {
return x == nil
}
func add1(x *Number) *Number {
e := new(Number)
*e = x
return e
}
func sub1(x *Number) *Number {
return *x
}
func add(x, y *Number) *Number {
if isZero(y) {
return x
}
return add(add1(x), sub1(y))
}
func mul(x, y *Number) *Number {
if isZero(x) || isZero(y) {
return zero()
}
return add(mul(x, sub1(y)), x)
}
func fact(n *Number) *Number {
if isZero(n) {
return add1(zero())
}
return mul(fact(sub1(n)), n)
}
// -------------------------------------
// Helpers to generate/count Peano integers
func gen(n int) *Number {
if n > 0 {
return add1(gen(n - 1))
}
return zero()
}
func count(x *Number) int {
if isZero(x) {
return 0
}
return count(sub1(x)) + 1
}
// -------------------------------------
// Print i! for i in [0,9]
func main() {
for i := 0; i <= 9; i++ {
f := count(fact(gen(i)))
fmt.Println(i, "! =", f)
}
}

Pass variable to struct function

type MultiplyStruct struct {
Number1 int
}
func (m MultiplyStruct) Multiply() int {
return m.Number1 * number2
}
how can I pass number2 to the Multiply function? Would it be like this?
var multiplier = MultiplyStruct(10)
multiplier.Multiply(20)
I think this is what you want:
package main
import (
"fmt"
)
type MultiplyStruct struct {
Number1 int
}
func (m MultiplyStruct) Multiply(number2 int) int {
return m.Number1 * number2
}
func main() {
multipler := MultiplyStruct{Number1: 10}
val := multipler.Multiply(20)
fmt.Println(val)
}
On Go Playground
Just an interesting addition to the correct answer. You can create a curried function without using a struct to store only an integer:
func Multiply(number1 int) (func(int) int) {
return func(number2 int) int {
return number1 * number2
}
}
func main() {
timesTen := Multiply(10)
fmt.Println(timesTen(20)) // => 200
timesTwo := Multiply(2)
fmt.Println(timesTwo(10)) // => 20
fmt.Println(Multiply(2)(3)) // => 6
}

Can I define a receiving method in main?

I can define a function globally,
func f()int{
return 0
}
But I can also do in main,
func main(){
var f=func()int{
return 0
}
}
Can I do the same with receiving methods? I can do globally,
type I int
func(i I)f()int{
return int(i)
}
But can I do this in main too, so like (because this does not work)
func main(){
type I int
var f=func(i I)()int{
return 0
}
}
No, not like that,
but like this working sample code you may still use f:
package main
import "fmt"
func main() {
j := I(2)
fmt.Println(j.Double())
f := j.Double
fmt.Println(f())
}
type I int
func (i I) Double() int {
return int(i) * 2
}
output:
4
4

Alternative for function overloading in Go?

Is it possible to work similar way like the function overloading or optional parameter in C# using Golang? Or maybe an alternative way?
The idiomatic answer to optional parameters in Go is wrapper functions:
func do(a, b, c int) {
// ...
}
func doSimply(a, b) {
do(a, b, 42)
}
Function overloading was intentionally left out, because it makes code hard(er) to read.
Neither function overloading nor optional arguments are directly supported. You could work around them building your own arguments struct. I mean like this (untested, may not work...) EDIT: now tested...
package main
import "fmt"
func main() {
args:=NewMyArgs("a","b") // filename is by default "c"
args.SetFileName("k")
ret := Compresser(args)
fmt.Println(ret)
}
func Compresser(args *MyArgs) string {
return args.dstFilePath + args.srcFilePath + args.fileName
}
// a struct with your arguments
type MyArgs struct
{
dstFilePath, srcFilePath, fileName string
}
// a "constructor" func that gives default values to args
func NewMyArgs(dstFilePath string, srcFilePath string) *MyArgs {
return &MyArgs{
dstFilePath: dstFilePath,
srcFilePath:srcFilePath,
fileName :"c"}
}
func (a *MyArgs) SetFileName(value string){
a.fileName=value;
}
There are some hints here using variadic arguments, for example:
sm1 := Sum(1, 2, 3, 4) // = 1 + 2 + 3 + 4 = 10
sm2 := Sum(1, 2) // = 1 + 2 = 3
sm3 := Sum(7, 1, -2, 0, 18) // = 7 + 1 + -2 + 0 + 18 = 24
sm4 := Sum() // = 0
func Sum(numbers ...int) int {
n := 0
for _,number := range numbers {
n += number
}
return n
}
Or ...interface{} for any types:
Ul("apple", 7.2, "BANANA", 5, "cHeRy")
func Ul(things ...interface{}) {
fmt.Println("<ul>")
for _,it := range things {
fmt.Printf(" <li>%v</li>\n", it)
}
fmt.Println("</ul>")
}
An approach I use sometime for constructing an object using New methods having different arguments is to have a "flavor" pseudo type. You can try it on the Go Playground https://play.golang.org/p/5To5AcY-MRe
package main
import "fmt"
type flavorA struct{}
type flavorB struct{}
var FlavorA = flavorA{}
var FlavorB = flavorB{}
type Something struct {
i int
f float64
}
func (flavor flavorA) NewSomething(i int) *Something {
return &Something{i:i, f:0.0}
}
func (flavor flavorB) NewSomething(f float64) *Something {
return &Something{i:0, f:f}
}
func main() {
fmt.Println(FlavorA.NewSomething(1), FlavorB.NewSomething(2))
}
When you have many arguments it may make sense to use a new struct for them or to define a new MyOptionBuilder type to build and store all the arguments and to construct nice defaults.
Here's a simple example where the go defaults for types are okay.
package main
import "fmt"
type FancyFuncOptions struct {
I int64
S string
F float64
//...many more...
}
func FancyFunc(opts *FancyFuncOptions) {
fmt.Println("%v", opts)
}
func main() {
// simple way
options := &FancyFuncOptions{S: "happy"}
FancyFunc(options)
In golang you'll see people using method-chaining for this, if the options have complex logic.
package main
import "fmt"
type FancyFuncOptions struct {
I int64
S string
F float64
//...many more...
}
// chaining style
func NewFancyFuncOptions() *FancyFuncOptions {
return &FancyFuncOptions{I: 100, S: "empty", F: 0.1}
}
func (o *FancyFuncOptions) SetI(i int64) *FancyFuncOptions {
o.I = i
return o
}
func (o *FancyFuncOptions) SetS(s string) *FancyFuncOptions {
o.S = s
return o
}
func FancyFunc(opts *FancyFuncOptions) {
fmt.Println("%v", opts)
}
func main() {
// fancier
options = NewFancyFuncOptions().SetI(234).SetS("happy")
FancyFunc(options)
(https://go.dev/play/p/Ae_6Y6kZa97)
Make sense?

Resources