From 7733b104e3eff841dcd1ac3f67731eb80746e427 Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Wed, 8 Jun 2022 22:25:20 -0400 Subject: Add page on function and modifier types --- docs/doc/glossary.html | 16 ++++++++-------- docs/doc/index.html | 3 ++- docs/doc/ops.html | 32 ++++++++++++++++++++++++++++++++ docs/doc/types.html | 4 +++- 4 files changed, 45 insertions(+), 10 deletions(-) create mode 100644 docs/doc/ops.html (limited to 'docs') diff --git a/docs/doc/glossary.html b/docs/doc/glossary.html index 878a6738..720c12cc 100644 --- a/docs/doc/glossary.html +++ b/docs/doc/glossary.html @@ -16,17 +16,17 @@
  • Number: Like some caveman was counting but then forty thousand years of math happened to it.
  • Character: A Unicode code point.
  • Array: A multidimensional collection of values.
  • -
  • Function: An operation that is called on one or two arguments.
  • -
  • 1-modifier: An operation that is called on one operand.
  • -
  • 2-modifier: An operation that is called on two operands.
  • +
  • Function: An operation that is called on one or two arguments.
  • +
  • 1-modifier: An operation that is called on one operand.
  • +
  • 2-modifier: An operation that is called on two operands.
  • Namespace: A container for variables, some of which are exposed as fields.
  • A few terms refer to multiple types collectively:

    BQN uses standard terminology for particular sets of numbers, with natural numbers starting at 0.

    @@ -81,7 +81,7 @@

    Operations

    diff --git a/docs/doc/index.html b/docs/doc/index.html index 9038f45b..c86ab0d3 100644 --- a/docs/doc/index.html +++ b/docs/doc/index.html @@ -32,9 +32,10 @@
  • Array indices
  • Fill elements
  • The leading axis model
  • +
  • Functions and modifiers
  • Tacit programming
  • Function trains
  • -
  • Blocks (including function and modifier definition)
  • +
  • Blocks
  • Lexical scoping
  • Functional programming
  • Control flow
  • diff --git a/docs/doc/ops.html b/docs/doc/ops.html new file mode 100644 index 00000000..617aab63 --- /dev/null +++ b/docs/doc/ops.html @@ -0,0 +1,32 @@ + + + + BQN: Functions and modifiers + + +

    Functions and modifiers

    +

    BQN's three operation types 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 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 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 can be useful in this case.

    +

    Functions can be primitives or blocks (or system functions), but there are also two kinds of compound functions: derived functions that consist of a modifier and its operands, and trains. Tacit programming refers to code written without blocks, so of course it uses compound functions heavily.

    +↗️
        3 + 4     # Primitive function
    +7
    +    {𝕩+𝕩} 4   # Block function
    +8
    +    +˜ 4      # Derived function
    +8
    +    (⊢+÷) 4   # Train
    +4.25
    +
    +

    Compound functions have some differences with blocks, most importantly that blocks can express mutation while a compound function can't have side effects unless one of its constituent functions or modifiers does. More subtly, compound functions match 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).

    +

    While normally functions are just called, some primitives might try to infer properties of functions, which necessarily involves inspecting their definitions. The identity value used by reductions and the results of Undo and Under 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 or system-provided, or blocks. 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)
    ++⎉3
    +    2{-𝕗}  # Block 1-modifier
    +¯2
    +
    +

    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/docs/doc/types.html b/docs/doc/types.html index 20ab9578..c27a9400 100644 --- a/docs/doc/types.html +++ b/docs/doc/types.html @@ -63,6 +63,7 @@

    Arrays are value types (or immutable), so that there is no way to "change" the shape or elements of an array. An array with different properties is a different array. As a consequence, arrays are an inductive type, and it's not possible for an array to contain itself, or contain an array that contains itself, and so on. However, it is possible for an array to contain a function or other operation that has access to the array through a variable, and in this sense an array can "know about" itself.

    Different elements of an array should not influence each other. While some APLs force numbers placed in the same array to a common representation, which may have different precision properties, BQN values must not change behavior when placed in an array. However, this doesn't preclude changing the storage type of an array for better performance: for example, in a BQN implementation using 64-bit floats, an array whose elements are all integers that fit in 32-bit int range might be represented as an array of 32-bit ints.

    Operation types

    +

    Full documentation here.

    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.

    Functions

    @@ -70,4 +71,5 @@

    Modifiers

    A 1-modifier is called with one operand, while a 2-modifier is called with two. In contrast to functions, these are distinct types, and it is impossible to have a value that can be called with either one or two operands. Also in contrast to functions, data values cannot be called as modifiers: they will cause an error if called this way.

    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.

    +

    Full documentation here.

    +

    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.

    -- cgit v1.2.3