rubyguides

Array#prepend

arr.prepend(*objects) -> arr

Array#prepend adds one or more elements to the beginning of an array, mutating it in place. It returns the same array object, allowing method chaining.

Syntax

array.prepend(*objects)

Parameters

ParameterTypeDefaultDescription
*objectsObjectRequiredOne or more objects to add to the array

Examples

The following examples walk through the core behaviors of prepend, starting with a simple single-element insertion and building up to multiple arguments, method chaining, common patterns, and edge cases. Each example shows the array both before and after the call so you can see exactly how the mutation changes the receiver.

Basic usage

queue = ["second", "third"]
queue.prepend("first")
queue
# => ["first", "second", "third"]

The example above shows that prepend changes the array in place and returns the modified object. After the call, queue contains the new element at index zero, and the remaining elements shift to the right. This mutation is visible to any other part of the program that holds a reference to the same array, so make sure that the side effect is expected by the surrounding code before choosing prepend over a non-mutating alternative.

Adding multiple elements

numbers = [3, 4, 5]
numbers.prepend(1, 2)
numbers
# => [1, 2, 3, 4, 5]

When you pass several arguments to prepend, each one is inserted at the front in the order they are given. The first argument ends up closest to the original elements, and the last argument becomes the new first element. This is the same ordering you would get by calling prepend once for each argument, so the multi-argument form is just a convenient shorthand for repeated single-argument calls.

Method chaining

result = [].prepend(2).prepend(1)
result
# => [1, 2]

Method chaining with prepend works because the method returns self — the same array object. Each call to prepend modifies the array and passes it along to the next method in the chain. This pattern is concise for building arrays step by step, but it can be harder to debug than assigning intermediate results to named variables. Use chaining when the construction logic is simple and the intent is obvious from the method names.

Common Patterns

Queue implementation with prepend

queue = ["task2", "task3"]
queue.prepend("task1")  # Add to front
queue.shift             # => "task1"

Using prepend and shift together creates a natural queue where items enter at the front and leave from the front. This is a LIFO stack rather than a FIFO queue, because the most recently prepended item is the first to be shifted. For a true FIFO queue where the oldest item comes out first, pair push with shift instead. The naming is intuitive once you remember that prepend places items at the beginning and shift removes from the beginning.

Building a list in reverse order

items = []
items.prepend("third")
items.prepend("second")
items.prepend("first")
# => ["first", "second", "third"]

Building a list in reverse by repeatedly calling prepend creates the final order in one pass without needing to reverse the array afterward. Each call pushes the next item to the front, so the last item prepended becomes the first element of the finished array. This pattern reads naturally when the data arrives in reverse order, such as processing log entries from newest to oldest and wanting the output in chronological order.

Edge Cases

Adding nil or false

arr = [1, 2]
arr.prepend(nil)
arr.prepend(false)
arr
# => [false, nil, 1, 2]

prepend treats nil and false the same as any other value — they are added to the front without special handling. This is different from methods like compact that filter out nil values. If you need to prepend only non-nil elements, check the values before passing them or use a conditional approach that builds the argument list selectively.

Adding to empty array

arr = []
arr.prepend("first")
arr
# => ["first"]

Prepending to an empty array produces a single-element array, which is the same result you would get from << or push on an empty array. The difference is positional: prepend places the element at index zero, while push places it at the end. When the array is empty, the position does not matter, but the choice of method still signals intent — prepend suggests that more items will follow at the front, while push suggests the opposite.

Adding mixed types

mixed = []
mixed.prepend(1, "two", :three)
mixed
# => [1, "two", :three]

Unlike typed collections in other languages, Ruby arrays happily store elements of different types together. prepend does not care about the class of each argument, so you can mix strings, symbols, integers, and even other arrays in a single call. This flexibility is convenient for quick prototyping, but in production code it is usually better to keep array elements uniform so that downstream consumers can make reliable assumptions about each item.

Performance Notes

prepend mutates the array in place. However, it may require shifting all existing elements, making it O(n) in the worst case. For frequent front insertions, consider using a different data structure like a linked list.

when adding to the front makes sense

prepend is a good match when the earliest item should stay at the front of the list, such as a queue, a reversed build step, or a data set that is assembled from newest to oldest. The method says plainly that the array is changing in place, so the code should make that side effect obvious to the reader. If the surrounding logic needs a fresh array instead, a non-mutating approach will usually be easier to follow.

The method is often easiest to read when the array name already implies that it is a working collection. That way the reader expects the object to change as the program runs, and the front insertion feels natural instead of surprising. It is a small method, but the choice still matters because it affects the object that other code may still be holding. Clear naming and a small surrounding scope make that choice easier to trust.

When the array is used as a queue or a build list, prepend can keep the order of the final result straightforward. The code can add items at the front while the surrounding logic continues to treat the array as the same live object. That makes the method a practical fit for small stateful workflows, especially when the code wants to avoid creating a new array just to place one item at the start.

See Also