# Language principles


<!-- WARNING: THIS FILE WAS AUTOGENERATED! DO NOT EDIT! -->

BasedPL (BPL) keeps APL’s glyphs and its right-to-left evaluation. It
changes the notation where APL’s rules make code harder to read or to
write. Most of the changes follow from one decision, to write lists in
brackets. BasedPL stands for Based-array Programming Language, after the
array model it takes from BQN.

Many of the notation choices answer problems that Marshall Lochbaum,
BQN’s author, lists in his notes on [BQN’s
problems](https://mlochbaum.github.io/BQN/commentary/problems.html) and
on [its first five
years](https://mlochbaum.github.io/BQN/commentary/fiveyears.html).
[Syntax](syntax.qmd) and [Evaluation](evaluation.qmd) state the rules
without the reasons. [BPL, APL and BQN side by side](comparison.qmd)
shows the choices on real code.

## Lists are written in brackets

In APL, arrays written side by side form a list. `1 2 3`, `a b c` and
`(x+1) y` are all vectors. This is called stranding. It’s short, but it
gives a space a different job in different places. Between arrays, a
space separates the items of a list. Between functions it means nothing:
`+/÷≢` and `+ / ÷ ≢` are the same train. Between an operator and an
array, it can do either.

That last case causes real trouble. An operator takes the single item to
its right as its operand, after stranding has already joined that item
to its neighbours. In APL, the operand in `f⍤1 M` is `1 M`. You have to
write `f⍤1⊢M`, where `⊢` is there only to break the strand. BQN’s
documentation gives the example `a +˝∘×⎉1‿∞ b`, a matrix product. No
rule decides well which of `1`, `∞` and `b` should strand together. BQN
marks its strands with `‿` instead.

In BPL, lists are written in brackets, `[a b c]`, as in Python and
JavaScript. Lochbaum notes that new BQN programmers “are always
expecting `[]` to be the list notation, and it’d let you copy-paste JSON
too”. A list of literals can still leave its brackets out, as in `1 2 3`
and `"no" "yes"`. Inside brackets, names and literals mix freely:

``` bpl
x←5
[1 x 3]
```

    1 5 3

Outside brackets, arrays side by side form a list too, whatever the
names hold. `(+/x) 3` is a two-item list whether `x` is a vector or a
matrix. Each run, a stretch of code with no spaces in it, is one item of
the list. In `a b+1` the items are `a` and `b+1`. A bracket list is one
run like any other:

``` bpl
a←1 ⋄ b←2
a b+1
[1 2] 3
```

    1 3

    [[1 2] 3]

A bracket list is a vector, however many items it has. `[1]` is a
one-item vector, not a number:

``` bpl
⍴[1]
```

    [1]ₓ

Parentheses only group, as they do in maths. `(1 2)` is the same value
as `1 2`. To make a scalar, enclose with `⊂`, as in BQN. `⊂[1 2]` is a
scalar holding a vector, with no axes:

``` bpl
⍴⊂[1 2]
```

    ⍬ₓ

A function after `⊂` makes a train instead, as in `⊂+`. The scalar
holding `+` is written `+ᵘ`.

Array notation extends brackets to higher ranks, as Dyalog’s does. Rows
separated by `⋄`, or written on separate lines, become major cells:

``` bpl
[1 2
 3 4]
```

    1 2
    3 4

The result has one more axis than each row. Rows that are numbers have
no axes, and give a vector. Rows that are one-item vectors give a
column:

``` bpl
[1 ⋄ 2]
[[1] ⋄ [2]]
```

    1 2

    1
    2

`[a ⋄ b]` is the Mix of `[a b]` when `a` and `b` have the same shape.

In parentheses, rows form a new level of nesting instead of a new axis.
Each row is one item of a vector, read as if written in brackets. The
rows can have different lengths:

``` bpl
≢¨(4 ⋄ 4 5 ⋄ 4 5 6)
```

    [1 2 3]ₓ

A row holding one string is still a vector of one item. `("ab" ⋄ "cd")`
holds two one-item vectors, while `["ab" "cd"]` is the vector of two
strings:

``` bpl
≢¨("ab" ⋄ "cd")
≢¨["ab" "cd"]
```

    [1 1]ₓ

    [2 2]ₓ

Items in brackets can be functions. `[+/ ÷ ≢]` holds three functions.
Without the spaces, `[+/÷≢]` holds one, the mean:

``` bpl
≢[+/ ÷ ≢]
≢[+/÷≢]
```

    3ₓ

    1ₓ

Writing a function expression in brackets is one way to make it a value.
In BQN this takes `⊑⟨Expr⟩` or a name, a problem Lochbaum lists as
“Converting a function expression to a subject is tricky”. The other way
is `fᵘ`, a scalar holding the function `f`.

Items in a list are evaluated left to right, as statements are. BQN
chose the same order for its lists and strands. Here each item prints as
it’s evaluated, before the list itself displays:

``` bpl
[⎕←1 ⎕←2]
```

    1
    2

    1 2

## Spaces group

Outside brackets, literals separated by spaces form a strand, as in
`1 2 3`. Every other space separates runs. A run is a sequence of tokens
with no spaces between them. Each run is evaluated first, as if it were
in parentheses:

``` bpl
c←3 ⋄ d←4
a+b×c+d
a+b × c+d
```

    15

    21

Runs also fix the operand problem. Because a run ends at a space,
`+/⍤1 m` applies `+/⍤1` to `m` with no `⊢` needed. A run ending in a
dyadic operator takes the next run as its operand, as if no space came
between them. A literal argument after a space still joins the operand’s
strand, as in `f⍤1 2 3`, whose operand is `1 2 3`. Write such an
argument in brackets or parentheses. All three of these sum each row:

``` bpl
m←2 3⍴⍳6
+/⍤1 m
+/⍤ 1 m
+/⍤1(2 3⍴⍳6)
```

    3 12

    3 12

    3 12

A space after an operator also lets a longer function be its operand
without parentheses. `⌊⌾ 10×` rounds down to one decimal place, with
`10×` as the operand of `⌾`:

``` bpl
⌊⌾ 10× 1.24 3.57
```

    1.2 3.5

Lochbaum describes the problem that runs solve, under “Modifiers look
looser than trains without spaces”. In BQN’s `⋆∘-×˜`, the `-` looks
closer to `⋆`, but it binds to `×˜`. Writing `⋆∘- ×˜` shows the
structure. He calls it “unfortunate that this is something the writer
must do rather than something the notation encourages”. In BPL the space
is part of the notation.

Under “Long trains are hard for humans to parse”, he notes that readers
lose track of a train’s structure after four to eight parts. Runs let
spaces show that structure. `⌊ +/÷≢` is the floor of the mean:

``` bpl
⌊ +/÷≢ 1 2 4
```

    2ₓ

Code that is fully spaced, or not spaced at all, groups as in APL. Only
mixed spacing changes the grouping. A reader used to APL reads `1+2 × 3`
as 7, but here it’s 9:

``` bpl
1+2 × 3
```

    9

A tool that normalises spaces would change a program’s meaning. Other
languages give spaces meaning too. K reads `a -1` differently from
`a - 1`. Nim tried an experimental mode in which the spaces around an
operator changed its precedence, and removed it in version 0.20.

## A run that ends in a function is a train

A run that ends in a function has no argument yet. It’s a function,
built as an APL train with one addition. A subject directly before a
function binds to it, as `2` does in `2×`. Here `32+1.8×` converts
Celsius to Fahrenheit:

``` bpl
f←32+1.8×
f100
```

    212

The rest follows APL’s train rules, including Dyalog’s fork with a
subject on the left, `0.5×⊢+÷`. Binding covers the common case of fixing
a left argument, without `↣`. K has the same idea, called projection, in
which `2*` is a function.

`+/÷≢ nums` and `+/÷≢nums` differ only in the space before `nums`. The
first applies the train `+/÷≢`, the mean, to `nums`. The second is one
run ending in a subject, the expression `+/(÷(≢nums))`:

``` bpl
nums←1 2 3 6
+/÷≢ nums
+/÷≢nums
```

    3

    1ᵣ4

If both spellings meant the same, the space would mean nothing. In
everyday arithmetic the two readings agree. When the functions have
arrays between them, as in `32+1.8×`, the train gives the same result as
the expression. The readings differ only where a fork gets a function as
its left part, as in `0.5×⊢+÷`. APL has the same split, with nothing in
the source to mark it. Removing the argument from APL’s `0.5×⊢+÷⍵` turns
it into a fork with a different meaning. In BPL the space shows which
reading you get.

## Selection is a function

Index, `⌷`, selects. `I⌷Y` takes one item of `I` for each leading axis
of `Y`. In K, `v 1` selects, because K treats a list as a function of
its positions. In BPL `v 1` is a strand, because subjects and functions
stay apart. One literal position can be written more briefly as a
[subscript](scripts.ipynb#subscripts), as in `v₁`:

``` bpl
v←10 20 30 40
1⌷v
v₁
```

    20

    20

Selecting with a number drops that axis from the result. Selecting with
an array of positions puts the array’s shape in place of the axis.
`[⊂1]⌷v` gives a scalar holding the item, `[[1]]⌷v` a one-item vector,
and `[[2 0]]⌷v` two items:

``` bpl
[⊂1]⌷v
[[1]]⌷v
[[2 0]]⌷v
```

    ⊂20

    [20]

    30 10

Dyalog has the same rule, but its `v[1]` looks like a one-item list and
gives a scalar. A one-item result needs `v[,1]`.

Because Index takes its positions on the left, its right argument can be
any expression. With `sales` [keyed](keyed.ipynb) by city and month,
`"NY"⌷+/sales` selects New York’s total with no parentheses:

``` bpl
sales←["NY" "LA";"jan" "feb"]:[1 2 ⋄ 3 4]
sales
"NY"⌷+/sales
```

       jan feb
    NY   1   2
    LA   3   4

    3

## Counting from 0

Positions and axes count from 0, as in BQN, J, K, Python and NumPy.
Negative positions count from the end.

- A Boolean is a valid position, as in `c⌷"no" "yes"`. With 1-origin,
  the position would be `1+c`.
- Positions run from `¯n` to `n-1` with no gap. With 1-origin, position
  0 is an error that sits between the first item and the last.
- `n|i` wraps a position round a vector of length `n`. `⌊i÷n` and `n|i`
  give the row and column of a flat position.
- The Python API returns positions from functions such as `grade` and
  `where`. Those positions must agree with Python and NumPy, which count
  from 0.

Here the comparison is the position:

``` bpl
(3>2)⌷"no" "yes"
```

    yes

Counting idioms pay for this with a `1+`, as in `1+⍳10` for the numbers
1 to 10. Code from APL books and libraries assumes 1-origin and needs
converting.

Two rules follow J and BQN where 0-origin left a choice. A negative
length counts down, as J’s `i._3` does:

``` bpl
⍳¯3
```

    2 1 0

Interval Index counts the boundaries at or below each value, as BQN’s
does. Below the first boundary the count is 0. A position there would be
`¯1`, which selects the last item:

``` bpl
1 3 5⍸0 3 9
```

    [0 2 3]ₓ

## Based arrays

BPL uses BQN’s [based array
model](https://mlochbaum.github.io/BQN/doc/based.html). Numbers,
characters and functions are atoms. An array is a rectangular collection
of values. Atoms are not arrays. Enclosing always adds a layer: `⊂3` is
a rank-0 array holding 3, a different value from 3. Enclosing it again
gives depth 2:

``` bpl
⊂3 ≡ 3
≡⊂⊂3
```

    $f

    2ₓ

In APL’s nested array model, enclosing 3 gives 3 again. Under the based
model, every value has one representation, whether you pass it to a
function, return it, or store it in an array. Functions are atoms too.
`[+/ ÷ ≢]` is a list of three of them. Lochbaum’s page on the model
gives the longer argument.

## Functions act on major cells

BPL follows BQN’s leading-axis model. A function that works on a whole
array acts on its major cells, the cells along its first axis. The
last-axis glyphs `⌽ / \ ,` are the leading-axis functions applied at
rank 1. Their first-axis twins `⊖ ⌿ ⍀ ⍪` are the leading-axis functions
themselves. Every function therefore treats a matrix by the same rule.

Search follows that rule. `⍳ ∊ ~ ∪ ∩` compare the major cells of the
searched argument, which for a matrix are its rows. Here `~` removes
every row that is `1 2`, leaving a one-row matrix:

``` bpl
rows←[1 2
      3 4
      1 2]
rows~[1 2 ⋄ 5 6]
⍴rows~[1 2 ⋄ 5 6]
```

    3 4

    [1 2]ₓ

The other argument’s cells have the same rank. A unit has no major cells
to search. To remove the spaces from a string, give `~` the string
`" "`. Giving it the character `' '`, a unit, is a `RANK` error:

``` bpl
"a b c"~" "
```

    abc

Partition splits along the first axis too, into blocks of major cells.
Here new blocks start at rows 0 and 2:

``` bpl
1 0 1⊂rows
```

    [[1 2 ⋄ 3 4] [1 2 ⋄]]

`⊂⍤1` partitions each row instead, and `⊂⍠1` splits a matrix into blocks
of columns.

Encode and Decode put digits on the last axis, as J’s `#:` and `#.` do.
Encode turns each number of a vector into a row of digits. Decode turns
the rows back into numbers:

``` bpl
d←2 2 2⊤5 6
d
2⊥d
```

    1 0 1
    1 1 0

    5 6

At rank 0, the function gets each atom as itself and each array item
enclosed in a scalar. BQN’s `⎉0` encloses atoms as well. The depth of
each 0-cell shows the difference:

``` bpl
{≡⍵}⍤0 [1 [2 3]]
```

    [0 2]ₓ

As a result, `⊢⍤0` returns its argument unchanged, even when the
argument is nested. A function under `⍤0` sees numbers as literals and
selection give them. Each, `¨`, gives the function the items themselves.
