在尝试运行此行代码时出现错误,但我不知道为什么
let validCol column value : bool =
for i in 0..8 do
if sudokuBoard.[i,column] = value then
false
else true
答案 0 :(得分:2)
正如泰勒·哈特维格(Tyler Hartwig)所说,for
循环无法返回除unit
之外的值。
另一方面,在列表推导或seq
计算表达式中,您可以使用for
来yield
值,然后测试您要查找的值是否存在:< / p>
let validCol column value : bool =
seq { for i in 0..8 do yield sudokuBoard.[i,column] }
|> Seq.exists value
|> not
答案 1 :(得分:1)
在F#中,最后一次调用是返回的内容,您已明确声明要返回布尔值。
for
循环无法返回或聚合多个值,而用bun则返回unit
。
let validCol column value : bool =
for i in 0..8 do
if sudokuBoard.[i,column] = value then
false
else
true
在这里,您需要弄清楚如何汇总所有bool
以获得最终结果。我不太确定这应该返回什么,或者我举个例子。
答案 2 :(得分:1)
似乎您正在寻找循环的捷径,就像在C#中,您可以使用continue
,break
或return
退出循环一样。
在F#中,通过性能实现此目的的方法是使用尾递归。您可以使用while循环来实现它,但是它需要可变的变量,而尾部递归不需要可变的变量(尽管有时我们会使用它)。
tail-recursive函数是一个在最后调用自己而不看结果的函数:
所以这是尾递归的
let rec loop acc i = if i > 0 then loop (acc + i) (i - 1) else acc
不是这里的
let rec loop fib i = if i < 1 then 1 else fib (i - 1) + fib (i - 2)
如果F#编译器确定函数是尾递归的,则编译器对该函数应用尾递归优化(TCO),基本上它将其展开为高效的for循环,看起来像C#中的循环。 >
因此,这是使用尾递归编写validCol
的一种方法:
let validCol column value : bool =
// loops is tail-recursive
let rec loop column value i =
if i < 9 then
if sudokuBoard.[i,column] = value then
false // The value already exists in the column, not valid
else
loop column value (i + 1) // Check next row.
else
true // Reach the end, the value is valid
loop column value 0
很不幸; F#编译器没有强制TCO的属性(就像Scala或kotlin一样),因此,如果您犯了一个小错误,则可能会得到不是TCO的函数。我想我看到了有关添加这样的属性的GitHub问题。
PS。 seq
的综合能力在许多情况下都很好,但是对于数独求解器,我认为您正在寻找的是尽可能快的东西。 seq
理解(和LINQ)对于数独解决方案而言,我认为添加了太多的开销,而尾递归则与在F#中获得的速度一样快。
PS。在.NET中,2D数组比1D数组慢,仅是FYI。不确定使用dotnet core是否可以改善。