I'm getting an error saying "undefined isvalid". How do I call another function in a function?
package main
import "fmt"
type Position struct {
row int
col int
}
func (posstn Position) isvalid() bool {
if posstn.row > 8 || posstn.row < 0 || posstn.col > 8 || posstn.col < 0 {
return false
}
return true
}
func Possmov(pos Position) {
var isval isvalid
if isval == true {
fmt.Println("Something")
}
}
func main() {
Possmov(Position{1, 7})
}
you may call isvalid() like this pos.isvalid() see this working sample code:
package main
import "fmt"
type Position struct {
row int
col int
}
func (posstn Position) isvalid() bool {
if posstn.row > 8 || posstn.row < 0 || posstn.col > 8 || posstn.col < 0 {
return false
}
return true
}
func Possmov(pos Position) {
isval := pos.isvalid()
if isval == true {
fmt.Println("Something")
}
}
func main() {
Possmov(Position{1, 7}) //Something
}
Your first line in function Possmov(pos Position){...} i.e. var isval isvalid is actually attempting to declare a variable of type isvalid (which is undefined as described by the error)
Instead your isvalid() method is declared on the Position type.
Try: var isvalid = pos.isvalid() in it's place
Your defined var isval isvalid, while isvalid is not a known type in Go, instead:
func Possmov(pos Position) {
var isval bool // default is false
if isval == true {
fmt.Println("Something")
}
}
https://play.golang.org/p/Ml2PgEOZfV
Related
This question already has answers here:
Set an int pointer to an int value in Go
(6 answers)
Closed last month.
I need map the struct to create a JSON structure. The collector_id attribute in JSON should be able to take null value or int value.
I hace the follow code:
type purchaseInfo struct {
CollectorID *int64 `json:"collector_id"`
}
func mapPurchaseInfo(collectorID int64) purchaseInfo {
var collectorIDToSend *int64
if collectorID < 0 {
collectorIDToSend = nil
} else {
collectorIDToSend = collectorID
}
return purchaseInfo{
CollectorID: collectorIDToSend,
}
}
This code doesn't compile, the collectorID can't be assigned to collectorIDToSend.
Is there a way to be able to do this?
Thanks!
In the declaration of the mapPurchaseInfo function, to correctly assign the value passed in parameter to collectorIDToSend, the & operator must be used to retrieve the memory address of collectorID.
When constructing the purchaseInfo return variable, it is possible to put the fields of the structure directly as in the example.
type purchaseInfo struct {
CollectorID *int64 `json:"collector_id"`
}
func mapPurchaseInfo(collectorID int64) purchaseInfo {
var collectorIDToSend *int64
if collectorID < 0 {
collectorIDToSend = nil
} else {
collectorIDToSend = &collectorID
}
return purchaseInfo{
CollectorID: collectorIDToSend,
}
}
type purchaseInfo struct {
CollectorID *int64 `json:"collector_id"`
}
func mapPurchaseInfo(collectorID *int64) purchaseInfo {
if *collectorID < 0 {
return purchaseInfo{CollectorID: nil}
}
return purchaseInfo{
CollectorID: collectorID,
}
}
My problem comes from an error handler that I need to write. The handler is meant to catch an error, do an action 'A', and then proceed to retry the original function that failed in the first place. The blocker comes when I need to generalise the handler to be able to accept any function definition.
For example:
fun foo(a: Any) {
// Do something and return null if unsuccessful
}
fun bar(b: Any, c: Any) {
// Do something else and return false if unsuccessful
}
fun handler(fn: Function???, args: Array[arguments???]) {
log.warn("Error has been caught at <${functionName}>, doing action A and retrying")
// Do action A
log.warn("Retrying <${functionName}>")
fn(args)
}
fun main() {
val resultFoo = foo('bar')
if (resultFoo == null) {
handler(foo, ['bar'])
}
val resultBar = bar('foo', { 'foo': 'bar' })
if (!resultBar) {
handler(bar, ['foo', { 'foo': 'bar' }])
}
}
As you can see, I have two functions foo and bar with different definitions which I would like to be able to call from handler. Otherwise I would need to copy-paste the body inside handler to each individual function and handle the error inside there. I was hoping to be able to generalise this and be able to reuse it.
If you want to avoid reflection, which would provide no compile-time error checking, you should overload your function to have variants with different numbers of variables. Then you can use generics, and you'll get compile-time checking.
There's not a clean way to pass functions along with their names, so I made the name for logging a separate argument in this example.
// zero args handler
inline fun <R> handler(loggedFunctionName: String?, fn: ()->R): R {
val functionName = "<$loggedFunctionName>" ?: "function"
log.warn("Error has been caught at $functionName, doing action A and retrying")
// Do action A
log.warn("Retrying $functionName")
return fn()
}
// one arg handler
inline fun <A, R> handler(loggedFunctionName: String?, fn: (A)->R, argA: A): R
= handler(loggedFunctionName) { fn(argA) }
// two args handler
inline fun <A, B, R> handler(loggedFunctionName: String?, fn: (A, B)->R, argA: A, argB: B): R
= handler(loggedFunctionName) { fn(argA, argB) }
fun main() {
val resultFoo = foo("bar")
if (resultFoo == null) {
handler("foo", ::foo, "arg")
}
val resultBar = bar("arg1", "arg2")
if (!resultBar) {
handler("bar", ::bar, "arg1", "arg2")
}
}
However, it seems you could reduce boilerplate further by incorporating your logical test of the result as another argument:
// zero args handler
inline fun <R> handler(loggedFunctionName: String?, fn: ()->R, verifyResult: (R)->Boolean): R {
val firstResult = fn()
if (verifyResult(firstResult)){
return firstResult
}
val functionName = "<$loggedFunctionName>" ?: "function"
log.warn("Error has been caught at $functionName, doing action A and retrying")
// Do action A
log.warn("Retrying $functionName")
return fn()
}
// one arg handler
inline fun <A, R> handler(loggedFunctionName: String?, fn: (A)->R, verifyResult: (R)->Boolean, argA: A): R
= handler(loggedFunctionName, { fn(argA) }, verifyResult)
// two args handler
inline fun <A, B, R> handler(loggedFunctionName: String?, fn: (A, B)->R, verifyResult: (R)->Boolean, argA: A, argB: B): R
= handler(loggedFunctionName, { fn(argA, argB) }, verifyResult)
fun main() {
handler("foo", ::foo, { it != null }, "arg")
handler("bar", ::bar, { it }, "arg1", "arg2")
}
First of all you need to know, what exactly you want to generalize.
As I can see from your example, you want to repeat function call with same arguments. So instead all this messing with argument-arrays you can wrap payload (function call with arguments) into lambda and call it twice.
Second question is repeat condition. In foo it's result == null, in bar it's result == false. So condition is different for different functions. You can calculate condition in separate lambda.
So you can write something like this:
fun <T, F: KFunction<*>> F.callAndRepeatOnCondition (
payload: (F) -> T,
condition: (T) -> Boolean,
): T {
var result = payload(this)
if (condition(result)) {
println("log: doing something and repeat function ${this.name} ")
println("some super logic before repeat")
result = payload(this)
}
return result
}
fun foo(a: Int, b: String): String? { return null }
fun bar(c: Int): Boolean { return false }
fun main() {
val resultFoo = ::foo.callAndRepeatOnCondition({ it(1, "a") }, { it == null })
val resultBar = ::bar.callAndRepeatOnCondition({ it(2) }, { !it })
}
PS. If you don't need to log function name or can pass it explicitly, here is a little less ugly solution:
fun foo(a: Int, b: String): String? { return null }
fun bar(c: Int): Boolean { return false }
fun <T> (() -> T).repeatIf(condition: (T) -> Boolean): T {
val result = this()
if (!condition(result)) return result
println("some super logic before repeat")
return this()
}
fun <T> (() -> T).repeatWithLoggingIf(logName: String, condition: (T) -> Boolean): T {
val result = this()
if (!condition(result)) return result
println("log: repeating $logName")
println("some super logic before repeat")
return this()
}
fun main() {
run { // without logName
val resultFoo = { foo(1, "a") }.repeatIf { it == null }
val resultBar = { bar(2) }.repeatIf { !it }
}
run { // with logName
val resultFoo = { foo(1, "a") }.repeatWithLoggingIf("foo") { it == null }
val resultBar = { bar(2) }.repeatWithLoggingIf("bar") { !it }
}
}
I found something interesting in Go. Let's say I have my package name is mypkg, inside mypkg, I have two functions:
package mypkg
func MyFunc0(){
//...
}
var MyFunc1 = func(){
//...
}
Now in my main package, it is possible to override MyFunc1, like this:
mypkg.MyFunc1 = func(){
// new logic
}
However, it is not possible to override MyFunc0 the same way. So now a question is raised. What are the differences between the two ways of declaring a function? Is this behavior difference intended?
MyFunc0 is a function declaration (https://golang.org/ref/spec#Function_declarations)
MyFunc1 is not a function declaration. It is a variable (https://golang.org/ref/spec#Variable_declarations) of type func (see https://golang.org/ref/spec#Function_types, https://golang.org/ref/spec#Function_literals). It has an initial value, but can be changed to hold a different value/function (as long as function signatures match).
I learning go language (and English :P), and in the tour of go is a exersie: Fibonacci closure
(https://tour.golang.org/moretypes/22)
The result is:
0
1
1
2
3
5
8
13
21
34
The main function is:
func main() {
f := fibonacci()
for i := 0; i < 10; i++ {
fmt.Println(f())
}
}
And my first solution was:
func fibonacci() func() int {
antant := 0
ant := 1
i := 0
return func() int {
var result int
if i == 0 || i == 1 {
result = i
i++
return result
}
result = antant + ant
antant = ant
ant = result
return result
}
}
But I didn't want ask in heach call to f() if was the firsth or second call (if i == 0 || i == 1). The result was a function auto-override:
type doFibonacci func(*doFibonacci) int
func fibonacci() func() int {
antant := 0
ant := 1
i := 0
doFibo := doFibonacci(func(ptrDo *doFibonacci) int {
var result int
if i == 0 || i == 1 {
result = i
i++
return result
}
*ptrDo = func(ptrDo *doFibonacci) int {
var result int
result = antant + ant
antant = ant
ant = result
return result
}
return (*ptrDo)(ptrDo)
})
return func() int {
return doFibo(&doFibo)
}
}
I apologize for my English.
Is there any difference in swift between function declaration:
func function(a: String) {
print(a);
}
function("test");
and closure assignment:
let closure = {
(a: String) in
print(a);
}
closure("test");
Is there any difference between those?
Named or anonymous
func function(a: String) {
print("\(a), name: \(__FUNCTION__)");
}
let closure = { (a: String) in
print("\(a), name: \(__FUNCTION__)");
}
Capture List
supported in closures only:
let obj = FooClass()
let closure = { [weak obj] in ... }
Curried function
supported in functions only:
func curriedFunc(x:Int)(y:Int) { ... }
let curried = curriedFunc(1)
curried(y:2)
Similar, but not exact the same with using closure:
let closure = { (x:Int) in { (y:Int) in ... }}
Generics
supported in functions only:
func function<T>(x:T) { ... }
Referenceability from its own initial declaration
supported in global functions only:
func recursive(var x:Int) -> Int {
...
return condition ? x : recursive(x)
}
You can do this using closure also:
var recursive:((Int) -> Int)!
recursive = { (var x) in
...
return condition ? x : recursive(x)
}
But this is not recommended because this causes strong reference cycles.
Overload
supported in functions only:
func function(a: String) { print("String: \(a)") }
func function(a: Float) { print("Float: \(a)") }
n.b. You can reference them as a closure like this:
let f:(Float) -> Void = function
Another difference: recursivity inside another function
Nested functions cannot be recursive:
func foo() {
func bar() { bar() } // does not compile
}
but closures inside other functions can be recursive:
func foo() {
var bar: (() -> ())!
bar = { bar() }
}
In Java I can do something like
derp(new Runnable { public void run () { /* run this sometime later */ } })
and "run" the code in the method later. It's a pain to handle (anonymous inner class), but it can be done.
Does Go have something that can facilitate a function/callback being passed in as a parameter?
Yes, consider some of these examples:
package main
import "fmt"
// convert types take an int and return a string value.
type convert func(int) string
// value implements convert, returning x as string.
func value(x int) string {
return fmt.Sprintf("%v", x)
}
// quote123 passes 123 to convert func and returns quoted string.
func quote123(fn convert) string {
return fmt.Sprintf("%q", fn(123))
}
func main() {
var result string
result = value(123)
fmt.Println(result)
// Output: 123
result = quote123(value)
fmt.Println(result)
// Output: "123"
result = quote123(func(x int) string { return fmt.Sprintf("%b", x) })
fmt.Println(result)
// Output: "1111011"
foo := func(x int) string { return "foo" }
result = quote123(foo)
fmt.Println(result)
// Output: "foo"
_ = convert(foo) // confirm foo satisfies convert at runtime
// fails due to argument type
// _ = convert(func(x float64) string { return "" })
}
Play: http://play.golang.org/p/XNMtrDUDS0
Tour: https://tour.golang.org/moretypes/25 (Function Closures)
You can pass function as parameter to a Go function. Here is an example of passing function as parameter to another Go function:
package main
import "fmt"
type fn func(int)
func myfn1(i int) {
fmt.Printf("\ni is %v", i)
}
func myfn2(i int) {
fmt.Printf("\ni is %v", i)
}
func test(f fn, val int) {
f(val)
}
func main() {
test(myfn1, 123)
test(myfn2, 321)
}
You can try this out at: https://play.golang.org/p/9mAOUWGp0k
Here is the sample "Map" implementation in Go. Hope this helps!!
func square(num int) int {
return num * num
}
func mapper(f func(int) int, alist []int) []int {
var a = make([]int, len(alist), len(alist))
for index, val := range alist {
a[index] = f(val)
}
return a
}
func main() {
alist := []int{4, 5, 6, 7}
result := mapper(square, alist)
fmt.Println(result)
}
Here is a simple example:
package main
import "fmt"
func plusTwo() (func(v int) (int)) {
return func(v int) (int) {
return v+2
}
}
func plusX(x int) (func(v int) (int)) {
return func(v int) (int) {
return v+x
}
}
func main() {
p := plusTwo()
fmt.Printf("3+2: %d\n", p(3))
px := plusX(3)
fmt.Printf("3+3: %d\n", px(3))
}
This is the simplest way I can come with.
package main
import "fmt"
func main() {
g := greeting
getFunc(g)
}
func getFunc(f func()) {
f()
}
func greeting() {
fmt.Println("Hello")
}
I hope the below example will provide more clarity.
package main
type EmployeeManager struct{
category string
city string
calculateSalary func() int64
}
func NewEmployeeManager() (*EmployeeManager,error){
return &EmployeeManager{
category : "MANAGEMENT",
city : "NY",
calculateSalary: func() int64 {
var calculatedSalary int64
// some formula
return calculatedSalary
},
},nil
}
func (self *EmployeeManager) emWithSalaryCalculation(){
self.calculateSalary = func() int64 {
var calculatedSalary int64
// some new formula
return calculatedSalary
}
}
func updateEmployeeInfo(em EmployeeManager){
// Some code
}
func processEmployee(){
updateEmployeeInfo(struct {
category string
city string
calculateSalary func() int64
}{category: "", city: "", calculateSalary: func() int64 {
var calculatedSalary int64
// some new formula
return calculatedSalary
}})
}
You can also pass the function of a struct, like:
package main
// define struct
type Apple struct {}
// return apple's color
func (Apple) GetColor() string {
return "Red"
}
func main () {
// instantiate
myApple := Apple{}
// put the func in a variable
theFunc := myApple.GetColor
// execute the variable as a function
color := theFunc()
print(color)
}
output will be "Red", check on the playground
Yes Go does accept first-class functions.
See the article "First Class Functions in Go" for useful links.