繁体   English   中英

F#无法理解我的多个参数值所具有的分隔符。 为什么?

[英]F# can't understand the delimitation my multiple argument values have. Why?

我实际上正面临着F#编译器潜在的奇怪问题。 以下代码给了我一个错误,我不明白为什么:

    yield Animal(
        AnimalType(animal.AnimalType.Value),
error-->if Option.isSome animal.AnimalSubType then Some(AnimalSubType(animal.AnimalSubType.Value)) else None,
        AnimalSpecificSubType(animal.AnimalSpecificSubType.Value)
        )

编译器抱怨Animal应该接受3个参数,但实际上只接受2个。我想它没有意识到if参数在行的结尾(以逗号结尾)。 我可以通过在令人讨厌的行周围添加()来使代码运行:

    yield Animal(
        AnimalType(animal.AnimalType.Value),
--> OK  (if Option.isSome animal.AnimalSubType then Some(AnimalSubType(animal.AnimalSubType.Value)) else None),
        AnimalSpecificSubType(animal.AnimalSpecificSubType.Value)
        )

但我想了解这个问题。 为什么这可以解决问题,例如,不能解决?

    yield Animal(
        AnimalType(amimal.AnimalType.Value),
error-->if (Option.isSome animal.AnimalSubType) then (Some(AnimalSubType(animal.AnimalSubType.Value))) else (None),
        AnimalSpecificSubType(animal.AnimalSpecificSubType.Value)
        )

我没有看过F#的语法,但是我猜想每当F#看到if子句时,它将期望else子句,并可能后面跟随else子句。 我猜想,只要我小心else子句,一切都会好起来的。

怎么了

编译器将错误行末尾的逗号解释为else分支返回的元组的一部分,即

yield Animal(
    a,
    if c then Some(b) else None,
    d 
    )

解析为:

yield Animal(
    a,
    if c then Some(b) else ((None, ...? )
    d 
    )

这就是您的第一个修订而不是第二个修订起作用的原因,因为在第二个修订中添加方括号只是包裹了幻影元组的第一个元素,而不是元组本身,即:

yield Animal(
    a,
    if c then Some(b) else (None),
    d 
    )

解析为:

yield Animal(
    a,
    if c then Some(b) else ((None), ...? )
    d 
    )

问题与如何在F#中创建元组有关:

> let test (a,b,c) = "Test"
> test(1, if true then Some 1 else None,1);;

  test(1, if true then Some 1 else None,1);;
  -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error FS0001: Type mismatch. Expecting a
    'a * 'b * 'c    
but given a
    'a * 'b    
The tuples have differing lengths of 3 and 2

这清楚地表明编译器认为test正在采用两个参数,但是编译器认为这两个参数是什么? 由于这种类型的函数实际上只是将单个参数作为元组的函数,因此我们可以像下面这样来解构该行代码:

> 1, if true then Some 1 else None,1;;

  1, if true then Some 1 else None,1;;
  ----------------------------^^^^^^

stdin(19,29): error FS0001: This expression was expected to have type
    int option    
but here has type
    'a * 'b

因此,您可以看到编译器正在将None,1视为if表达式中else的表达式,这就是为什么编译器需要int option 为防止这种情况,您需要向编译器指示if表达式的开始和结束位置。 实现此目的的最简单方法是像这样简单地加上括号:

> 1,(if true then Some 1 else None),1;;
val it : int * int option * int = (1, Some 1, 1)

现在我们得到了预期的元组。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM