我正在F#中进行一个较小的项目,该项目涉及将现有C#代码移植到F#,而且我似乎在两种语言之间处理正则表达式的方式上有所不同(我将其发布以希望找出答案)只是做错了什么)。

这个次要函数使用 here 概述的正则表达式技巧简单地检测代理对。这是当前的实现:

let isSurrogatePair input =
    Regex.IsMatch(input, "[\uD800-\uDBFF][\uDC00-\uDFFF]")

如果我然后针对这样的已知代理对执行它:
let result = isSurrogatePair "𠮷野𠮷"
printfn "%b" result

我在 FSI 窗口中得到 false

如果我使用等效的 C#:
public bool IsSurrogatePair(string input)
{
    return Regex.IsMatch(input, "[\uD800-\uDBFF][\uDC00-\uDFFF]");
}

和相同的输入值,我(正确地)得到 true 回来。

这是真的吗?我只是在我的 F# 实现中做错了什么吗?

最佳答案

F# 对转义的 Unicode 字符进行编码的方式似乎存在错误。
这是来自 F# Interactive 的(注意最后两个结果):

> "\uD500".[0] |> uint16 ;;
val it : uint16 = 54528us
> "\uD700".[0] |> uint16 ;;
val it : uint16 = 55040us
> "\uD800".[0] |> uint16 ;;
val it : uint16 = 65533us
> "\uD900".[0] |> uint16 ;;
val it : uint16 = 65533us

幸运的是,此解决方法有效:
> let s = new System.String( [| char 0xD800 |] )
s.[0] |> uint16
;;

val s : System.String = "�"
val it : uint16 = 55296us

基于该发现,我可以构建 isSurrogatePair 的更正(或更确切地说,解决方法)版本:
let isSurrogatePair input =
  let chrToStr code = new System.String( [| char code |] )
  let regex = "[" + (chrToStr 0xD800) + "-" + (chrToStr 0xDBFF) + "][" + (chrToStr 0xDC00) + "-" + (chrToStr 0xDFFF) + "]"
  Regex.IsMatch(input,  regex)

此版本为您的输入正确返回 true

我刚刚在 GitHub 上提交了这个问题:https://github.com/Microsoft/visualfsharp/issues/338

10-07 23:43