janet-lang / janet

A dynamic language and bytecode vm
https://janet-lang.org
MIT License
3.38k stars 217 forks source link

Error stating 3 is not an integer? #1315

Closed CubicMelon closed 9 months ago

CubicMelon commented 9 months ago

Hi all, I'm not sure if this is a result of me doing something very confusing for the compiler or something, but I'm getting a very strange error with this function:

(defn drpts "draw points" [color list]
  (let [part-list (partition 2 list)]
    (loop [i :range [0 (length part-list)]]
      (T/line ((part-list i) 0) ((part-list i) 1) ((part-list (+ i 1)) 0) ((part-list (+ 1 i)) 1) color))))

(there is probably a far better way to do this, but this is the best I could come up with in my inexperience) In any case, the issue is when I call this function, it does what is intended correctly but then gives an error saying:

repl:579:> (drpts 6 [1 2 3 4 5 6])
tic80/line: x0=1 y0=2 x1=3 y1=4 color=6 
tic80/line: x0=3 y0=4 x1=5 y1=6 color=6
error: expected integer key for array in range [0, 3), got 3
  in drpts [repl] on line 578, column 56
  in _thunk [repl] (tailcall) on line 579, column 1

Why is it complaining about 3 not being an integer? It's very strange.

Thanks for any insight!

sogaiu commented 9 months ago

I think the message is saying that the expectation was for a value that is 0, 1, or 2, but it got 3.

IIUC, the [0, 3) notation is from math -- a half-open interval (so 0 is included but 3 is not).

May be you are familiar already, but FWIW, there are some details in this section of a Wikipedia page (no direct link -- searching for "half-open" may get one closer).

CFiggers commented 9 months ago

Your (length part-list) is returning 3, which means your loop is going to run a total of four times (because you're starting at zero, so it will run for i = {0, 1, 2, 3}). But a zero-indexed array with three elements only goes up to a max of 2.

To fix it, you could decrement that value (like this: (dec (length part-list))) so that you only run the loop three times (on 0, 1, 2).

EDIT: Although actually, looking at the body of your loop, you're incrementing the i to get the next element in the array. So that will go out of bounds when the loop runs on i = 2. You might want to try (- 2 (length part-list)) instead of what I wrote above.

EDIT AGAIN: Actually I think I was wrong above, because the :range keyword in (loop) goes UP TO the second number but doesn't include it. So only decrementing the counter a single time should be fine, only because you're looking one ahead in the body of the loop 🙂

CubicMelon commented 9 months ago

That was it, I had to decrement the end of the range by 1 because I was looking one index ahead each loop! That's what I get for trying to write this overnight. Thanks so much for helping me understand.