Come parte di un progetto mi sono assegnato come un modo per migliorare la mia conoscenza di F # e programmazione funzionale in generale, sto tentando di scrivere un algoritmo di corrispondenza di stringhe da zero senza utilizzare alcun cicli o variabili (o espressioni regolari, o String.Replace e amici). Poiché questo è puramente un progetto di apprendimento, non mi interessa nel miglior modo possibile per farlo, solo il modo migliore per farlo funzionale.F # String Pattern-Matching con caratteri jolly
che sto cercando di scrivere una funzione che accetta un carattere jolly, una stringa modello, e una stringa di input come parametri. Se il modello non corrisponde all'ingresso, la funzione restituisce None
. Se il modello non corrisponde l'ingresso, la funzione restituisce Some(str)
dove str
è qualunque parte della stringa di input soddisfi qualche jolly che avrebbero potuto essere presenti nella stringa modello.
ho questo per lo più a lavorare, e io includere il codice in un attimo. Ho scritto una funzione generica pattern-matching che funziona su qualsiasi elenco generico di tutto ciò che sostiene l'uguaglianza, e quindi una funzione di supporto che prende le stringhe e passa liste di personaggi alla funzione generica. Tutto questo funziona, tranne che per una cosa: il supporto per più caratteri jolly nella stringa del pattern non è molto buono - prende le corrispondenze per ogni carattere jolly e le concatena in un'unica stringa nell'output.
Ad esempio:
> 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"
E 'l'ultima che sto cercando di risolvere. Idealmente mi piacerebbe per restituire un elenco di stringhe, piuttosto che una singola stringa, con ogni elemento della lista è la stringa che corrisponde un jolly. In caso contrario, posso probabilmente accontentarmi di una versione che restituisce solo la corrispondenza per il primo carattere jolly: sono i valori concatenati di entrambi i caratteri jolly di cui ho bisogno per sbarazzarmi. Non sono abbastanza sicuro di come affrontarlo.
Quindi, se qualcuno può suggerire come posso raggruppare i miei valori di ritorno con i caratteri jolly corrispondenti, sarei grato. Sono anche interessato a qualsiasi altro miglioramento del mio codice che potresti suggerire.
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))
Probabilmente avete indovinato, ma questo fa parte di un'implementazione di chat-bot di Eliza in F #.
Sono d'accordo, questo è praticamente esattamente quello che voglio finire. Pensavo fosse quello che stavo chiedendo, ma forse non ero chiaro. La mia domanda più profonda è semplicemente: "Come ci arrivo da qui?" Sono abbastanza nuovo per F #, e continuo a perdersi in tutte le ricorsioni e listing consing e quant'altro ogni volta che cerco di implementarlo come suggerisci tu. –
Inoltre, dato che la mia funzione generica doMatch sta già restituendo un '' opzione lista ', non dovrei invece restituire un' 'opzione lista lista'? Il mio problema è che non mi è chiaro come dire quando dovrei aggiungere il personaggio corrente ad un elenco esistente di personaggi rispetto all'avvio di un nuovo elenco di caratteri. –
Dopo la modifica: grazie mille. 'Some (x :: xs) -> Some ((ihd :: x) :: xs)' era il bit di sintassi che non avevo proprio ragione. Ho imparato qualcosa oggi! –