let peek itr i =
if i < 0 || i >= itr.len then raise(Out_of_bounds "Rope.Iterator.peek")
else (
if itr.current_g0 <= i && i < itr.current_g1 then
itr.current.[i + itr.current_offset]
else
get itr.rope i (* rope get *)
)
This checks the more general constraint (out-of-bounds) before checking the good path. Given that we can assume current_g0 and current_g1 to be within the rope's bounds, we can prioritize their check without risking out-of-bounds:
let peek itr i =
if itr.current_g0 <= i && i < itr.current_g1 then
itr.current.[i + itr.current_offset]
else if i < 0 || i >= itr.len then
raise(Out_of_bounds "Rope.Iterator.peek")
else
get itr.rope i (* rope get *)
This should bring a small performance benefit when algorithms are within the local bounds a lot, which is generally why iterators are used in the first place.
By the same token, get can also check the local bounds first.
On a related note, what is the reason for peek to not update the current leaf like get does? I ran into a bit of a performance trap with an algorithm that would just call peek a lot and thus never update the current leaf. My intuition was that get itr = peek itr (pos itr).
This is the current implementation of
peek
:This checks the more general constraint (out-of-bounds) before checking the good path. Given that we can assume
current_g0
andcurrent_g1
to be within the rope's bounds, we can prioritize their check without risking out-of-bounds:This should bring a small performance benefit when algorithms are within the local bounds a lot, which is generally why iterators are used in the first place.
By the same token,
get
can also check the local bounds first.On a related note, what is the reason for
peek
to not update the current leaf likeget
does? I ran into a bit of a performance trap with an algorithm that would just callpeek
a lot and thus never update the current leaf. My intuition was thatget itr = peek itr (pos itr)
.