为什么这个F#嵌套匹配表达式不能正常工作?
现在,我有一个行为异常的嵌套模式匹配 下面是代码片段为什么这个F#嵌套匹配表达式不能正常工作?,f#,pattern-matching,F#,Pattern Matching,现在,我有一个行为异常的嵌套模式匹配 下面是代码片段 match setting with | "-f" | "--file" -> // Open file ({ state with file = Some (cur_dir + "\\" + elem) }, "") | "" -> // Option without parameter match elem with | "-h" |
match setting with
| "-f" | "--file" -> // Open file
({ state with file = Some (cur_dir + "\\" + elem) }, "")
| "" -> // Option without parameter
match elem with
| "-h" | "--help" -> // Display help message
({ state with help = true }, "")
| "-r" | "--readonly" -> // Open with readonly
({ state with readonly = true }, "")
| opt -> (state, opt)
| _ -> (state, "") // Ignore invalid option
不幸的是,在编译上述代码时,我收到了两个警告。其中一个声明最终的通配符模式是不可访问的。另一个声明第一个匹配语句不完整
这两个警告似乎相互冲突,如果我添加括号以使表达式更清晰,警告将消失,代码正常工作
match setting with
| "-f" | "--file" -> // Open file
({ state with file = Some (cur_dir + "\\" + elem) }, "")
| "" -> // Option without parameter
( match elem with
| "-h" | "--help" -> // Display help message
({ state with help = true }, "")
| "-r" | "--readonly" -> // Open with readonly
({ state with readonly = true }, "")
| opt -> (state, opt) )
| _ -> (state, "") // Ignore invalid option
我的问题是:原始代码有什么问题?这不是一个放错括号的情况,对于编译器来说,每个匹配结束的地方似乎应该是显而易见的
编辑:这是完整的函数,以防有帮助
let process_args argv =
let (result, _) = ((default_settings, "-f"), argv) ||>
Array.fold (fun (state, setting) elem ->
match setting with
| "-f" | "--file" -> // Open file
({ state with file = Some (cur_dir + "\\" + elem) }, "")
| "" -> // Option without parameter
match elem with
| "-h" | "--help" -> // Display help message
({ state with help = true }, "")
| "-r" | "--readonly" -> // Open with readonly
({ state with readonly = true }, "")
| opt -> (state, opt)
| _ -> (state, "") // Ignore invalid option
) in
result
我还应该注意,这个错误发生在轻量级和冗长的语法中
Edit2:我错误地粘贴了一个稍有改动的函数,这导致了一些编译错误,而不仅仅是警告。我道歉 当我将您的完整函数复制到VS代码中时,我得到两个错误,都是由相同的缩进错误引起的:
let process_args argv =
let (result, _) = ((default_settings, "-f"), argv)
||> Array.fold (fun (state, setting) elem ->
// (snip rest of function)
这两个错误分别出现在let(result,)=…
的let
和|124;>
操作符上。let
上的错误为:
不完整的值或函数定义。如果它位于表达式中,则表达式体必须缩进到与“let”关键字相同的列中
而| |>
上的错误是:
绑定中出现意外的中缀运算符。在此点或其他标记处或之前应为不完整的结构化构造
实际上,这两个错误都无助于帮助您找出错误所在,因为实际原因是在使用|124;>
运算符时出现了一个简单的缩进错误
根据,需要将“管道”操作符(|>
,|>
,等等)缩进到与它们所操作的表达式相同的级别。在代码中,| |>
运算符缩进在(结果,|)
元组下。但这个元组实际上并不是| |>
要操作的对象;该元组是赋值的目标。| |>
操作的表达式是((默认设置,“-f”),argv)
元组。因此,您应该将代码缩进如下:
let process_args argv =
let (result, _) = ((default_settings, "-f"), argv)
||> Array.fold (fun (state, setting) elem ->
// (snip rest of function)
否则:
let process_args argv =
let (result, _) =
((default_settings, "-f"), argv)
||> Array.fold (fun (state, setting) elem ->
// (snip rest of function)
第二个更好,IMHO。你的例子对我来说很好。几乎可以肯定这是一个缩进错误。该示例是直接从源代码复制和粘贴的。此外,无论我是否使用
#light“off”
将匹配语句复制到VS代码中,Ionide插件都不会向我显示任何警告。但是,当我复制完整的process\u args
函数时,我在let
语句中得到一个缩进错误。我会写一个完整的答案,但简短的版本(这样你就不必等待)是:移动你的((默认设置,等等。
将元组下放到下一行,并将其缩进四个空格,不做其他更改,代码应该可以工作。顺便说一句,如果你做了很多参数解析,就会有问题。谢谢你的回复。这修复了如果light语法打开的警告。如果light关闭,它仍然会给出匹配的警告。另外,如果light语法打开并且| |>
操作符与let绑定在同一行,它将给出匹配警告。这是一个令人费解的警告……我还应该提到,我弄错了,并将错误的代码复制到了原始帖子中。当我运行| |>
操作符并得到警告时,我的代码中的操作符与let绑定在同一行。我不知道我为什么要更改它。我会修复它。对于这个错误,我很抱歉!如果您试图用详细的语法编写F(即,使用#light“off”
),我想你会发现很少有人再熟悉语法的细节了。light语法已经成为F#代码的默认和事实标准。除非你正在做一些事情,比如从另一种ML语言复制和粘贴代码,并希望它能在最小的改动下工作,否则我强烈建议你只学习F#的light举个例子:我刚刚花了5-10分钟在网上寻找有关详细语法中匹配表达式的任何参考,以及如何终止它们。(因为,正如您已经了解到的,详细语法的编译器认为第一个匹配表达式的最后一个
大小写实际上是第二个匹配表达式的一部分)。我没有找到任何引用来告诉我是否有比将第二个匹配表达式括在括号中更好的方法。正如您所说,“对于编译器来说,似乎每个匹配的结束位置都是显而易见的。“是的,如果你使用的是轻语法,它应该是这样的。@idlys:我觉得你在使用冗长语法时有点误入歧途。它中没有任何东西会迫使你编写更具功能性的F#。唯一的区别在于你是使用缩进还是显式关键字来分隔结构。