How is the situation with closures?

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 :slight_smile:

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).

4 Likes