Skip to content

Step 1 of 3 · Reading · ~2 min

Range Queries

Lists

LRANGE: reading without removing

LPOP/RPOP destructively remove elements. Most real usage of lists — paginating a feed, reading the last N log lines, inspecting a job queue — needs a read-only view of a slice. That's LRANGE.

Index normalization

LRANGE key start stop accepts negative indices, Python-slice style: -1 is the last element, -2 the second-to-last. The first job is converting these into valid non-negative array positions:

python

Note the stop + 1LRANGE is inclusive on both ends, unlike Python's own slicing which excludes the stop index. This is the single most common off-by-one bug in list implementations: LRANGE mylist 0 2 must return 3 elements (indices 0, 1, 2), not 2.

Clamping, not erroring

Out-of-range indices are clamped rather than rejected:

  • LRANGE mylist 0 1000 on a 3-element list returns all 3 elements — stop clamps down to length - 1.
  • LRANGE mylist -1000 -1 returns the whole list — start clamps up to 0.
  • LRANGE mylist 5 10 on a 3-element list returns an empty array (start > stop after clamping), not an error.

Missing keys and empty results

A nonexistent key isn't an error case for LRANGE — it behaves exactly like an empty list, replying with *0\r\n (a zero-length RESP array). Route both "key never existed" and "start/stop clamp to nothing" through the same empty-array code path so you don't end up with two subtly different "empty" replies.

Encoding the reply

A RESP array wraps each element as its own bulk string:

*3\r\n
$1\r\n
a\r\n
$1\r\n
b\r\n
$1\r\n
c\r\n

Write a shared encode_array(items) helper now — you'll reuse it for HGETALL, SMEMBERS, and ZRANGE later in this course, and having one tested implementation of "array of bulk strings" saves you from re-debugging the same \r\n mistakes four times.

Up nextHSET & HGET — Field-Level StorageHashes

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…