F#正则表达匹配链

unk*_*656 2 regex f# operators pattern-matching

由于我对F#的正则表达式实现并不完全满意,因此我希望实现一个所谓的正则表达链.它基本上如下工作:

s将检查给定的字符串,是否与第一个模式匹配.如果是,它应该执行与第一个模式相关的功能.如果没有,则应继续下一个.

我尝试按如下方式实现它:

let RegexMatch ((s : string, c : bool), p : string, f : GroupCollection -> unit) =
    if c then
        let m = Regex.Match(s, p)
        if m.Success then
            f m.Groups
            (s, false)
        else (s, c)
    else (s, c)


("my input text", true)
|> RegexMatch("pattern1", fun g -> ...)
|> RegexMatch("pattern2", fun g -> ...)
|> RegexMatch("pattern3", fun g -> ...)
|> .... // more patterns
|> ignore
Run Code Online (Sandbox Code Playgroud)

问题是,这个代码是无效的,因为正向管道运算符似乎没有管道元组或者不喜欢我的实现"设计".

我的问题是:我可以轻松修复上面的代码,还是应该实现其他类型的正则表达链?

Fyo*_*kin 6

您的函数RegexMatch不支持管道,因为它具有tupled参数.

首先,看一下管道的定义:

let (|>) x f = f x
Run Code Online (Sandbox Code Playgroud)

从这一点,人们可以清楚地看到这个表达:

("text", true)
|> RegexMatch("pattern", fun x -> ...)
Run Code Online (Sandbox Code Playgroud)

等同于:

RegexMatch("pattern", fun x -> ...) ("text", true)
Run Code Online (Sandbox Code Playgroud)

这符合您的功能签名吗?显然不是.在您的签名中,text/bool对首先出现,并且是参数的三倍,以及模式和功能.

为了使它工作,你需要以咖喱形式和最后的"管道"参数:

let RegexMatch p f (s, c) = ...
Run Code Online (Sandbox Code Playgroud)

然后你可以做管道:

("input", true)
|> RegexMatch "pattern1" (fun x -> ...)
|> RegexMatch "pattern2" (fun x -> ...)
|> RegexMatch "pattern3" (fun x -> ...)
Run Code Online (Sandbox Code Playgroud)

顺便说一句,我必须指出,你的做法是不是很,啊哈,功能.你的整个逻辑基于副作用,这会使你的程序无法组合,难以测试,并且可能容易出错.你没有从F#中获益,有效地将它用作"具有更好语法的C#".

此外,实际上有很好的研究方法来实现你想要的.首先,查看面向铁路的编程(也称为monadic计算).