简体   繁体   English

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

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

I'm actually facing a potentially strange problem with the F# compiler. 我实际上正面临着F#编译器潜在的奇怪问题。 The following code gives me an error and I can't understand why: 以下代码给了我一个错误,我不明白为什么:

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

The compiler complains that Animal should take 3 arguments but is in fact only taking 2. I guess it is failing to realize that the if argument ends at the end of the line (in the comma). 编译器抱怨Animal应该接受3个参数,但实际上只接受2个。我想它没有意识到if参数在行的结尾(以逗号结尾)。 I can get the code running by adding ()'s around the offending line: 我可以通过在令人讨厌的行周围添加()来使代码运行:

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

but I'd like to understand the issue. 但我想了解这个问题。 Why does this fix the issue and, for instance, this does not? 为什么这可以解决问题,例如,不能解决?

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

I've not looked up over F#'s grammar, but I'd guess every time F# sees an if clause it will expect an else clause, potentially followed by an else clause. 我没有看过F#的语法,但是我猜想每当F#看到if子句时,它将期望else子句,并可能后面跟随else子句。 I'd guess that as long as I was careful with the else clause everything would be fine. 我猜想,只要我小心else子句,一切都会好起来的。

What's the matter here? 怎么了

The compiler interprets the comma at the end of the error line as part of a tuple returned by the else branch, ie 编译器将错误行末尾的逗号解释为else分支返回的元组的一部分,即

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

is parsed as: 解析为:

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

That's why your first fix works and not the second, as adding brackets in the second fix just wraps the first element of the phantom tuple, not the tuple itself, ie: 这就是您的第一个修订而不是第二个修订起作用的原因,因为在第二个修订中添加方括号只是包裹了幻影元组的第一个元素,而不是元组本身,即:

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

is parsed as: 解析为:

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

The problem has to do with how tuples are created in F#: 问题与如何在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

This makes it clear that the compiler thinks test is taking two parameters, but what does the compiler think these two parameters are? 这清楚地表明编译器认为test正在采用两个参数,但是编译器认为这两个参数是什么? Since functions of this type are really just functions which take a single parameter as a tuple, we can deconstruct that line of code a bit like so: 由于这种类型的函数实际上只是将单个参数作为元组的函数,因此我们可以像下面这样来解构该行代码:

> 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

So you can see that the compiler is treating None,1 as the expression in the else of the if expression which is why the compiler is expecting an int option . 因此,您可以看到编译器正在将None,1视为if表达式中else的表达式,这就是为什么编译器需要int option To prevent this, you need to indicate to the compiler where the start and end of the if expression are. 为防止这种情况,您需要向编译器指示if表达式的开始和结束位置。 The easiest way of achieving this is by simply putting parenthesis around it like this: 实现此目的的最简单方法是像这样简单地加上括号:

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

Now we get the expected tuple. 现在我们得到了预期的元组。

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

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