# Add Array#insert(Int, Enumerable(T)) overload

**URL:** <https://forum.crystal-lang.org/t/add-array-insert-int-enumerable-t-overload/6723>\
**Category:** Crystal Contrib\
**Created:** [March 28, 2024, 3:34am UTC](https://forum.crystal-lang.org/t/add-array-insert-int-enumerable-t-overload/6723 "2024-03-28T03:34:45Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![echo](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/echo/32/2008_2.png) [@echo](https://forum.crystal-lang.org/u/echo)\
**Post date:** [March 28, 2024, 3:34am UTC](https://forum.crystal-lang.org/t/add-array-insert-int-enumerable-t-overload/6723/1 "2024-03-28T03:34:45Z")

</div>

I’d like to suggest adding an overload to [`Array(T)#insert`](https://crystal-lang.org/api/1.11.2/Array.html#insert%28index%3AInt%2Cobject%3AT%29%3Aself-instance-method) that allows an Array (or Enumerable/Iterable/etc.) to be passed as an argument.

In my shard, I process a list of nodes, parsing any markup that may be present. I make use of a method I defined called [`insert_all`](https://codeberg.org/supercell/luce/src/commit/a956779178/src/luce/util.cr#L264), which inserts all elements of an array into another array. The downside is that it involves reopening the `Array` class, meaning any project using mine will also have the method, potentially causing issues.

I’m currently in the process of removing all instances of “reopening standard classes” and noticed that the standard library doesn’t seem to provide a “nice” way to insert an array into another array at a specific index. Please correct me if I’m wrong!

This is possible in Ruby with [`Array#insert`](https://apidock.com/ruby/Array/insert), in C# with [`List.InsertRange`](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1.insertrange?view=net-8.0), in Dart with [`List.insertAll`](https://api.dart.dev/stable/3.3.3/dart-core/List/insertAll.html), and probably others.

Below is an example adapted from [the actual usage in my shard](https://codeberg.org/supercell/luce/src/commit/fbb02263/src/luce/document.cr#L118).

```crystal
class Node; end

class UnparsedNode < Node
  getter text_content : String

  def initialize(@text_content : String)
  end
end

class ParsedNode < Node
  getter children : Array(Node)

  def initialize(str : String)
    @children = [] of Node
  end
end

class Document
  def parse(content : String) : Array(Node)
    block_nodes = parse_blocks(content)
    parse_inline_nodes(block_nodes)
  end

  def parse_blocks(content : String) : Array(Node)
    # ...
    content.split("\n\n").map { |raw| UnparsedNode.new(raw) }.as Array(Node)
  end

  def parse_inline(content : String) : Array(Node)
    # ...
    content.split(" ").map { |parsed| ParsedNode.new(parsed) }.as Array(Node)
  end

  def parse_inline_nodes(nodes : Array(Node)) : Nil
    i = 0
    while i < nodes.size
      node = nodes[i]
      if node.is_a? UnparsedNode
        inline_nodes = parse_inline(node.text_content)
        nodes.delete_at(i)
        nodes.insert(i, inline_nodes) #################
        i += inline_nodes.size - 1
      elsif node.is_a?(ParsedNode) && node.children.size > 0
        parse_inline_nodes(node.children)
      end
      i += 1
    end
  end
end

Document.new.parse(%[
# Heading

inline *markup*
])

```

As far as I’m aware, there are two main ways to accomplish the same task (again, correct me if there’s something easier!)

```crystal
arr = [1, 2, 3, 7]
# Option 1:
arr = arr[0..2] + [4, 5, 6] + arr[3..]
# Option 2:
arr[3, 0] = [4, 5, 6]

```

Personally, I think `arr.insert(3, [4, 5, 6])` is cleaner and more explicit in what’s happening.

---

<div class="post-metadata">

**Author:** ![yxhuvud](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/yxhuvud/32/27_2.png) [@yxhuvud](https://forum.crystal-lang.org/u/yxhuvud)\
**Post date:** [March 28, 2024, 9:22am UTC](https://forum.crystal-lang.org/t/add-array-insert-int-enumerable-t-overload/6723/2 "2024-03-28T09:22:59Z")

</div>

Well, there is also

```auto
x = [1,2,3,4,5]

x[1...1] = [6,7,8]

p x # => [1, 6, 7, 8, 2, 3, 4, 5]

```

Which is not really an argument either way, but it is possible without too much effort.

---

<div class="post-metadata">

**Author:** ![straight-shoota](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/straight-shoota/32/36_2.png) [@straight-shoota](https://forum.crystal-lang.org/u/straight-shoota)\
**Post date:** [March 28, 2024, 11:28am UTC](https://forum.crystal-lang.org/t/add-array-insert-int-enumerable-t-overload/6723/3 "2024-03-28T11:28:54Z")

</div>

It’s nice to see proposals for enhancements that have proven themselves as useful local extensions already.

I think this makes a lot of sense. While there is already a syntax for this with range assignment, I believe an explicit method describes the intention much better and is easier to understand.

It would probably be best to keep the name `#insert_all` though to make a clear distinction between inserting a single element (which could also be an enumerable!) and inserting a list of elements.

---

<div class="post-metadata">

**Author:** ![echo](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/echo/32/2008_2.png) [@echo](https://forum.crystal-lang.org/u/echo)\
**Post date:** [March 29, 2024, 8:19am UTC](https://forum.crystal-lang.org/t/add-array-insert-int-enumerable-t-overload/6723/4 "2024-03-29T08:19:25Z")

</div>

> It would probably be best to keep the name `#insert_all` though to make a clear distinction between inserting a single element (which could also be an enumerable!) and inserting a list of elements.

This would be my preference as well. I only suggested using `insert` to match Ruby.

While my implementation currently accepts `Iterable(T)`, I’m doubtful that this alone is the best choice. Should `Enumerable(T)` be used or a combination of them (either through separate methods or a union type)?
