Hey @houghtonap, thanks for the article.
It looks like you’ve got a small bug in your program:
const len = text.len;
...
const last = if (this.end > len) len else end;
return text[first .. last + 1];
If last is equal to text.len
, then this will read one index beyond the end of the string.
I’d recommend changing those lines to:
const last = @min(this.end + 1, text.len);
return text[first..last];
Personally, I’d just keep it to non-inclusive ranges to be consistent, but I get that you’re trying to mimic another function
I think that the example/template, however, is more complex than it needs to be. For instance, we don’t actually need the ClosureScope
object. You can pass the integers directly into the function as comptime arguments:
fn foo(comptime begin: usize, comptime end: usize) ClosureType {
return struct {
fn closure(text: []const u8) []const u8 {
return text[@min(begin, text.len)..@min(end + 1, text.len)];
}
}.closure;
}
I bring this up not to disparage your article (it’s well written and well intended). I think it’s introducing more steps than are actually necessary.
I also think you should point out that this is for comptime-known parameters. This won’t work for runtime closures (which are doable, but there’s more machinery involved).