aboutsummaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
Diffstat (limited to 'doc')
-rw-r--r--doc/README.md3
-rw-r--r--doc/glossary.md16
-rw-r--r--doc/ops.md33
-rw-r--r--doc/types.md6
4 files changed, 48 insertions, 10 deletions
diff --git a/doc/README.md b/doc/README.md
index 9a0470df..c9844b7c 100644
--- a/doc/README.md
+++ b/doc/README.md
@@ -27,9 +27,10 @@ Concepts:
- [Array indices](indices.md)
- [Fill elements](fill.md)
- [The leading axis model](leading.md)
+- [Functions and modifiers](ops.md)
- [Tacit programming](tacit.md)
- [Function trains](train.md)
-- [Blocks](block.md) (including function and modifier definition)
+- [Blocks](block.md)
- [Lexical scoping](lexical.md)
- [Functional programming](functional.md)
- [Control flow](control.md)
diff --git a/doc/glossary.md b/doc/glossary.md
index 50f5998f..89999380 100644
--- a/doc/glossary.md
+++ b/doc/glossary.md
@@ -13,16 +13,16 @@ The possible types are:
* [**Number**](types.md#numbers): Like some caveman was counting but then forty thousand years of math happened to it.
* [**Character**](types.md#characters): A Unicode code point.
* [**Array**](types.md#arrays): A multidimensional collection of values.
-* [**Function**](types.md#functions): An operation that is called on one or two arguments.
-* [**1-modifier**](types.md#modifiers): An operation that is called on one operand.
-* [**2-modifier**](types.md#modifiers): An operation that is called on two operands.
+* [**Function**](ops.md#functions): An operation that is called on one or two arguments.
+* [**1-modifier**](ops.md#modifiers): An operation that is called on one operand.
+* [**2-modifier**](ops.md#modifiers): An operation that is called on two operands.
* [**Namespace**](namespace.md): A container for variables, some of which are exposed as fields.
A few terms refer to multiple types collectively:
* [**Atom**](based.md#starting-from-atoms): A value that's not an array.
-* [**Modifier**](types.md#modifiers): A 1-modifier or 2-modifier.
+* [**Modifier**](ops.md#modifiers): A 1-modifier or 2-modifier.
* [**Data type**](types.md#data-types): Number, character, or array.
-* [**Operation type**](types.md#operation-types): Function, 1-modifier, or 2-modifier.
+* [**Operation type**](ops.md): Function, 1-modifier, or 2-modifier.
* [**Mutable type**](lexical.md#mutation): Operation or namespace.
BQN uses standard terminology for particular sets of numbers, with natural numbers starting at 0.
@@ -72,7 +72,7 @@ The possible roles are:
## Operations
-* **Operation**: A value that is called on inputs to perform computation and return a result or cause an error.
+* [**Operation**](ops.md): A value that is called on inputs to perform computation and return a result or cause an error.
* **Call**: Submit inputs to an operation and receive any result.
* **Input**: A value given (*passed*) to an operation when it's called.
* **Result**: A value returned from an operation when called.
@@ -83,8 +83,8 @@ The possible roles are:
* **Monadic**: Called with one argument, either always (a monadic function) or in a particular instance (a monadic call).
* **Dyadic**: Called with two arguments, always or in a particular instance.
-* **Compound function**: A derived function or train.
-* **Derived function**: A function produced by binding operands to a deferred modifier; doing so does not cause any computation.
+* [**Compound function**](ops.md#functions): A derived function or train.
+* [**Derived function**](ops.md#functions): A function produced by binding operands to a deferred modifier; doing so does not cause any computation.
* [**Train**](train.md): A function composed of two or more functions.
* [**Identity value**](fold.md#identity-values): An inferred property of a function: the result of a reduction with this function on an empty array.
diff --git a/doc/ops.md b/doc/ops.md
new file mode 100644
index 00000000..56da5fc2
--- /dev/null
+++ b/doc/ops.md
@@ -0,0 +1,33 @@
+*View this file with results and syntax highlighting [here](https://mlochbaum.github.io/BQN/doc/ops.html).*
+
+# Functions and modifiers
+
+BQN's three operation [types](types.md) are the function, 1-modifier, and 2-modifier.
+
+In general, an operation is *called* by passing in *inputs*, and returns a *result* value. The inputs and result can have any type. Since BQN isn't a pure [functional](functional.md) language, the operation might also have side effects: it can modify the values of variables, perform program input or output, or call other operations with their own side effects.
+
+This page deals with types, not syntax. Expressions with a function or modifier [role](expression.md#syntactic-role) don't have to yield a value of that type when run. However, primitives and blocks do have roles that match their types.
+
+## Functions
+
+A function has one or two inputs called *arguments*. The general layout is `𝕨 Fn 𝕩`, with an optional left argument `𝕨` and a non-optional right argument `𝕩`. The number of arguments is called its *valence*, and functions are naturally *ambivalent*, allowing one or two arguments. When called with one argument—`𝕩` only—it's *monadic*, and when called with two it's *dyadic*. More arguments, or a variable number, should be handled by using a list argument; [destructuring headers](block.md#destructuring) can be useful in this case.
+
+Functions can be [primitives](primitive.md) or [blocks](block.md) (or system functions), but there are also two kinds of *compound* functions: *derived* functions that consist of a modifier and its operands, and [trains](train.md). [Tacit](tacit.md) programming refers to code written without blocks, so of course it uses compound functions heavily.
+
+ 3 + 4 # Primitive function
+ {𝕩+𝕩} 4 # Block function
+ +˜ 4 # Derived function
+ (⊢+÷) 4 # Train
+
+Compound functions have some differences with blocks, most importantly that blocks can express [mutation](lexical.md#mutation) while a compound function can't have side effects unless one of its constituent functions or modifiers does. More subtly, compound functions [match](match.md#atomic-equality) when they have the same composition (much like lists) while blocks must be the same instance to match. A function's composition can also be inspected directly with `•Decompose` ([spec](../spec/system.md#operation-properties)).
+
+While normally functions are just called, some primitives might try to infer properties of functions, which necessarily involves inspecting their definitions. The [identity value](fold.md#identity-values) used by reductions and the results of [Undo](undo.md) and [Under](under.md) rely on inference.
+
+## Modifiers
+
+There are two modifier types, separated for syntax reasons: 1-modifiers follow the layout `𝔽 _mod` and 2-modifiers follow `𝔽 _mod_ 𝔾`. The values `𝔽` and `𝔾` are called *operands*. There aren't any compound modifiers, so modifiers are always [primitives](primitive.md) or system-provided, or [blocks](block.md). A primitive is a 1-modifier when it's written as a superscript like `˘` or `˝`, and a 2-modifier when it has an unbroken circle like `∘` or `⍟` (not `⌽` or `⍉`).
+
+ +⎉3 # Primitive 2-modifier (deferred)
+ 2{-𝕗} # Block 1-modifier
+
+In general, a modifier call works just like a function: inputs out, result in. Syntactically, a modifier call expression has a function role, but that doesn't affect execution. However, one kind of modifier is more strict: a *deferred* modifier doesn't evaluate anything when called, but returns a derived function. When the derived function is finally called, the modifier's definition determines what happens. Primitive modifiers are always deferred, and a block modifier is deferred if it includes arguments, either in the header or with `𝕨`, `𝕩`, or `𝕤` in the body.
diff --git a/doc/types.md b/doc/types.md
index 288fd5d0..af6eaa65 100644
--- a/doc/types.md
+++ b/doc/types.md
@@ -79,6 +79,8 @@ Different elements of an array should not influence each other. While some APLs
## Operation types
+*Full documentation [here](ops.md).*
+
An operation is either a function or modifier, and can be applied to *inputs*—which are called *arguments* for functions and *operands* for modifiers—to obtain a result. During this application an operation might also change variables within its scope and call other operations, or cause an error, in which case it doesn't return a result. There is one type of call for each of the three operation types, and an operation will give an error if it is called in a way that doesn't match its type.
In BQN syntax the result of a function has a subject role and the result of a modifier has a function role. However, the result can be any value at all: roles take place at the syntactic level, which has no bearing on types and values in the semantic level. This distinction is discussed further in [Mixing roles](context.md#mixing-roles).
@@ -93,4 +95,6 @@ A 1-modifier is called with one operand, while a 2-modifier is called with two.
## Namespaces
-Functions and modifiers have internal scopes which they can manipulate (by defining and modifying variables) to save and update information. Namespaces let the programmer to expose this state more directly: identifiers in a namespace may be exported, allowing code outside the namespace to read their values. They are described in detail [here](namespace.md).
+*Full documentation [here](namespace.md).*
+
+Functions and modifiers have internal scopes which they can manipulate (by defining and modifying variables) to save and update information. Namespaces let the programmer to expose this state more directly: identifiers in a namespace may be exported, allowing code outside the namespace to read their values.