Overview
I posted this as an Issue on Github, but I figured this might be a better place to have those discussions. I’ve been working with Strings a bunch, both natively and within JavaScript, and there seems to be some edge cases with both string literals as well as the String module itself:
- odd exceptions & errors when retrieving substrings
- parsing issues with escaped strings (esp
\"
)
This isn’t the first time I’ve run into this with Reason, but it is the first time it’s caused a bit of a show stopper for me (I’m currently working around it in JavaScript by calling JavaScript’s String.prototype.substring
method, I’ll figure out a work around for native). These all seemed pretty surprising to me, but perhaps I just am misunderstanding something pretty fundamental.
Thank you for your help!
Substring issues:
Reason # let src = "\"test\"\n\"foo\"\n"
;
let src: string = "\"test\"\n\"foo\"\n";
Reason # String.length(src)
;
- : int = 13
Reason # String.sub(src, 8, 11)
;
Exception: Invalid_argument("String.sub / Bytes.sub").
Reason # String.sub(src, 1, 4)
;
- : string = "test"
Parsing issues:
I ran into this in a different context, wherein Escaped strings cause the compiler to complain about missing braces, but I ran into a similar edge case today:
Reason # let src1 = "\"test\""foo\"";
let src1: string = "\"test\"";
Reason # String.length(src1);
- : int = 6
Substrings
The length of the string is 11, but String.sub
returns an error; when we start to slice more towards the beginning of the string, we see some odd behavior:
Reason # let src2 = "\"test\"\"foo\"";
let src2: string = "\"test\"\"foo\"";
Reason # String.length(src2);
- : int = 11
Reason # String.sub(src2, 7, 9);
Exception: Invalid_argument("String.sub / Bytes.sub").
Reason # String.sub(src2, 5, 7);
Exception: Invalid_argument("String.sub / Bytes.sub").
Reason # String.sub(src2, 4, 6);
- : string = "t\"\"foo"
Reason # String.sub(src2, 3, 5);
- : string = "st\"\"f"
Reason # String.sub(src2, 4, 6);
- : string = "t\"\"foo"
Reason # String.sub(src2, 3, 6);
- : string = "st\"\"fo"
- I wouldn’t have expected an
Invalid_argument
for anything between 5 & 9 in this string - I also wouldn’t have expected
String.sub(src2 ,4, 6)
to return"t\"\"foo"
, which looks almost like it’s returning the tail of a list or the like - The behavior isn’t consistent,
String.sub
is different for 3 to 5, 4 to 6, and 3 to 6.