add more notes to README
MODIFY
README.md
README.md
# Nat
-At a basic level, `Nat` ensures that a number is within the natural, safe integers (0, 1, 2... to 2 \*\* 53 - 1). If not, `Nat` throws a RangeError.
+`Nat(value)` returns its argument if it represents a non-negative integer (i.e. a "natural number") that can be accurately represented in a Javascript `Number`, specifically (0, 1, 2... to 2 \*\* 53 - 1). Otherwise it throws a `RangeError` exception. This makes it easy to use on incoming arguments, or as an assertion on generated values.
+
+Traditional Javascript has a single `Number` type, which is defined to contain a 64-bit IEEE-754 floating point value. This can safely represent a wide range of integers, but if they get too large, `Number` will lose precision: `2**53 + 1` will give you the same value as `2**53 + 2`. In situations where you care about accuracy rather than range, this would be a problem.
You can think of `Nat()` as a type enforcement.
## How to use
-`Nat()` can be used to enforce desired properties on account balances.
+`Nat()` can be used to enforce desired properties on account balances, where precision is important.
-For instance, in a deposit scenario, you would want to validate the amount to be deposited before proceeding:
+For instance, in a deposit scenario, you would want to defend against someone "depositing" a negative value. Use `Nat` to validate the amount to be deposited before proceeding:
```
deposit: function(amount) {
@@ -17,13 +19,13 @@ deposit: function(amount) {
}
```
-We also want to use `Nat()` before using values internally:
+We also want to use `Nat()` before using values internally, as a precondition check:
```
Nat(ledger.get(purse));
```
-Any expressions dealing with monetary amounts should protected with `Nat()`:
+Any addition or subtraction expressions dealing with monetary amounts should protected with `Nat()` to guard against overflow/underflow errors. Without this check, the two balances might both be safe, but their sum might be too large to represent accurately, causing precision errors in subsequent computation:
```
Nat(myOldBal + amount);
@@ -32,16 +34,15 @@ const srcNewBal = Nat(srcOldBal - amount);
## Non-monetary usage
-Deadlines or block numbers should be wrapped with `Nat()` before using:
+Array indexes can be wrapped with `Nat()`, to guard against the surprising string coersion of non-integral index values:
```
-deadline = Nat(deadline);
-```
-
-Indexes can be wrapped with `Nat()`:
-
-```
-const index = Nat(data.index);
+const a = [2,4,6]
+function add(index, value) {
+ a[Nat[index]] = value;
+}
+add(3, 8); // works
+add(2.5, 7); // throws rather than add a key named "2.5"
```
Nat can be used even in cases where it is not strictly necessary, for extra protection against human error.
@@ -56,6 +57,8 @@ By excluding 2^53, we have the nice invariant that if
are all true, then `(a+b)` is an accurate sum of a and b.
+Future versions of `Nat` will use Javascript's upcoming (`BigInt` standard)[https://tc39.github.io/proposal-bigint/], to increase the range of accurately-representable integers to be effectively unbounded.
+
## History
Nat comes from the Google Caja project, which tested whether a number was a primitive integer within the range of continguously representable non-negative integers.

add more notes to README