diff --git a/infra.bs b/infra.bs index a5662fd..2d8bc04 100644 --- a/infra.bs +++ b/infra.bs @@ -1319,6 +1319,12 @@ out-of-bounds, except when used with exists. "b", "c", "a" ». Then |example|[1] is the string "b". +

Lists can also have holes, which mark the location of a deleted value. Holes are not exposed to any algorithm unless explicitly called out; in all other cases, holes are treated as if they did not exist and are automatically skipped over. There is no literal syntax for holes. + +

For example, if the list « 0, 1, 2 » has the item at index 1 [=list/removed=], it leaves behind a hole in its position. Subsequent requests for the item at index 1 will now return 2, as index counting skips over holes unless otherwise specified; similarly, the list will report its [=list/size=] as 2 rather than 3. + +Note: Holes exist to make [=list/iteration=] stable and predictable when the list can be mutated during the iteration, matching ECMAScript behavior. If the [=list=] is read-only or not currently being iterated by anything, [=list/holes=] can be omitted or removed. +


To append to a list that is not an ordered set is to @@ -1356,7 +1362,7 @@ index is to add the given item to the list between the given index − 1 and the given index is 0, then prepend the given item to the list.

To remove zero or more items from a list is -to remove all items from the list that match a given condition, or do nothing if none do. +to remove all items from the list that match a given condition, replacing each with a [=list/hole=], or do nothing if none do.

Removing |x| from the list « |x|, |y|, |z|, |x| » is to remove all @@ -1369,7 +1375,7 @@ to remove all items from the list that match a given condition, or do nothing if

To empty a list is to remove -all of its items. +all of its items, replacing all of them with [=list/holes=].

A list contains an item if it appears in the list. We can also denote this by saying that, for a @@ -1385,15 +1391,30 @@ its size is zero. list, return the range from 0 to the list's size, exclusive. -

To iterate over a list, performing a -set of steps on each item in order, use phrasing of the form -"For each |item| of list", and then operate on |item| in the -subsequent prose. +

To iterate over a list |list|, +performing a set of steps |steps| on each item in order, perform [=list iteration=] +using |list| and |steps|. This can also be (and usually is) written as "[=list/For each=] +|item| of |list|: |steps|". + +

+ + List iteration over a [=list=] |list|, given some per-item |steps|, means to: + + 1. Let |index| initially be 0. + 1. While |index| < |list|'s [=list/size=] (including [=list/holes=]): + 1. Let |item| be |list|[|index|] (including [=list/holes=]). + 1. Increment |index| by 1. + 1. If |item| is a [=list/hole=], [=iteration/continue=]. + 1. Invoke |steps| with |item|. + + Note: Entries deleted from the list before being visited will not be processed. + Otherwise, every entry in a list is visited exactly once, including any entries added after iteration has begun. +

To clone a list |list| is to create a new list |clone|, of the same designation, and, for each |item| of |list|, append |item| to |clone|, so that |clone| contains the same -items, in the same order as |list|. +items, in the same order as |list|, omitting any [=list/holes=] that |list| contains.

This is a "shallow clone", as the items themselves are not cloned in any way. @@ -1539,6 +1560,10 @@ entries with a comma. "a" → `x`, "b" → `y` ]». Then |example|["a"] is the byte sequence `x`. +

[=Maps=] can have holes, which mark the location of a deleted value. A hole is considered to have a key and value which are also holes. Holes are not exposed to any algorithm unless explicitly called out; in all other cases, holes are treated as if they did not exist and are automatically skipped over. There is no literal syntax for holes. + +Note: As with [=list=] [=list/holes=], these exist solely to make [=map/iteration=] stable and predictable, and to match ECMAScript Map iteration. If the [=map=] is read-only, or nothing is iterating the map, [=map/holes=] can be omitted or removed. +


To get the value of an entry in an @@ -1565,12 +1590,12 @@ also denote this by saying, for an ordered map |map|, key |key|, and valu "set |map|[|key|] to |value|".

To remove an entry from an ordered map is to remove -all entries from the map that match a given condition, or do nothing if none do. If +all entries from the map that match a given condition, replacing them with [=map/holes=], or do nothing if none do. If the condition is having a certain key, then we can also denote this by saying, for an ordered map |map| and key |key|, "remove |map|[|key|]".

To clear an ordered map is to remove all entries -from the map. +from the map, leaving [=map/holes=] in their places.

An ordered map contains an entry with a given key if there exists an entry with that key. @@ -1591,10 +1616,25 @@ of running get the keys on the map.

An ordered map is empty if its size is zero. -

To iterate over an ordered map, performing -a set of steps on each entry in order, use phrasing of the form -"For each |key| → |value| of |map|", and then operate on |key| and |value| in the -subsequent prose. +

To iterate over an ordered map |map|, +performing a set of steps |steps| on each [=map/entry=] in order, perform [=map iteration=] +using |map| and |steps|. This can also be (and usually is) written as "[=map/For each=] +|key| → |value| of |map|: |steps|". + +

+ Map iteration over a [=map=] |map|, given some per-item |steps|, means to: + + 1. Let |index| initially be 0. + 1. While |index| < |map|'s [=map/size=] (including [=map/holes=]): + 1. Let |entry| be the |index|th entry in [=map=] (including [=map/holes=]). + 1. Increment |index| by 1. + 1. If |entry| is a [=map/hole=], [=iteration/continue=]. + 1. Let |key| and |value| be the [=map/key=] and [=map/value=] of |entry|. + 1. Invoke |steps| with |key| and |value|. + + Note: Entries deleted from the map before being visited will not be processed. + Otherwise, every entry in a map is visited exactly once, including any entries added after iteration has begun. +

To clone an ordered map |map| is to create a new ordered map |clone|, and, for each |key| → |value| of |map|,