Skip to content

Add String.{cut,rcut}.#13

Closed
dbuenzli wants to merge 1 commit intoocaml:trunkfrom
dbuenzli:cut
Closed

Add String.{cut,rcut}.#13
dbuenzli wants to merge 1 commit intoocaml:trunkfrom
dbuenzli:cut

Conversation

@dbuenzli
Copy link
Copy Markdown
Contributor

As a follow up to pull request #10. This pull request adds String.{cut,rcut} which cuts a string in two at a given non empty separator sep starting either from the beginning of the string or from the end. The signature for StringLabels is :

val cut : ~sep:string -> string -> (string * string) option
val rcut : ~sep:string -> string -> (string * string) option

These functions have the following invariants. First for any non empty sep and s such that sep is in s we have:

assert (String.{cut,rcut} sep s = Some (l,r))
assert (l ^ sep ^ r = s)

Then for any s such that sep doesn't occur in s:

assert (String.{rcut,cut} sep s = None)

Here is the result of String.{cut,rcut} on a few edge cases.

  (* String.cut *) 
  assert (try ignore (String.cut "" ""); false with Invalid_argument _ -> true);
  assert (try ignore (String.cut "" "123"); false with Invalid_argument _ -> true);
  assert (String.cut "," "" = None);
  assert (String.cut "," "," = Some ("", ""));
  assert (String.cut "," ",," = Some ("", ","));
  assert (String.cut "," ",,," = Some ("", ",,"));
  assert (String.cut "," "123" = None); 
  assert (String.cut "," ",123" = Some ("", "123"));
  assert (String.cut "," "123," = Some ("123", "")); 
  assert (String.cut "," "1,2,3" = Some ("1", "2,3")); 
  assert (String.cut "," " 1,2,3" = Some (" 1", "2,3")); 
  assert (String.cut "<>" "" = None); 
  assert (String.cut "<>" "<>" = Some ("", ""));
  assert (String.cut "<>" "<><>" = Some ("", "<>"));
  assert (String.cut "<>" "<><><>" = Some ("", "<><>"));
  assert (String.rcut "<>" "1" = None);
  assert (String.cut "<>" "123" = None);
  assert (String.cut "<>" "<>123" = Some ("", "123"));
  assert (String.cut "<>" "123<>" = Some ("123", ""));
  assert (String.cut "<>" "1<>2<>3" = Some ("1", "2<>3"));
  assert (String.cut "<>" " 1<>2<>3" = Some (" 1", "2<>3"));
  assert (String.cut "<>" ">>><>>>><>>>><>>>>" = 
          Some (">>>", ">>><>>>><>>>>"));
  assert (String.cut "<->" "<->>->" = Some ("", ">->"));
  assert (String.rcut "<->" "<-" = None);
  assert (String.cut "aa" "aa" = Some ("", "")); 
  assert (String.cut "aa" "aaa" = Some ("", "a"));
  assert (String.cut "aa" "aaaa" = Some ("", "aa"));
  assert (String.cut "aa" "aaaaa" = Some ("", "aaa";));
  assert (String.cut "aa" "aaaaaa" = Some ("", "aaaa"));
  (* String.rcut *) 
  assert (try ignore (String.rcut "" ""); false with Invalid_argument _ -> true);
  assert (try ignore (String.rcut "" "123"); false with Invalid_argument _ -> true);
  assert (String.rcut "," "" = None);
  assert (String.rcut "," "," = Some ("", ""));
  assert (String.rcut "," ",," = Some (",", ""));
  assert (String.rcut "," ",,," = Some (",,", ""));
  assert (String.rcut "," "123" = None); 
  assert (String.rcut "," ",123" = Some ("", "123"));
  assert (String.rcut "," "123," = Some ("123", "")); 
  assert (String.rcut "," "1,2,3" = Some ("1,2", "3")); 
  assert (String.rcut "," "1,2,3 " = Some ("1,2", "3 ")); 
  assert (String.rcut "<>" "" = None); 
  assert (String.rcut "<>" "<>" = Some ("", ""));
  assert (String.rcut "<>" "<><>" = Some ("<>", ""));
  assert (String.rcut "<>" "<><><>" = Some ("<><>", ""));
  assert (String.rcut "<>" "1" = None);
  assert (String.rcut "<>" "123" = None);
  assert (String.rcut "<>" "<>123" = Some ("", "123"));
  assert (String.rcut "<>" "123<>" = Some ("123", ""));
  assert (String.rcut "<>" "1<>2<>3" = Some ("1<>2", "3"));
  assert (String.rcut "<>" "1<>2<>3 " = Some ("1<>2", "3 "));
  assert (String.rcut "<>" ">>><>>>><>>>><>>>>" = 
          Some (">>><>>>><>>>>", ">>>"));
  assert (String.rcut "<->" "<->>->" = Some ("", ">->"));
  assert (String.rcut "<->" "<-" = None);
  assert (String.rcut "aa" "aa" = Some ("", "")); 
  assert (String.rcut "aa" "aaa" = Some ("a", ""));
  assert (String.rcut "aa" "aaaa" = Some ("aa", ""));
  assert (String.rcut "aa" "aaaaa" = Some ("aaa", "";));
  assert (String.rcut "aa" "aaaaaa" = Some ("aaaa", ""));

@dbuenzli
Copy link
Copy Markdown
Contributor Author

One disputable aspect of the proposal is that it doesn't respect String's design conventions to raise Not_found rather than return options. I'm on the side that new additions should not perpetuate the (wrong in my eyes) idea of using exceptions for non-exceptional cases. But I'm willing to turn that option into a raise Not_found if that is a pre-condition for including the patch.

@dbuenzli
Copy link
Copy Markdown
Contributor Author

Let's not even consider this.

@dbuenzli dbuenzli closed this Apr 14, 2015
@dbuenzli dbuenzli deleted the cut branch January 6, 2016 15:43
@dbuenzli dbuenzli mentioned this pull request Jul 9, 2016
This was referenced Mar 14, 2019
dra27 referenced this pull request in dra27/ocaml Mar 20, 2019
This uses `extract_blank_separated_words` instead of splitting by hand.

Closes #13
ulrikstrid pushed a commit to ulrikstrid/ocaml that referenced this pull request Sep 25, 2019
poechsel pushed a commit to poechsel/ocaml that referenced this pull request Jul 2, 2021
DMaroo pushed a commit to DMaroo/ocaml that referenced this pull request Jan 6, 2024
Add caml_trigger_verified_gc primitive
turly221 pushed a commit to scantist-ossops-m2/ocaml that referenced this pull request Nov 30, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant