How to clean up this code? (checking for nil)

Hi… Crystal newbie here… I’m struggling with having to check for nil values.

start = 0
if match = text.match(someRegex, start)
      name = match[1]
      if b = match.begin
        output += text[start..b - 1]
       # ...

I can’t use match.begin directly because it complains about being type nil|Int32… even though I’ve already checked that match is truthy in the first if statement.

Is there any way to ensure match.begin is not nil when match is not nil? Alternatively, some type of shorter syntax than having to have multiple if clauses.

This actually looks like a bug in the regex API.

match.begin is only nilable because String#byte_index_to_char_index returns nil if the byte index is out of range. But in this case, it is ensured to be in range, so the return type of match.begin should just be Int32.

I recommend it rarely, but this is probably a good use case for .not_nil! as a workaround.

1 Like
3 Likes

@speg I threw in some values for the variables to try it and it seems to work. Is it possible that the bug exists elsewhere in your code but is manifesting here?

To be clear, though, this part of the type system is also where I struggled the most while learning Crystal :-)

1 Like

The bug is that match.begin is nilable when it really shouldn’t. So this has nothing to do with user code. The OP’s code just shows a bug in stdlib.

I must’ve misread, I thought they were saying that the code as written doesn’t compile. On second reading, though, I see that might not be what they meant.