为什么这个F#函数的参数值似乎变为0?

时间:2012-11-21 23:51:35

标签: parameters f# matching

我正在尝试编写一个用于构建专用卡片组的递归函数。第一个参数numOfCards应该是牌组中的牌数。 sourceDeck是可用于构建套牌的可能卡的列表,currentDeck是我的累加器,这将产生最终的卡片列表。

但是,我遇到的问题是当我为numOfCards发送一个数字值时,它会在match语句中设置为0。或者至少它看起来如何。我尝试使用调试器,当我输入函数时,值是正确的。然而,一旦我开始执行匹配,它突然变为0,如果我将鼠标悬停在匹配中的值和参数中的值(至少是一致的)上。

因此,匹配在0上触发,只返回空的currentDeck,而不是迭代。

关于这个的任何提示?可能是简单的事情,但我很难过。 :)

let rec buildDungeon (numOfCards, sourceDeck : List<Card>, currentDeck : List<Card>) =
  match currentDeck.Length with
    | numOfCards  -> currentDeck
    | _           -> buildDungeon (numOfCards, sourceDeck, newCard(sourceDeck)::currentDeck)

3 个答案:

答案 0 :(得分:5)

如果您想在currentDeck.Length 等于 numOfCards时处理案例,那么您需要写一下:

let rec buildDungeon (numOfCards, sourceDeck : List<Card>, currentDeck : List<Card>) =
  match currentDeck.Length with
  | n when n = numOfCards -> currentDeck
  | _ -> buildDungeon (numOfCards, sourceDeck, newCard(sourceDeck)::currentDeck)

问题在于,当您编写子句| numOfCards -> (...)时,模式匹配会将currentDeck.Length的值绑定到符号numOfCards(并且新定义的numOfCards值会隐藏同名的前一个值 - 即您作为参数获得的值。)

我上面写的模式匹配将currentDeck.Length绑定到 new 符号n,然后检查n = numOfCards(指的是numOfCards已通过作为一个论点)。

因此,模式匹配并不是检查相等性的最佳工具 - 您的代码可能更容易使用普通if编写:

let rec buildDungeon (numOfCards, sourceDeck : List<Card>, currentDeck : List<Card>) =
  if currentDeck.Length = numOfCards then currentDeck
  else buildDungeon (numOfCards, sourceDeck, newCard(sourceDeck)::currentDeck)

答案 1 :(得分:1)

numOfCards表达式中的match与参数中的{{1}}不同:它是阴影旧表达式的新变量。因为它是一个无界的变量模式,它将匹配任何东西并将自己绑定到那个东西。因此,永远不会达到第二个(通配符)模式,因为第一个模式永远不会失败。

答案 2 :(得分:1)

据我了解F#中的模式匹配,你应该使用

let rec buildDungeon (numOfCards, sourceDeck : List<Card>, currentDeck : List<Card>) =
  match currentDeck.Length with
  | n when n = numOfCards -> currentDeck
  | _ -> buildDungeon (numOfCards, sourceDeck, newCard(sourceDeck)::currentDeck)

通过指定创建新变量的模式排序(本例中为n)。您没有使用已定义的。