diff options
Diffstat (limited to 'doc')
| -rw-r--r-- | doc/README.md | 3 | ||||
| -rw-r--r-- | doc/glossary.md | 16 | ||||
| -rw-r--r-- | doc/ops.md | 33 | ||||
| -rw-r--r-- | doc/types.md | 6 |
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. |
