使用类型约束的泛型:无法将false(无类型的bool常量)用作赋值中的T值

huangapple go评论65阅读模式
英文:

Go generics with type constraints: cannot use false (untyped bool constant) as T value in assignment

问题

我有以下一段代码:

func createGrid[T int | bool](size int, forFlooded bool) [][]T {
	var tempGrid [][]T

	for i := 0; i <= size+1; i++ {
		for j := 0; j <= size+1; j++ {
			if forFlooded {
				tempGrid[i][j] = false
			} else {
			    tempGrid[i][j] = -1
            }
		}
	}
	return tempGrid
}

在我给tempGrid[i][j]赋值的行上,我得到以下错误:

cannot use false (untyped bool constant) as T value in assignment
cannot use -1 (untyped int constant) as T value in assignment

这是我使用它的方式:

var grid [][]int;
grid = createGrid(n, false);
var flooded [][]bool;
flooded = createGrid(n, true);

在这里,我得到了CannotInferTypeArgs(无法推断T)的错误。

我还尝试将类型约束提取到一个接口中。我做错了什么?

更新:

根据@kraylog的建议,我使用了以下解决方法:

func initialiseGrid[T int | bool](size int, fn func(i, j, size int) T) [][]T {
	var tempGrid [][]T

	for i := 0; i <= size+1; i++ {
		for j := 0; j <= size+1; j++ {
			tempGrid[i][j] = fn(i, j, size)
		}
	}
	return tempGrid
}
// 在某个函数体中:
grid := initialiseGrid(n, func(i, j, size int) int {
	if i == 0 || i == size+1 || j == 0 || j == size+1 {
		return -1
	} else {
		return int(math.Floor(rand.Float64() * 6))
	}
})
flooded := initialiseGrid(n, func(i, j, size int) bool { return false })
英文:

I have the following piece of code:

func createGrid[T int | bool](size int, forFlooded bool) [][]T {
	var tempGrid [][]T

	for i := 0; i &lt;= size+1; i++ {
		for j := 0; j &lt;= size+1; j++ {
			if forFlooded {
				tempGrid[i][j] = false
			} else {
			    tempGrid[i][j] = -1
            }
		}
	}
	return tempGrid
}

I get the following errors on the lines where I'm assigning tempGrid[i][j]:

cannot use false (untyped bool constant) as T value in assignment
cannot use -1 (untyped int constant) as T value in assignment

This is how I'm using it:

var grid [][]int;
grid = createGrid(n, false);
var flooded [][]bool;
flooded = createGrid(n, true);

Here, I get CannotInferTypeArgs (cannot infer T) error.

I've also tried extracting that type constraint to an interface.
What am I doing wrong?

Update:

Taking @kraylog's suggestions, I solved it using this:

func initialiseGrid[T int | bool](size int, fn func(i, j, size int) T) [][]T {
	var tempGrid [][]T

	for i := 0; i &lt;= size+1; i++ {
		for j := 0; j &lt;= size+1; j++ {
			tempGrid[i][j] = fn(i, j, size)
		}
	}
	return tempGrid
}
// In some function body:
grid := initialiseGrid(n, func(i, j, size int) int {
	if i == 0 || i == size+1 || j == 0 || j == size+1 {
		return -1
	} else {
		return int(math.Floor(rand.Float64() * 6))
	}
})
flooded := initialiseGrid(n, func(i, j, size int) bool { return false })

答案1

得分: 3

泛型是编译器为你提供的一种快捷方式,用于为不同类型创建多个相同函数的实例。

让我们尝试手动完成编译器的工作。你将得到这两个函数 - 一个用于 int 类型:

func createGridInt(size int, forFlooded bool) [][]int {
    var tempGrid [][]int

    for i := 0; i <= size+1; i++ {
        for j := 0; j <= size+1; j++ {
            if forFlooded {
                tempGrid[i][j] = false
            } else {
                tempGrid[i][j] = -1
            }
        }
    }
    return tempGrid
}

和一个用于 bool 类型:

func createGridBool(size int, forFlooded bool) [][]bool {
    var tempGrid [][]bool

    for i := 0; i <= size+1; i++ {
        for j := 0; j <= size+1; j++ {
            if forFlooded {
                tempGrid[i][j] = false
            } else {
                tempGrid[i][j] = -1
            }
        }
    }
    return tempGrid
}

突然间,这不再有意义,因为你不能像第一个函数中那样将 false 赋给 int,也不能在第二个函数中反过来赋值。

为了解决这个问题,你需要使用 T 作为你正在处理的类型。这也解决了将布尔标志传递给函数的代码问题:

func createGrid[T int | bool](size int, fillWith T) [][]T {
    var tempGrid [][]T

    for i := 0; i <= size+1; i++ {
        for j := 0; j <= size+1; j++ {
            tempGrid[i][j] = fillWith
        }
    }
    return tempGrid
}

你可以这样调用它:

createGrid(n, false)
createGrid(n, -1)
英文:

Generics are a shortcut the compiler gives you for creating multiple instances of the same function, for different types.

Let's try to do the compiler's work manually. You'll get these two functions - one for int:

func createGridInt(size int, forFlooded bool) [][]int {
    var tempGrid [][]int

    for i := 0; i &lt;= size+1; i++ {
        for j := 0; j &lt;= size+1; j++ {
            if forFlooded {
                tempGrid[i][j] = false
            } else {
                tempGrid[i][j] = -1
            }
        }
    }
    return tempGrid
}

and one for bool:

func createGridBool(size int, forFlooded bool) [][]bool {
    var tempGrid [][]bool

    for i := 0; i &lt;= size+1; i++ {
        for j := 0; j &lt;= size+1; j++ {
            if forFlooded {
                tempGrid[i][j] = false
            } else {
                tempGrid[i][j] = -1
            }
        }
    }
    return tempGrid
}

Suddenly, this doesn't make sense anymore, since you can't assign false to int as in the first function, and the other way around in the second.

To solve the problem, you need to use T as the type you're working on. This also solves the code smell of passing a boolean flag to a function:

func createGrid[T int | bool](size int, fillWith T) [][]T {
    var tempGrid [][]T

    for i := 0; i &lt;= size+1; i++ {
        for j := 0; j &lt;= size+1; j++ {
            tempGrid[i][j] = fillWith
        }
    }
    return tempGrid
}

And you can call this with:

createGrid(n, false)
createGrid(n, -1)

huangapple
  • 本文由 发表于 2022年3月23日 13:49:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/71582372.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定