Higher Order List Operations and Rings

There’s an even easier way to select the even numbers from a list:

(If you don’t have the keep block near the bottom of the Variable palette, click the File button in the tool bar and select “Import tools…”)

The keep block takes a Predicate expression as its first input, and a list as its second input. It reports a list containing those elements of the input list for which the predicate returns true. Notice two things about the predicate input: First, it has a grey ring around it. Second, the mod block has an empty input. Keep puts each item of its input list, one at a time, into that empty input before evaluating the predicate. (The empty input is supposed to remind you of the “box” notation for variables in elementary school: ☐+3=7.) The grey ring is part of the keep block as it appears in the palette:

image

What the ring means is that this input is a block (a predicate block, in this case, because the interior of the ring is a hexagon), rather than the value reported by that block. Here’s the difference:

image image

Evaluating the = block without a ring reports true or false; evaluating the block with a ring reports the block itself. This allows keep to evaluate the = predicate repeatedly, once for each list item. A block that takes another block as input is called a higher order block (or higher order procedure, or higher order function).

Snap! provides three higher order blocks for operating on lists:

image

You’ve already seen keep. Map takes a Reporter block and a list as inputs. It reports a new list in which each item is the value reported by the Reporter block as applied to one item from the input list. That’s a mouthful, but an example will make its meaning clear:

image

By the way, we’ve been using arithmetic examples, but the list items can be of any type, and any reporter can be used. We’ll make the plurals of some words:

image

These examples use small lists, to fit the page, but the higher order blocks work for any size list.

The map block has arrowheads at the right end because of a little-used feature that allows mapping through multiple same-length lists in parallel, with a multi-input reporter expression. Don’t worry about it for now; just make sure when you drag an expression into the list input slot that you hit the slot and not the arrowheads.

The third higher order block, combine, computes a single result from all the items of a list, using a two-input

reporter as its first input. In practice, there are only a few blocks you’ll ever use with combine:

image

These blocks take the sum of the list items, take their product, string them into one word, combine them into a sentence (with spaces between items), see if all items of a list of Booleans are true, or see if any of the items is true.

image

Why + but not −? It only makes sense to combine list items using an associative function: one that doesn’t care in what order the items are combined (left to right or right to left). (2+3)+4 = 2+(3+4), but (2−3)−4 ≠ 2−(3−4).

  • Typed Inputs