Поскольку String.tokens является каррированной функцией, я знаю, что могу изменить
String.tokens (fn
c =\> c = #" "
) "hello world";
в строку, которая будет содержать все разделители, но я просто смущен фактической диктовкой того, как.
Одна из форм, которые я пробовал, была:
fun splitter nil = nil
| splitter str =
let
val c = " ,.;?:!\t\n"
val s = String.tokens (fn (c:string,x:char) => c=Char.toString c x) str
in
s
end;
C - это строка разделителей, но я знаю, что что-то не так. Если бы кто-нибудь мог указать мне в правильном направлении, это было бы очень признательно.
String.tokens
принимает два аргумента: предикат для определения, является ли символ токеном; и строка для разделения. Первый аргумент является важной частью. Нам не нужно указывать символ для разделения, просто правило для идентификации этого символа.
Если вы превратите строку, содержащую символы токена, в список с помощью String.explode
, то легко использовать List.exists
, чтобы узнать, есть ли символ в этой строке токена.
fun splitOn(str, tokens) =
let
val tokens' = String.explode tokens
fun isToken c = List.exists (fn c' => c = c') tokens'
in
String.tokens isToken str
end;
splitOn("hello world | wooble. foo? bar!", " |.?!");
(* ["hello", "world", "wooble", "foo", "bar"] *)
isToken
не принимает tokens'
в качестве аргумента. Скорее isToken
— это замыкание, которое имеет доступ к tokens'
, когда оно оценивается позже. String.tokens
использует эту функцию, чтобы определить, является ли символ токеном, и использует эту информацию для разделения входной строки str
.
Я просто хочу уточнить, String.tokens принимает isTokens как функцию, которая принимает токены, которые представляют собой список символов? List.exists возвращает true или false в зависимости от того, находится ли один из символов в токенах в строке str? Затем, основываясь на этом true или false, String.tokens удаляет соответствующие символы из токенов?