Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
List 如何搜索元组元素的列表?_List_F#_Tuples_Return Value - Fatal编程技术网

List 如何搜索元组元素的列表?

List 如何搜索元组元素的列表?,list,f#,tuples,return-value,List,F#,Tuples,Return Value,在我的任务中,我必须列出婚礼上不能坐在一起的人的名单。然后将其与桌子上的人员列表进行比较。如果同一元组中的任意两个人在表列表中,则该值应为false。否则是真的。这是我第一次用F#编写代码,所以这里的语法让我很头疼 let isValidTable (cantSit:(string*string) list) (people: string list) = let truth = true; let rec matchPeople cantSit person1 person2

在我的任务中,我必须列出婚礼上不能坐在一起的人的名单。然后将其与桌子上的人员列表进行比较。如果同一元组中的任意两个人在表列表中,则该值应为false。否则是真的。这是我第一次用F#编写代码,所以这里的语法让我很头疼

let isValidTable (cantSit:(string*string) list) (people: string list) =

    let truth = true;
    let rec matchPeople cantSit person1 person2= 
        match cantSit with
        | [] -> None
        | head :: tail ->
            let (person1,person2) = head 
            if ((List.exists(fun names -> names = person1) people) && (List.exists(fun names2 -> names2 = person2) people)) then
                let result2 = false
            else 
                matchPeople tail fst snd;;
                let result = true;;
    matchPeople cantSit fst snd;;


let x = [("Eric", "Mark"); ("Anna", "Maya"); ("Beth", "Hope")];; 
let weddingList = ["Eric"; "Anna"; "Beth"]
let validOrNah = isValidTable x weddingList;;
printf("\n%O") validOrNah;;
对我来说,问题是我不断地遇到诸如“matchPeople构造函数未定义”或“let is unfinished”之类的错误。任何帮助都将不胜感激,谢谢

以前:我有

if(first person is in list and second person is in list)
then Some false
else recursive statement;

此代码编译时没有错误,但仅打印为null。我知道变量在F#中是不可变的,这使得这很困难。

代码中有很多问题,都是由于不熟悉F#造成的。我会一行一行地看一遍,试着解释一下你还没有理解的东西

let isValidTable (cantSit:(string*string) list) (people: string list) =
这很好

    let truth = true;
        | [] -> None
            let (person1,person2) = head 
根本不需要这个任务,因为您在代码中的任何地方都不使用名称
truth
。如果您确实需要使用它,您可以将其替换为常量
true
,这样它的可读性会更好。让我们完全删除这一行

顺便说一句,与类C语言不同,F#中的行尾不需要分号。双分号仅在F#交互式解释器中使用,用于告诉解释器“我已输入完此表达式”。这允许您将表达式拆分为多行,而无需解释器猜测何时完成(因为F#中的许多部分表达式看起来是完整的,因此需要显式表达式终止)。我不会在每次出现分号时都提到这一点,但您可以删除行末尾的所有分号(和双分号)。F中唯一需要分号的地方是列表中的项目之间,例如在
x
weddingList

转到下一行

    let rec matchPeople cantSit person1 person2=
            else 
这看起来不错,但实际上,您根本不需要
person1
person2
参数。我的猜测是,参数列表中有它们,因为您认为在创建变量之前需要声明变量,但F#根本不是这样工作的。在函数的后面编写
let(person1,person2)=head
时,变量
person1
person2
就在那里创建,不需要将它们作为函数参数。因此,您可以删除它们,您的函数定义将变成
let rec matchPeople cantSit=

        match cantSit with
这很好

    let truth = true;
        | [] -> None
            let (person1,person2) = head 
这是一个小错误。在其他地方,您似乎希望返回布尔值,但在这里,您将返回一个选项。在F#中,
match
和/或
if…else
的所有分支必须返回相同的类型。您的
isValidTable
函数显然是要返回布尔值,
matchPeople
也是如此,因此这也应该是一个布尔值。问题是,这行应该返回
false
还是
true
?要回答这个问题,请思考空的
cantSit
列表在问题域的语义中意味着什么。这意味着没有人不能坐在一起,所以座位表是有效的,无论是谁在桌子上。当然,这也可能意味着您已经通过多次递归调用到达了
cantSit
列表的末尾,在这种情况下,您在这里返回的值将是最后一次递归调用返回的值。同样,返回
true
是您想要的,因为如果您之前发现了一个无效的坐姿对,您将立即返回
false
,而不会进行另一个递归调用。因此,如果您到达
cantSit
列表为空的点,那么您就可以返回
true

        | head :: tail ->
这很好

    let truth = true;
        | [] -> None
            let (person1,person2) = head 
这不仅很好,还很好

            if ((List.exists(fun names -> names = person1) people) && (List.exists(fun names2 -> names2 = person2) people)) then
这很好,但可以简化。这里有一个
列表。包含满足您需要的
函数。任何类型的调用
List.exists(fun item->item=value)itemList)
都可以简化为
List.contains item itemList
。因此,如果(List.containmentperson1-people)和(List.containmentperson2-people),那么这将成为
,它更容易阅读和快速理解

                let result2 = false
这是错误的;F#中的
let
赋值没有值,因为它是
if
块中的最后一个表达式,这意味着如果条件为真,则
if
块将没有值。这就是为什么会出现“未完成”错误:在F#中,
let
赋值可能永远不会是代码块的最后一个表达式。它后面必须始终跟有值的表达式。实际上,您在这里要做的是非常清楚的:如果两个人都在列表中,您希望返回
false
。您可以通过在这行中写入
false
来实现这一点;我在这里再解释一下

在F#中,
if…else
是一个返回值的表达式,而不是像大多数其他语言那样的语句。所以你可以这样写:

let n = 5
let s = if n % 2 = 0 then "Even" else "Odd"
printfn "%s" s  // Prints "Odd"
这里,您的
if…else
match
表达式的最后一行,因此它的值将是
match
表达式的值。而
match
表达式是
matchPeople
函数的最后一个表达式,因此其值将是函数的返回值。因此,如果您发现一个匹配的对不能放在一起(这个
if…else
表达式的真正分支),那么您只需要有一行代码告诉您
false
,如果它碰到该分支,这将是函数的返回值

继续下一行

    let rec matchPeople cantSit person1 person2=
            else 
显然,这很好

                matchPeople tail fst snd;;
一旦您删除了
fst
snd
(因为我们更改了函数签名,所以
matchPeople
现在只需要一个参数