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
}
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)
}
}
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
}
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
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?