F# と関数型プログラミング全般の知識を向上させる方法として自分自身を割り当てたプロジェクトの一環として、ループや変数 (または正規表現、または文字列) を使用せずに、文字列パターン マッチング アルゴリズムをゼロから作成しようとしています。 .Replace とフレンズ)。これは純粋に学習プロジェクトであるため、私はそれを行うための最善の方法には興味がありません。それを行うための最善の機能的な方法だけです。
ワイルドカード文字、パターン文字列、および入力文字列をパラメーターとして受け入れる関数を作成しようとしています。パターンが入力と一致しない場合、関数は を返しますNone
。パターンが入力と一致する場合、関数は、パターン文字列に存在する可能性のあるワイルドカードと一致した入力文字列の部分がSome(str)
どこにあるかを返します。str
私はこれをほとんど機能させています。すぐにコードを含めます。等価性をサポートする任意の汎用リストで機能する汎用パターン マッチング関数を作成し、文字列を受け取って文字のリストを汎用関数に渡すヘルパー関数を作成しました。これはすべて機能しますが、1 つのことを除いて: パターン文字列での複数のワイルドカードのサポートはあまり良くありません。各ワイルドカードの一致を取得し、それらを連結して出力内の 1 つの文字列にします。
例えば:
> strMatch '*' "foo" "bar";;
val it : string option = None
> strMatch '*' "test" "test";;
val it : string option = Some ""
> strMatch '*' "functional programming is *" "functional programming is fun";;
val it : string option = Some "fun"
> strMatch '*' "* and *" "you and me";;
val it : string option = Some "youme"
それは私が修正しようとしている最後のものです。理想的には、リスト内の各要素が 1 つのワイルドカードに一致する文字列である、単一の文字列ではなく文字列のリストを返したいと考えています。それができない場合は、おそらく最初のワイルドカードの一致のみを返すバージョンで間に合わせることができます。削除する必要があるのは、両方のワイルドカードからの連結された値です。私はそれにアプローチする方法がよくわかりません。
したがって、一致したワイルドカードによって戻り値をグループ化する方法を誰かが提案できる場合は、感謝します。あなたが提案したいかもしれない私のコードへの他の改善にも興味があります.
let rec doMatch (wildcard:'a) (pat:'a list) (input:'a list) : 'a 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 x -> Some(ihd :: x)
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 x -> Some(ihd :: x)
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(new string(Array.ofList x))
ご想像のとおりですが、これは F# での Eliza チャット ボットの実装の一部です。