【问题标题】:Indentation problem in f# (vs2010 beta1)f#(vs2010 beta1)中的缩进问题
【发布时间】:2010-11-21 03:53:25
【问题描述】:

我只是在学习 f#,所以可能我正在做一些非常愚蠢的事情。随时向我指出相关文档,我已经搜索但无法找到。我在 Windows 7 (.Net 4.0) 上使用 Visual Studio 2010 beta。

我的第一个 f# 项目一切顺利。嗯..几乎所有东西。特别是 我正在编写一个非常简单的线性插值函数,代码如下:

let linterp (x:double) (xvalues:double list) (yvalues:double list) =
    let num_els = xvalues.Length
    if x <= xvalues.Head then 
        let result = yvalues.Head
    elif x >= (List.rev xvalues).Head then 
        let result = (List.rev yvalues).Head
    else for idx in [0 .. num_els] do 
        if List.nth xvalues idx >= x then 
            let x0 = xvalues.Item idx
            let y0 = yvalues.Item idx
            let x1 = xvalues.Item (idx+1)
            let y1 = yvalues.Item (idx+1)
            let result = y0 + (y1-y0)/(x1-x0)*(x - x0)
    result

我收到了一系列完全无法理解的错误。

这是错误和警告列表:

  • “此 'let' 的返回表达式中的错误。第一个、第二个和最后一个“let”的缩进可能正确。

  • “可能不正确的缩进:此标记超出从位置 (39:10) 开始的上下文。尝试进一步缩进此标记或使用标准格式约定”作为“if”

  • “在表达式中此点或之前的不完整结构化构造”用于最后一行(结果)。

我要补充一点,我不得不花点时间来注释类型,因为出于某种我不知道的原因,编译器能够正确推断第一个列表,但对于第二个列表,类型总是被推断为 unit 另外,我的原始版本没有绑定名称结果,而是简单地“返回表达式”,就像在

if x <= xvalues.Head then 
    yvalues.Head

或在

else for idx in [0 .. num_els] do 
    if List.nth xvalues idx >= x then 
        let x0 = xvalues.Item idx
        let y0 = yvalues.Item idx
        let x1 = xvalues.Item (idx+1)
        let y1 = yvalues.Item (idx+1)
        y0 + (y1-y0)/(x1-x0)*(x - x0)

这会在“for”下留下一个错误,说“此表达式具有类型 unit,但在这里与类型 double 一起使用”,并且“if”可能缩进不正确。

我想当我看到这个问题的解决方案时我会觉得很傻,但是我已经被这么简单的问题困了一个多小时,所以我请求你的帮助。

提前致谢!

ps:我已经检查了选项卡在工具->选项->.... -> F#->选项卡菜单中被正确解释为空格

pps:这是我关于 SO 的第一个问题 :-)

【问题讨论】:

  • 我很惭愧,但代码中有一个明显的错误:-) 这证明我太老了,不能在深夜编码。为此,let x0 = xvalues.Item (idx - 1)let x1 = xvalues.Item idx 因为 idx 表示第一个大于或等于 x 的项目。

标签: windows f# indentation


【解决方案1】:

你的问题是这样的

let result = yvalues.Head

不是一个完整的表达式,因此它不能形成if 块的其中一个分支的主体。您的初始方法是正确的,除了 for ... do 循环没有返回有意义的值(它返回 (),这是 unit 类型的唯一值,正如编译器试图解释的那样;这类似于void 在 C# 等语言中)。而不是for 循环,您需要使用具有您正在寻找的值的表达式。对代码的最小更改是使用您在循环中强制设置的可变值。更惯用的方法是使用像 List.fold 这样的内置函数将列表压缩为单个值。这很复杂,因为您需要访问列表中的连续条目(并且您需要同时对 xvalues 和 yvalues 进行操作),这意味着您可能需要使用 List.zip 和 Seq.pairwise,这可能降低不习惯 F# 的人的清晰度。

此外,您还可以应用一些其他更改来使您的代码更符合习惯。例如,let x0 = xvalues.Item idx 更常写作let x0 = xvalues.[idx]。但是请注意,F# 列表是不可变的链表,因此不支持快速随机访问。这是支持使用内置 List 运算符的方法的另一个原因。

【讨论】:

  • 谢谢,现在我更好地理解了错误的含义。例如。如果我没有使用 #light 语法,我应该写 if x
【解决方案2】:
let linterp x (xvalues:double list) (yvalues:double list) =
    if x <= xvalues.Head then 
        yvalues.Head
    elif x >= (List.rev xvalues).Head then 
        (List.rev yvalues).Head
    else
        let idx = List.findIndex (fun e -> e >= x) xvalues
        let x0 = xvalues.Item idx
        let y0 = yvalues.Item idx
        let x1 = xvalues.Item (idx+1)
        let y1 = yvalues.Item (idx+1)
        y0 + (y1-y0)/(x1-x0)*(x - x0)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-07-20
    • 1970-01-01
    • 1970-01-01
    • 2022-01-11
    • 1970-01-01
    • 1970-01-01
    • 2013-09-26
    • 1970-01-01
    相关资源
    最近更新 更多