从设计的角度来看,我喜欢返回
'a list option
在哪里。
None // it did not match
Some[] // matched, input had 0 wildcards
Some["foo";"bar"] // matched, input has 2 wildcards, "foo" matched 1st, "bar" 2nd
(我不清楚在你的长篇博文中是否有更深层次的问题。)
编辑
'a list list option
因为“a”是一个字符,“a”列表就像一个字符串,我们需要一个字符串列表。singleMatch将启动一个新的字符串列表,而longerMatch将考虑当前字符串的前面。
let rec doMatch (wildcard:'a) (pat:'a list) (input:'a list)
: 'a list list option =
let singleMatch p i =
match (p, i) with
| phd :: ptl, ihd :: itl ->
if phd = wildcard then
match doMatch wildcard ptl itl with
| None -> None
| Some xs -> Some([ihd]::xs)
else None
| _ -> None
let longerMatch p i =
match (p, i) with
| phd :: ptl, ihd :: itl ->
if phd = wildcard then
match doMatch wildcard p itl with
| None -> None
| Some ([]) -> Some([[ihd]])
| Some (x::xs) -> Some((ihd :: x)::xs)
else None
| _ -> None
match (pat, input) with
| [], [] -> Some([])
| [], _::_ -> None
| _::_, [] -> None
| phd :: ptl, ihd :: itl ->
if phd <> wildcard then
if phd = ihd then doMatch wildcard ptl itl
else None
else
match singleMatch pat input with
| Some x -> Some(x)
| None -> longerMatch pat input
let strMatch (wildcard:char) (pat:string) (input:string) =
match doMatch wildcard (List.ofSeq pat) (List.ofSeq input) with
| None -> None
| Some x -> Some(x|>List.map (fun chList -> new string(Array.ofList chList)))
printfn "%A" (strMatch '*' "foo" "bar")
printfn "%A" (strMatch '*' "test" "test")
printfn "%A" (strMatch '*' "functional programming is *"
"functional programming is fun")
printfn "%A" (strMatch '*' "* and *" "you and me")