英文:
Calling a generic function type: invalid operation: cannot call non-function fn
问题
我将发布我目前正在处理的代码示例。我遇到了错误:
error: invalid operation: cannot call non-function fn (variable of type MF constrained by MapFunc)
是否可以使用包含不同函数签名的约束以这种方式使用?(如果可能的话,我想先了解如何使我编写的代码正常工作。)
以下是示例代码:
package main
import "fmt"
// MapFunc constraint used in Funcy
type MapFunc interface {
func(s string, ss []string) []string | func(s string, ss []string) []bool
}
// MapFuncType used for Funcy return constraint
type MapFuncType interface {
string | bool
}
// Funcy preforms map operation on generic map functions
func Funcy[MF MapFunc, MFT MapFuncType](s string, ss []string, fn MF) []MFT {
return fn(s, ss)
// error: invalid operation: cannot call non-function fn (variable of type
// MF constrained by MapFunc)
}
// appendTo adds given string to the end of each index of given slice of strings
// Ex. appendTo("_", []string{"append", "to"}) --> []string{"append_", "to_"}
func appendTo(s string, ss []string) []string {
var slice []string
for _, v := range ss {
slice = append(slice, v+s)
}
return slice
}
// isMatch checks given string against each index in given string slice for a
// match
// Ex. isMatch("hi", []string{"hello", "hi"}) --> []bool{false, true}
func isMatch(s string, ss []string) []bool {
var slice []bool
for _, v := range ss {
slice = append(slice, s == v)
}
return slice
}
func main() {
slice1 := []string{"append", "to"}
slice2 := []string{"hello", "hi"}
fmt.Println(Funcy(slice1, appendTo))
// want: []string{"append_", "to_"}
// got: error: cannot infer MFT
fmt.Println(Funcy(slice2, isMatch))
//[]bool{false, true}
// got: error: cannot infer MFT
}
英文:
I'll post the code example that I am currently working on. I got the error:
> error: invalid operation: cannot call non-function fn (variable of type MF constrained by MapFunc)
Is it possible to use constraints that contain different function signatures to be used in this way? (I would like to understand how to get what I have written to work first if at all possible.)
Here is the example:
package main
import "fmt"
// MapFunc constraint used in Funcy
type MapFunc interface {
func(s string, ss []string) []string | func(s string, ss []string) []bool
}
// MapFuncType used for Funcy return constraint
type MapFuncType interface {
string | bool
}
// Funcy preforms map operation on generic map functions
func Funcy[MF MapFunc, MFT MapFuncType](s string, ss []string, fn MF) []MFT {
return fn(s, ss)
// error: invalid operation: cannot call non-function fn (variable of type
// MF constrained by MapFunc)
}
// appendTo adds given string to the end of each index of given slice of strings
// Ex. appendTo("_", []string{"append", "to"}) --> []string{"append_", "to_"}
func appendTo(s string, ss []string) []string {
var slice []string
for _, v := range ss {
slice = append(slice, v+s)
}
return slice
}
// isMatch checks given string against each index in given string slice for a
// match
// Ex. isMatch("hi", []string{"hello", "hi"}) --> []bool{false, true}
func isMatch(s string, ss []string) []bool {
var slice []bool
for _, v := range ss {
slice = append(slice, s == v)
}
return slice
}
func main() {
slice1 := []string{"append", "to"}
slice2 := []string{"hello", "hi"}
fmt.Println(Funcy(slice1, appendTo))
// want: []string{"append_", "to_"}
// got: error: cannot infer MFT
fmt.Println(Funcy(slice2, isMatch))
//[]bool{false, true}
// got: error: cannot infer MFT
}
答案1
得分: 2
当你将类型参数MF
约束为MapFunc
时,你无法调用fn
,因为MapFunc
类型集中的函数类型没有相同的签名。它们具有不同的返回类型[]string
和[]bool
。
因此,类型为fn
的变量实际上不支持调用,你会得到一个(稍微晦涩的)错误消息"cannot call non-function fn"。
更正式地说,只有具有核心类型为函数类型的值才能被调用,但约束MapFunc
没有核心类型。
修复的方法是将MapFunc
参数化,并将该类型参数用作返回值,这样在实例化时,它将具有核心类型:
type MapFunc[T MapFuncType] interface {
func(s string, ss []string) []T
}
并在Funcy
中使用MFT
实例化约束:
func Funcy[MF MapFunc[MFT], MFT MapFuncType](s string, ss []string, fn MF) []MFT {
return fn(s, ss)
}
Playground: https://go.dev/play/p/q88aJLgnzXZ
英文:
When you constrain the type param MF
to MapFunc
, you can't call fn
because the function types in MapFunc
's type set don't have the same signature. They have different return types []string
and []bool
.
So the variable of type fn
effectively does not support being called, and you get the (slightly cryptic) error message "cannot call non-function fn".
More formally, only a value that has a core type of type function can be called, but the constraint MapFunc
doesn't have a core type.
The fix would be to parametrize MapFunc
and use that type parameter as the return value, so that upon instantiation, it would have a core type:
type MapFunc[T MapFuncType] interface {
func(s string, ss []string) []T
}
And instantiate the constraint with MFT
in Funcy
:
func Funcy[MF MapFunc[MFT], MFT MapFuncType](s string, ss []string, fn MF) []MFT {
return fn(s, ss)
}
Playground: https://go.dev/play/p/q88aJLgnzXZ
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论