标量的 Unicode 字符串子串函数
Substring function of Unicode strings by scalars
之前,我写了一个unicode字符串在字位簇上的子串函数如下。传递给函数的位置超过了 Unicode 标量,例如,\r\n
被计为 2,但 Grapheme 簇数 \r\n
被计为 1。所以这个函数在某些情况下效果不佳:
let uni_sub (s: string) (pos: int) (len: int) =
let (_, r) =
Uuseg_string.fold_utf_8
`Grapheme_cluster
(fun (p, acc) ch -> if (p >= pos) && (p <= pos+len-1) then (p+1, acc ^ ch) else (p+1, acc))
(0, "")
s
in
r
我被建议通过使用 Uutf.String.fold_utf_8
和 Buffer.add_utf_8_uchar
在它们的标量上编写 unicode 字符串的子字符串函数。但是,由于没有很好地理解系统是如何工作的,我只能粗略地编写以下代码,并希望首先使类型工作。
let uni_sub_scalars (s: string) (pos: int) (len: int) =
let b: Buffer.t = Buffer.create 42 in
let rec add (acc: string list) (v: [ `Uchar of Stdlib.Uchar.t | `Await | `End ]) : Uuseg.ret =
match v with
| `Uchar u ->
Buffer.add_utf_8_uchar b u;
add acc `Await
| `Await | `End -> failwith "don't know what to do"
in
let (_, r) =
Uuseg_string.fold_utf_8
(`Custom (Uuseg.custom ~add:add))
(fun (p, acc) ch -> if (p >= pos) && (p <= pos+len-1) then (p+1, acc ^ ch) else (p+1, acc))
(0, "")
s
in
r
并且编译返回了一个我不知道如何修复的错误:
File "lib/utility.ml", line 45, characters 6-39:
45 | (`Custom (Uuseg.custom ~add:add))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Error: This expression has type
[> `Custom of
?mandatory:(string list -> bool) ->
name:string ->
create:(unit -> string list) ->
copy:(string list -> string list) -> unit -> Uuseg.custom ]
but an expression was expected of type [< Uuseg.boundary ]
Types for tag `Custom are incompatible
make: *** [lib/utility.cmo] Error 2
谁能帮我用标量写这个 Unicode 字符串的子串函数?
And the compilation returned an error that I don't know how to fix:
Uuseg.custom
函数创建自定义分段器并采用一些参数(您只传递了一个),
val custom :
?mandatory:('a -> bool) ->
name:string ->
create:(unit -> 'a) ->
copy:('a -> 'a) ->
add: ('a -> [ `Uchar of Uchar.t | `Await | `End ] -> ret) -> unit -> custom
因此您还需要传递 name
、create
、copy
参数以及位置 ()
参数。但我不认为这是你应该使用的功能。
Could anyone help me write this substring function of Unicode strings by scalars?
是的,如果我们听从建议并“使用 Uutf.String.fold_utf_8
和 Buffer.add_utf_8_uchar
” 实施它,那将非常容易。 (注意,建议我们使用 Uutf.String.fold_utf_8
而不是 Uuseg_string.fold_utf_8
)。
一个简单的实现(不做很多错误检查)看起来像这样,
let substring s pos len =
let buf = Buffer.create len in
let _ : int = Uutf.String.fold_utf_8 (fun off _ elt ->
match elt with
| `Uchar x when off >= pos && off < pos + len ->
Buffer.add_utf_8_uchar buf x;
off + 1
| _ -> off + 1) 0 s in
Buffer.contents buf
这是它的工作原理(以我的名字为例),
# substring "Иван\n\rГотовчиц" 0 5;;
- : string = "Иван\n"
# substring "Иван\n\rГотовчиц" 11 3;;
- : string = "чиц"
而且它适用于从右到左的脚本,
# let shalom = substring "שָׁלוֹ";;
val shalom : int -> int -> string = <fun>
# shalom 0 1;;
- : string = "ש"
# shalom 0 2;;
- : string = "שָ"
# shalom 2 2;;
- : string = "ׁל"
# shalom 2 1;;
- : string = "ׁ"
之前,我写了一个unicode字符串在字位簇上的子串函数如下。传递给函数的位置超过了 Unicode 标量,例如,\r\n
被计为 2,但 Grapheme 簇数 \r\n
被计为 1。所以这个函数在某些情况下效果不佳:
let uni_sub (s: string) (pos: int) (len: int) =
let (_, r) =
Uuseg_string.fold_utf_8
`Grapheme_cluster
(fun (p, acc) ch -> if (p >= pos) && (p <= pos+len-1) then (p+1, acc ^ ch) else (p+1, acc))
(0, "")
s
in
r
我被建议通过使用 Uutf.String.fold_utf_8
和 Buffer.add_utf_8_uchar
在它们的标量上编写 unicode 字符串的子字符串函数。但是,由于没有很好地理解系统是如何工作的,我只能粗略地编写以下代码,并希望首先使类型工作。
let uni_sub_scalars (s: string) (pos: int) (len: int) =
let b: Buffer.t = Buffer.create 42 in
let rec add (acc: string list) (v: [ `Uchar of Stdlib.Uchar.t | `Await | `End ]) : Uuseg.ret =
match v with
| `Uchar u ->
Buffer.add_utf_8_uchar b u;
add acc `Await
| `Await | `End -> failwith "don't know what to do"
in
let (_, r) =
Uuseg_string.fold_utf_8
(`Custom (Uuseg.custom ~add:add))
(fun (p, acc) ch -> if (p >= pos) && (p <= pos+len-1) then (p+1, acc ^ ch) else (p+1, acc))
(0, "")
s
in
r
并且编译返回了一个我不知道如何修复的错误:
File "lib/utility.ml", line 45, characters 6-39:
45 | (`Custom (Uuseg.custom ~add:add))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Error: This expression has type
[> `Custom of
?mandatory:(string list -> bool) ->
name:string ->
create:(unit -> string list) ->
copy:(string list -> string list) -> unit -> Uuseg.custom ]
but an expression was expected of type [< Uuseg.boundary ]
Types for tag `Custom are incompatible
make: *** [lib/utility.cmo] Error 2
谁能帮我用标量写这个 Unicode 字符串的子串函数?
And the compilation returned an error that I don't know how to fix:
Uuseg.custom
函数创建自定义分段器并采用一些参数(您只传递了一个),
val custom :
?mandatory:('a -> bool) ->
name:string ->
create:(unit -> 'a) ->
copy:('a -> 'a) ->
add: ('a -> [ `Uchar of Uchar.t | `Await | `End ] -> ret) -> unit -> custom
因此您还需要传递 name
、create
、copy
参数以及位置 ()
参数。但我不认为这是你应该使用的功能。
Could anyone help me write this substring function of Unicode strings by scalars?
是的,如果我们听从建议并“使用 Uutf.String.fold_utf_8
和 Buffer.add_utf_8_uchar
” 实施它,那将非常容易。 (注意,建议我们使用 Uutf.String.fold_utf_8
而不是 Uuseg_string.fold_utf_8
)。
一个简单的实现(不做很多错误检查)看起来像这样,
let substring s pos len =
let buf = Buffer.create len in
let _ : int = Uutf.String.fold_utf_8 (fun off _ elt ->
match elt with
| `Uchar x when off >= pos && off < pos + len ->
Buffer.add_utf_8_uchar buf x;
off + 1
| _ -> off + 1) 0 s in
Buffer.contents buf
这是它的工作原理(以我的名字为例),
# substring "Иван\n\rГотовчиц" 0 5;;
- : string = "Иван\n"
# substring "Иван\n\rГотовчиц" 11 3;;
- : string = "чиц"
而且它适用于从右到左的脚本,
# let shalom = substring "שָׁלוֹ";;
val shalom : int -> int -> string = <fun>
# shalom 0 1;;
- : string = "ש"
# shalom 0 2;;
- : string = "שָ"
# shalom 2 2;;
- : string = "ׁל"
# shalom 2 1;;
- : string = "ׁ"