Skip to content

Commit

Permalink
List; add remove(value)
Browse files Browse the repository at this point in the history
Having to encode this behaviour at every call site is tedious. It makes a lot of sense to just have the method available on list itself.
  • Loading branch information
ruby0x1 committed Apr 4, 2021
1 parent 4d1d0d9 commit ecce1f6
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 3 deletions.
18 changes: 15 additions & 3 deletions doc/site/lists.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -113,21 +113,33 @@ System.print(combined) //> [a, b, c, d, e, f]
## Removing elements

The opposite of `insert` is `removeAt`. It removes a single element from a
given position in the list. All following items are shifted up to fill in the
gap:
given position in the list.

To remove a specific _value_ instead, use `remove`. The first value that
matches using regular equality will be removed.

In both cases, all following items are shifted up to fill in the gap.

<pre class="snippet">
var letters = ["a", "b", "c", "d"]
letters.removeAt(1)
System.print(letters) //> [a, c, d]
letters.remove("a")
System.print(letters) //> [c, d]
</pre>

The `removeAt` method returns the removed item:
Both the `remove` and `removeAt` method return the removed item:

<pre class="snippet">
System.print(letters.removeAt(1)) //> c
</pre>

If `remove` couldn't find the value in the list, it returns null:

<pre class="snippet">
System.print(letters.remove("not found")) //> null
</pre>

If you want to remove everything from the list, you can clear it:

<pre class="snippet">
Expand Down
20 changes: 20 additions & 0 deletions doc/site/modules/core/list.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,26 @@ list.

[iterator protocol]: ../../control-flow.html#the-iterator-protocol

### **remove**(value)

Removes the first value found in the list that matches the given `value`,
using regular equality to compare them. All trailing elements
are shifted up to fill in where the removed element was.

<pre class="snippet">
var list = ["a", "b", "c", "d"]
list.remove("b")
System.print(list) //> [a, c, d]
</pre>

Returns the removed value, if found.
If the value is not found in the list, returns null.

<pre class="snippet">
System.print(["a", "b", "c"].remove("b")) //> b
System.print(["a", "b", "c"].remove("not found")) //> null
</pre>

### **removeAt**(index)

Removes the element at `index`. If `index` is negative, it counts backwards
Expand Down
8 changes: 8 additions & 0 deletions src/vm/wren_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,13 @@ DEF_PRIMITIVE(list_removeAt)
RETURN_VAL(wrenListRemoveAt(vm, list, index));
}

DEF_PRIMITIVE(list_removeValue) {
ObjList* list = AS_LIST(args[0]);
int index = wrenListIndexOf(vm, list, args[1]);
if(index == -1) RETURN_NULL;
RETURN_VAL(wrenListRemoveAt(vm, list, index));
}

DEF_PRIMITIVE(list_indexOf)
{
ObjList* list = AS_LIST(args[0]);
Expand Down Expand Up @@ -1411,6 +1418,7 @@ void wrenInitializeCore(WrenVM* vm)
PRIMITIVE(vm->listClass, "iterate(_)", list_iterate);
PRIMITIVE(vm->listClass, "iteratorValue(_)", list_iteratorValue);
PRIMITIVE(vm->listClass, "removeAt(_)", list_removeAt);
PRIMITIVE(vm->listClass, "remove(_)", list_removeValue);
PRIMITIVE(vm->listClass, "indexOf(_)", list_indexOf);
PRIMITIVE(vm->listClass, "swap(_,_)", list_swap);

Expand Down
18 changes: 18 additions & 0 deletions test/core/list/remove.wren
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
var a = [1, 2, 3]
a.remove(2)
System.print(a) // expect: [1, 3]

var b = [1, 2, 3]
b.remove(1)
System.print(b) // expect: [2, 3]

var c = [1, 2, 3]
c.remove(3)
System.print(c) // expect: [1, 2]

// Return the removed value.
System.print([3, 4, 5].remove(4)) // expect: 4
System.print([3, 4, 5].remove(5)) // expect: 5

// Return null when not found
System.print([1, 2, 3].remove(8)) // expect: null

0 comments on commit ecce1f6

Please sign in to comment.