I have previously posted a NetLogo lists tutorial, but I thought I’d post a few more NetLogo list examples, highlighting the primitives `reduce`

, `map`

, and `n-values`

.

## reduce

The `reduce`

primitive converts the one-element list [ *x* ] to *x*, but more interesting is what `reduce`

does with the list *L* = [ *x*_{1} *x*_{2} *x*_{3} … *x*_{n} ]. Given a binary operator ⊕, *L* is converted to:

((*x*_{1} ⊕ *x*_{2}) ⊕ *x*_{3}) … ⊕ *x*_{n}

Therefore `reduce + L`

, equivalent to `reduce [?1 + ?2] L`

, adds up all the elements of a list, just like `sum L`

. However, we can invent our own binary operators. For example, the code `reduce [10 * ?1 + ?2] L`

converts a list of digits like [ 2 6 0 4 3 ] to the corresponding integer (26043).

A useful variation is `reduce ⊕ (fput e L)`

, which calculates:

(((*e* ⊕ *x*_{1}) ⊕ *x*_{2}) ⊕ *x*_{3}) … ⊕ *x*_{n}

This form allows the operator ⊕ to take arguments of two different kinds. Using a reversed version of `fput`

, for example, gives a (slow) way of reversing a list:

`reduce [ fput ?2 ?1 ] (fput [] lst)`

## map

The `map`

primitive has two forms. Given a function f and a single list (`map f L`

), the list

*L* = [ *x*_{1} *x*_{2} *x*_{3} … *x*_{n} ] is converted to:

[ *f x*_{1} *f x*_{2} *f x*_{3} … *f x*_{n} ]

The execution is done left-to-right, and so the *f x*_{i} can be linked together if f has side-effects. For example, consider the following code, which defines a reporter (function) `add-to-total`

which adds its argument to a global variable, and then returns the value of that variable:

```
globals [ total ]
to-report add-to-total [ x ]
set total (x + total)
report total
end
```

If we initialise `total`

to 0, then `map add-to-total L`

(or `map [ add-to-total ? ] L`

) will construct a list of partial sums of `L`

, converting e.g. [ 2 6 0 4 3 ] to [ 2 8 8 12 15 ]. For a more complex example, we can perform the ISBN check-digit calculation I recently posted about:

Given an ISBN in the form of a string, we can extract the last digit (the check digit) using `last`

, converting it to a number with `read-from-string`

if it is not “X”, and using `but-last`

to get the other 9 digits:

```
let isbn "0936385405"
let chk (last isbn)
if (chk != "X") [ set chk (read-from-string chk) ]
let digits (but-last isbn)
```

To expand out these digits, we use `n-values`

. This is a lot like `map`

, except it takes a number *n* as input, forms the list [ 0 1 2 … *n*–1 ], and applies a function to the elements of that. Here we use `n-values`

twice: once to index all the possible positions in the string `digits`

, converting it to a list of numbers; and once to generate the list [ 10 9 8 … 2 ]:

```
set digits (n-values (length digits) [ read-from-string (item ? digits) ])
let multiplier (n-values 9 [ 10 - ? ])
```

We use `map`

with two lists (in parentheses to indicate that there is more than one list) to multiply pairs of elements from these two lists, and `sum`

to add up the products:

`let computed (sum (map [ ?1 * ?2 ] digits multiplier))`

Finally, the negation of this sum mod 11 is the required check digit (with 10 represented by “X”):

```
set computed ((- computed ) mod 11)
if (computed = 10) [ set computed "X" ]
ifelse (computed = chk)
[ print (word isbn " is OK") ]
[ print (word isbn " should end in " computed ", not " chk) ]
```

### Like this:

Like Loading...