f#一个函数作为匹配函数的参数



我创建了一个函数,它接受一个列表和一个列表的列表,并返回一个新的列表的列表。

let rec calculator list SS =
  match (List.item(0) SS) with
  |[] -> []
  |_ -> match (validate list (List.item(0) SS)) with
        |(validate theCode list) -> List.append [(List.item(0) SS)] (calculator list (SS.[1..])) 
        |_ -> (calculator list (SS.[1..]))

validate是一个返回两个元组整型的函数。例子(1,1)

list是一个包含四个整型数的列表

SS是一个包含四个int值的列表的列表

theCode是一个包含四个整型数的列表

我得到错误"模式鉴别符'validate'未定义"。

也许这是一个愚蠢的问题,但我仍然不知道它的答案。

是否不允许在匹配表达式中使用函数作为参数?还是这里发生了完全不同的事情?

据我所知,这两个验证函数将返回两个元组整数,因此应该能够匹配。

如果你的问题是如何得到这个编译,那么你只需要一个小小的改变& & &;一个函数调用本身并不是一个模式,所以你需要绑定到一个值并使用when保护:

let rec calculator list SS =
    match (List.item(0) SS) with
    | [] -> []
    | _  ->
        match (validate list (List.item(0) SS)) with
//        vvvvvvvvvv
        | x when x = (validate theCode list) ->
            List.append [(List.item(0) SS)] (calculator list (SS.[1..]))
        | _ -> (calculator list (SS.[1..]))

然而,如果你的问题确实是"什么是首选方法",那么虽然这对本网站(IMO)来说太主观了,但我将把这个作为我认为理想的可读逻辑的选项提交:

let rec calculator list (h::t) =
    if List.isEmpty h then h
    elif validate list h = validate theCode list then h::(calculator list t)
    else calculator list t

(这里假设SS是f#列表而不是System.Collections.Generic.List)

这实际上不是如何实现when保护的问题的答案,因为@ildjarn为您回答了这个问题。

我认为你实际上更适合使用库函数。您要做的似乎是过滤掉未通过验证的元素,但也要在第一个空元素上停止。如果您可以保证一定要循环遍历SS的每个元素,则只需执行

let calculator list = List.filter (fun s -> validate list s = validate theCode list)

如果必须在空元素处停止,可以定义一个函数在第一个空元素处切割列表,例如

let upToElement element list =
    let rec loop acc = function
        | [] -> List.rev acc
        | h :: t when h = element -> List.rev acc
        | h :: t -> loop (h :: acc) t
    loop [] list

那么你可以做

let calculator list =
    upToElement [] >> List.filter (fun s -> validate list s = validate theCode list)

最新更新