On this page

NLRoot and inherited utilities reference

Manual contents | Tools and utilities | Main reference | Patch reference | Turtle reference | Supporting types | Alphabetical index

Sources: nlroot.js and its base, apiroot.js. Main, Patch, and Turtle inherit from NLRoot. This page inventories NLRoot declarations and the APIRoot members available through that inheritance. It distinguishes source contracts from recommended modeling patterns; it does not repair or endorse legacy helpers simply because they are inherited.

1. Static versus instance calls

import {NLRoot} from "@nwk/api/nlroot.js";

const tokens = NLRoot.parse('tree "burning patch"');
const average = NLRoot.mean([2, 4, 6]);
const total = NLRoot.sum(value => value * 2, [1, 2, 3]);

These are static calls on the class, available without a world. Inheritance makes NLRoot.random available from APIRoot, not this.random(). Instance helpers such as this.any or this.newCoords belong to a model object. Do not instantiate an extra NLRoot as a replacement for Main, Patch, or Turtle.

Most helpers do not validate callback results, finite numbers, or collection shapes. Give them compatible inputs; callback exceptions propagate. For a first model, ordinary arrays and JavaScript filter/map/reduce are often clearest.

2. Context, construction, and reset

Instance member Contract
constructor(main) Calls the APIRoot constructor; stores main or this when main is falsy, and allocates stores as a new Set. Does not initialize a world, clock, coordinates, or populations.
main Owner reference. Main points to itself; patches/turtles point to their Main.
stores Base local-reset collection of objects supporting reinitialize(). Merely putting a Store here does not synchronize, activate, evaluate, or report it.
rows, cols Read/write accessors over _rows/_cols; no validation/default or implicit forwarding to Main. Main/Turtle populate them; Patch does not. Use patch.main.rows/cols.
reset() Calls reinitialize() on each entry in stores, returning undefined. No world orchestration, setup, time reset, or cleanup of listeners.

Overrides matter: NLSimMain and NLPatch override reset without calling this base reset; NLTurtle supplies its own built-in Store list and reset loop. Do not assume adding state to an inherited stores collection makes every subclass reset it. Allocate/register/restore custom state explicitly on its owner. See state ownership.

3. Coordinates and sampled paths

Instance signature Result and prerequisites
newCoords(x, y) Delegate to main.coordsFactory.create(x, y), returning a coordinate object. Requires initialized Main context. No boundary normalization, finite validation, indexing, or movement.
path(start, end) Array of coordinate objects sampled toward end in distance increments of 0.5. Inputs need numeric x/y properties; requires the coordinate factory. Begins with the exact start, then floored sample coordinates from distance zero onward.

path is a legacy sampled grid path, not a unique neighborhood or a general line-geometry algorithm. With the current factory each sample creates a new object, so identity-based includes does not deduplicate equal coordinates. The exact fractional endpoint is not appended; flooring loses fractional position, and an endpoint whose distance is not a half-unit multiple may not be sampled at all. No seam shortest path, hex physical scaling, or outside-world policy is applied. The Turtle trail methods use this helper; do not treat it as certified continuous collision detection.

For square grid selections use the neighborhood reference. For explicit movement use the Turtle movement operations.

4. Static sampling

Static signature Contract
NLRoot.shuffle(arr) Fisher-Yates shuffle in place; returns the same array. Random source is NLRoot.random.
NLRoot.n_of(size, elements) Shuffled shallow array sample of at most size positions, without replacement; input unchanged. Nonnegative integer size required (RangeError); array required (TypeError).
NLRoot.one_of(elements) Random array element, or undefined for empty array. Non-array throws TypeError. No input mutation.

Sampling positions is not deduplication: repeated values/object references can appear more than once in n_of results. A sample size above length returns a shuffled copy of all positions. Size zero returns []; implementation still shuffles a copy, so it can consume random draws. For Sets or population iterators, first make an array.

const candidates = [{id: 1}, {id: 2}, {id: 3}];
const chosen = NLRoot.one_of(candidates);
const pair = NLRoot.n_of(2, candidates);

NLRoot overrides APIRoot.shuffle. Both mutate, but APIRoot.shuffle returns undefined, not the array. Static declaration/return behavior depends on which class you call.

5. Static summaries and text

Static signature Result / restrictions
NLRoot.sum(func, l) l.map(func).reduce(sum, 0); normally a numeric sum, zero for empty array. Array map supplies value/index/array callback arguments. Does not accept a Set merely because it is iterable.
NLRoot.mean(vals) Arithmetic mean via reduce and length. Empty input gives NaN. No numeric validation or filtering of missing values.
NLRoot.meanPMStd(vals) [mean, mean + populationSD, mean - populationSD], in that order. Divides variance by population length, not length minus one. Empty gives three NaNs.
NLRoot.unquotify(s) Remove one pair of matching outer double quotes; otherwise retain string. No trimming, escape parsing, or single-quote handling. Pass a string.
NLRoot.parse(s) Array of whitespace-separated string tokens; double-quoted groups retained together with outer quotes removed. Empty/whitespace input gives []. Non-string throws TypeError; malformed quoting throws SyntaxError.

parse is not JSON, CSV, JavaScript, or NetLogo source parsing. Double quotes must begin a token and end before whitespace/end. Empty quoted tokens work. Single quotes and backslashes are literal; no escape processing. See string examples.

6. Instance collection adapters

Argument order is part of each contract, not interchangeable.

Instance signature Current behavior
map(elts, mapper) Returns elts.map(mapper); ordinary arrays work, Sets do not.
forEach(elts, eat) Calls elts.forEach(eat), returns undefined. Arrays and Sets work, but callback argument shapes are those of the underlying collection.
count(pred, l) Returns l.filter(pred).length. Intended for arrays; not a general iterable count.
any(fn, elements) Iterates elements.values(), returns true on first truthy fn(value), false when empty/no match. Arrays/Sets work.
filter(elts, pred) Legacy dispatch, described below. Prefer array.filter rather than assuming a uniform overload.

filter overload caveats

For a predictable model rule:

const patches = this.main.patches.toList();
const marked = patches.filter(patch => patch.color === 1);
const colors = this.map(marked, patch => patch.color);
const anyMarked = this.any(patch => patch.color === 1, patches);
const count = this.count(patch => patch.color === 1, patches);

This method-body fragment works after patch creation, with Main or a patch/ turtle as this. It reads state; it does not step, shift, activate, or publish.

7. Instance extrema and selection

Use ordinary finite scores. Helpers do not skip NaN or validate score types. Collections below must offer values() yielding elements (arrays/Sets work).

Instance signature Result / tie and empty policy
min_one_of(fn, elements) Element with least fn(value), with randomized replacement on ties; null if no selectable candidate.
max_one_of(fn, elements) Element with greatest fn(value), with randomized replacement on ties; null if no selectable candidate.
min_one_of_value(fn, elements) Least scalar score; Number.MAX_VALUE for empty/no lower score.
max_one_of_value(fn, elements) Legacy tuple callback: computes fn.apply(this, element), returns greatest score; -Number.MAX_VALUE for empty/no larger score. Not symmetric with minimum.
best_of(objs, fun, pred, best) Advanced selection. Starts answer as first element, replaces it when pred(fun(element), best) is truthy, then stores that score as best. Returns element, or null if empty.
max_of(objs, fun) best_of with strict greater-than and initial -Number.MAX_VALUE; returns element, first tie retained, null if empty.
min_of(objs, fun) best_of with strict less-than and initial Number.MAX_VALUE; returns element, first tie retained, null if empty.

Randomized tie decisions do not promise uniform sampling among all tied candidates. Finite sentinels also have edge cases: min_one_of may fail to select positive Infinity, and max_one_of negative Infinity. best_of/min_of/ max_of initially retain the first element even if no score beats the sentinel. Decide an explicit empty/invalid-score policy instead of interpreting a finite sentinel as a measured value.

max_one_of_value expects array-like tuple elements, not ordinary patch objects. For example:

const records = [{id: "a", score: 2}, {id: "b", score: 5}];
const winner = this.max_of(records, record => record.score);
const minimum = this.min_one_of_value(record => record.score, records);
const tupleMaximum = this.max_one_of_value((x, y) => x + y, [[1, 2], [3, 4]]);

winner is the second record, minimum 2, tupleMaximum 7. For scalar maximum scores prefer an explicit map/reduce with your chosen empty policy, rather than changing callback shape accidentally.

8. Inherited APIRoot constants and geometry

All members in this section are static, except getHistory. They are declared on APIRoot and inherited by NLRoot and its subclasses.

Static member Contract
PI2, PI Two pi and pi.
Pi4, Pi2, Pi34, Pi Pi/4, pi/2, 3pi/4, pi; capitalization matters.
degToRad(x), radToDeg(x) Linear conversions without heading normalization.
distance(x, y, z, w) Four-number Euclidean distance between (x,y) and (z,w); no boundary/finite validation.
distance(a, b) Raw Euclidean distance between finite coordinate objects supporting x/y or col/row (also callable x/y). Malformed coordinates throw TypeError. No wrapped/hex scaling.
normalize(theta) Null for null/undefined input; otherwise normalize finite heading to (-pi, pi]. No finite validation; NaN/positive Infinity yield NaN, negative Infinity can loop forever. Supply finite numbers.

Do not confuse NLRoot.degToRad (linear conversion) with Turtle.toRadians (normalized heading). Use Main's radius helpers for wrapped/hex spatial selection rather than treating raw distance as topology aware.

getHistory() is an inherited instance no-op returning undefined. It is a runtime extension point, not automatic collection of every show call. Main's dispatcher requests it; a custom history implementation must supply the expected map-like result. Ordinary guide models need not override it.

9. Inherited APIRoot random/distribution helpers

These are static operations with no world/reset requirement. They do not rewind when a model resets. Use valid parameter ranges even where code does not enforce them.

Static signature Contract / caveat
random(x, y) Intended unit/high/low-high uniform draw; x uses x
irandom(x, y) Floors one-bound or two-bound draw using a separate module generator. Second bound truth-tested; pass positive high or ordered bounds with nonzero high.
normal(m, s) Box-Muller draw with mean m, standard deviation s; uses random. No defaults/range validation.
bernoulli(p), flip(p) 1 if random() < p, otherwise 0, not Boolean. Intended probability range [0,1].
poisson(lambda) Positive-rate Poisson-style count; loop accumulates negative logs. No finite/range validation. At zero/negative rate returns zero; nonfinite rate is not a supported input.
binomial(n, p) Floors/coerces n and coerces p. Invalid/nonpositive n or p gives zero; p >= 1 gives floored n. Exact Bernoulli sum through n=100000; above that uses sparse Poisson or normal approximation and clamps count.
choose(...vals) One argument n → index in [0,n) for positive integer n. Multiple positive weights → category index by normalized weights. No array overload or input validation; invalid totals can yield the number of supplied weights as a fall-through index.
select(scale, ...probs) Scale zero chooses a uniform supplied-position index. Otherwise subtract weights from scale * random(); returns index or probs.length on leftover mass. Does not normalize weights for you.
multinomial(N, ...probs) Also accepts one array of probabilities. Applies check, counts floor(N) trials, includes a final leftover category. Returns length probs.length + 1. Fractional N rescales realized counts; floor(N) zero returns all zeros. Not a universally validated exact integer-count API.
check(probs) Returns a new array truncating each entry to at most remaining mass. Does not reject negatives/NaN or normalize arbitrary weights to sum one. Legacy probability preprocessing, not general validation.
shuffle(array) APIRoot version mutates array and returns undefined; hidden by NLRoot's returning-array override when called on NLRoot.

For a general ordered real interval use low + (high - low) * NLRoot.random(). There is no exposed common seed/replay contract: random uses Math.random while irandom uses the module generator. Prefer deterministic rules for exact checks. See modeling with random draws.

10. Verification and scope

The guide tests inventory every NLRoot prototype/static declaration and every APIRoot declaration. They execute the reference's static, collection, and selection examples, test base reset/context, path sampling limitations, extrema tie/empty policies, and inherited conversions/ selection contracts. The utility tests also exercise sampling input validation and string-tokenization edge cases.

Inventory coverage is not certification of every statistical distribution, unsupported input, host iterator API, or inherited legacy branch. No runtime behavior is changed by this reference.