【问题标题】:Return an integer value when pattern matching type value in F#在 F# 中模式匹配类型值时返回整数值
【发布时间】:2017-04-21 01:58:43
【问题描述】:
let Greeting name = 
    match name with
    | "Joe" | "Bob" | "Ray" -> "Hello"
    | "Miguel" | "Jose" -> "Hola"
    | _ -> "Don't know what to say"

此模式匹配函数与字符串完美匹配,但当我尝试将其转换为比较自定义类型值时,Visual Studio 显示该函数未完成,即使语法完全相同。

type Suit = Spades | Clubs | Hearts | Diamonds
type Rank = Ace | Two | Three | Four | Five | Six | Seven | Eight | Nine | Ten | Jack | Queen | King
type Card = { suit: Suit; rank: Rank}

let cardValue (card:Card) = 
    match card.rank with
    | Ace -> 1
    | Two -> 2
    | Three -> 3
    | Four -> 4
    | Five -> 5
    | Six -> 6
    | Seven -> 7
    | Eight -> 8
    | Nine -> 9
    | Ten | Jack | Queen | King -> 10
    | _ -> 0

Visual Studio 建议添加一个明确的结果,所以我添加了一个通配符(尽管它应该是不必要的,因为没有等级集 afaik 就无法创建卡片对象)但错误仍然存​​在。

【问题讨论】:

  • 我无法重现这个。当我在 Visual Studio 中加载您的卡片匹配代码时,它告诉我 _ -> 0 行将永远不会匹配。如果我删除通配符,它​​不会给出任何错误 - 但如果我随后删除其中一个匹配项(如 Six -> 6 行),我被告知匹配不完整:“例如,值 'Six' 可能表示模式未涵盖的情况。”
  • 当您说“Visual Studio 建议添加显式结果”时,您收到的 precise 错误消息是什么?代码的哪一部分产生了错误消息(即波浪下划线出现在哪里)?另外,您使用的是哪个版本的 Visual Studio 和 Visual F# 工具?
  • @rmunn 我正在使用 Visual Studio 2017 企业版和 f# core 4.4.1.0,它给我的错误是“这个 'let' 后面的块未完成。每个代码块都是一个表达式和必须有结果。'let'不能是块中的最后一个代码元素。考虑给这个块一个明确的结果。触发它的代码是 cardValue 函数开头的“let”。
  • 啊。该错误与match 表达式无关。只是let 语句可能不是 是函数中的最后一个表达式。我会写一个更详细的答案。但是当我这样做的时候,你能粘贴你的实际代码吗?因为到目前为止您显示的代码是完全正确的,并且无法产生该错误消息;您必须至少遗漏一件事。我敢打赌你的实际代码看起来像let something = match card.rank with ...,你省略了let something = 部分以使示例代码更简单。
  • 在那种情况下,我写的答案可能是不必要的(因为你可能刚刚发现了你的问题)......但为了其他人,我还是会完成它找到这个问题。

标签: function f# pattern-matching


【解决方案1】:

您在 cmets 中所说的错误消息如下:

这个'let'后面的块是未完成的。每个代码块都是一个表达式,并且必须有一个结果。 'let' 不能是块中的最后一个代码元素。考虑给这个块一个明确的结果。

这与您的match 表达式无关,您可以安全地删除_ -> 0 行。您看到该错误是因为您在代码块中的某处有一个 let 语句,该语句后面没有另一个表达式。即,此代码不合法​​:

let f x =
    let result = x + 5

F# 中的所有函数都必须返回一个值,let 语句是 F# 中为数不多的语句而非表达式之一。 let 不返回值。因此,当您在代码块中时,您必须let 语句后面加上其他表达式,以便 返回值 的最后一个表达式功能。即:

let f x =
    let result = x + 5
    result

这是合法的。

请注意,这适用于模块级别。模块是包含值的“容器”,它们本身没有值。 (它们基本上被编译成静态类)。所以这很好:

module Foo =
    let f x = x + 1
    let value = 26

let 语句作为模块中的最后一行是完全可以的(事实上,这很正常)。但它可能不是 function(或任何其他代码块)中的最后一行,因为函数必须返回一个值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-10-29
    • 1970-01-01
    • 1970-01-01
    • 2012-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多