From e52d50ed594dd5626523ca7931315e47bde8c9d1 Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Mon, 20 Jul 2020 14:05:36 -0400 Subject: Make header id slugs match Github's --- docs/doc/context.html | 8 ++++---- docs/doc/fromDyalog.html | 2 +- docs/doc/logic.html | 4 ++-- docs/index.html | 6 +++--- docs/problems.html | 36 ++++++++++++++++++------------------ docs/running.html | 6 +++--- docs/spec/evaluate.html | 2 +- docs/spec/grammar.html | 2 +- docs/spec/literal.html | 2 +- docs/spec/token.html | 2 +- docs/spec/types.html | 2 +- 11 files changed, 36 insertions(+), 36 deletions(-) (limited to 'docs') diff --git a/docs/doc/context.html b/docs/doc/context.html index 90963840..b4c5616f 100644 --- a/docs/doc/context.html +++ b/docs/doc/context.html @@ -1,6 +1,6 @@ -

BQN's context-free grammar

+

BQN's context-free grammar

APL has a problem. To illustrate, let's look at an APL expression:

a b c d e
 
@@ -12,12 +12,12 @@
a B C _d e
 

Here, the lowercase spelling indicates that a and e are to be treated as subjects ("arrays" in APL) while the uppercase spelling of variables B and C are used as functions and _d is a 1-modifier ("monadic operator"). Like parentheses for function application, the spelling is not inherent to the variable values used, but instead indicates their grammatical role in this particular expression. A variable has no inherent spelling and can be used in any role, so the names a, A, _a, and _a_ all refer to exact same variable, but in different roles; typically we use the lowercase name to refer to the variable in isolation—all values are nouns when speaking about them in English. While we still don't know anything about what values a, b, c, and so on have, we know how they interact in the line of code above.

-

Is grammatical context really a problem?

+

Is grammatical context really a problem?

Yes, in the sense of problems with BQN. A grammar that uses context is harder for humans to read and machines to execute. A particular difficulty is that parts of an expression you don't yet understand can interfere with parts you do, making it difficult to work through an unknown codebase.

One difficulty beginners to APL will encounter is that code in APL at first appears like a string of undifferentiated symbols. For example, a tacit Unique Mask implementation ⍳⍨= consists of six largely unfamiliar characters with little to distinguish them (in fact, the one obvious bit of structure, the repeated , is misleading as it means different things in each case!). Simply placing parentheses into the expression, like (⍳⍨)=(), can be a great help to a beginner, and part of learning APL is to naturally see where the parentheses should go. The equivalent BQN expression, ˜=↕, will likely appear equally intimidating at first, but the path to learning which things apply to which is much shorter: rather than learning the entire list of APL primitives, a beginner just needs to know that superscript characters like ˜ are 1-modifiers and characters like with unbroken circles are 2-modifiers before beginning to learn the BQN grammar that will explain how to tie the various parts together.

This sounds like a distant concern to a master of APL or a computer that has no difficulty memorizing a few dozen glyphs. Quite the opposite: the same concern applies to variables whenever you begin work with an unfamiliar codebase! Many APL programmers even enforce variable name conventions to ensure they know the class of a variable. By having such a system built in, BQN keeps you from having to rely on programmers following a style guide, and also allows greater flexibility, including functional programming, as we'll see later.

Shouldn't a codebase define all the variables it uses, so we can see their class from the definition? Not always: consider that in a language with libraries, code might be imported from dependencies. Many APLs also have some dynamic features that can allow a variable to have more than one class, such as the pattern in a dfn that makes an array in the dyadic case but a function in the monadic case. Regardless, searching for a definition somewhere in the code is certainly a lot more work than knowing the class just from looking! One final difficulty is that even one unknown can delay understanding of an entire expression. Suppose in A B c, B is a function and c is an array, and both values are known to be constant. If A is known to be a function (even if its value is not yet known), its right argument B c can be evaluated ahead of time. But if A's type isn't known, it's impossible to know if this optimization is worth it, because if it is an array, B will instead be called dyadically.

-

BQN's spelling system

+

BQN's spelling system

BQN's expression grammar is a simplified version of the typical APL, removing some oddities like niladic functions and the two-glyph Outer Product operator. Every value can be used in any of four syntactic roles:

@@ -54,7 +54,7 @@

BQN's variables use another system, where the spelling indicates how the variable's value is used. A variable spelled with a lowercase first letter, like var, is a subject. Spelled with an uppercase first letter, like Var, it is a function. Underscores are placed where operands apply to indicate a 1-modifier _var or 2-modifier _var_. Other than the first letter or underscore, variables are case-insensitive.

The associations between spelling and syntactic role are considered part of BQN's token formation rules.

One rule for typing is also best considered to be a pre-parsing rule like the spelling system: the role of a brace construct {} with no header is determined by which special arguments it uses: it's a subject if there are none, but a 𝕨 or 𝕩 makes it at least a function, an 𝔽 makes it a 1- or 2-modifier, and a 𝔾 always makes it a 2-modifier.

-

BQN's grammar

+

BQN's grammar

A formal treatment is included in the spec. BQN's grammar—the ways syntactic roles interact—follows the original APL model (plus trains) closely, with allowances for new features like list notation. In order to keep BQN's syntax context-free, the syntactic role of any expression must be known from its contents, just like tokens.

Here is a table of the APL-derived modifier and function application rules:

diff --git a/docs/doc/fromDyalog.html b/docs/doc/fromDyalog.html index 70bdb134..0b9ca972 100644 --- a/docs/doc/fromDyalog.html +++ b/docs/doc/fromDyalog.html @@ -1,6 +1,6 @@ -

BQN–Dyalog APL dictionary

+

BQN–Dyalog APL dictionary

A few tables to help users of Dyalog APL (or similar) get started quickly on BQN. Here we assume ML is 1 for Dyalog.

For reading

Here are some closest equivalents in Dyalog APL for the BQN functions that don't use the same glyphs as APL. Correspondence can be approximate, and is just used as a decorator to mean "reverse some things".

diff --git a/docs/doc/logic.html b/docs/doc/logic.html index 7ac951d8..d9d8a405 100644 --- a/docs/doc/logic.html +++ b/docs/doc/logic.html @@ -1,6 +1,6 @@ -

Logic functions: And, Or, Not (also Span)

+

Logic functions: And, Or, Not (also Span)

BQN retains the APL symbols and for logical and and or, and changed APL's ~ to ¬ for not, since ~ looks too much like ˜ and ¬ is more common in mathematics today. Like J, BQN extends Not to the linear function 1-. However, it discards GCD and LCM as extensions of And and Or, and instead uses bilinear extensions: And is identical to Times (×), while Or is ׬, following De Morgan's laws (other ways of obtaining a function for Or give an equivalent result—there is only one bilinear extension).

If the arguments are probabilities of independent events, then an extended function gives the probability of the boolean function on their outcomes (for example, if A occurs with probability a and B with probability b independent of A, then A or B occurs with probability ab). These extensions have also been used in complexity theory, because they allow mathematicians to transfer a logical circuit from the discrete to the continuous domain in order to use calculus on it.

Both valences of ¬ are equivalent to the fork 1+-. The dyadic valence, called "Span", computes the number of integers in the range from 𝕩 to 𝕨, inclusive, when both arguments are integers and 𝕩𝕨 (note the reversed order, which is used for consistency with subtraction). This function has many uses, and in particular is relevant to the Windows function.

@@ -29,7 +29,7 @@ 1 1 1

As with logical And and Or, any value and 0 is 0, while any value or 1 is 1. The other boolean values give the identity elements for the two functions: 1 and any value gives that value, as does 0 or the value.

-

Why not GCD and LCM?

+

Why not GCD and LCM?

The main reason for omitting these functions is that they are complicated and, when applied to real or complex numbers, require a significant number of design decisions where there is no obvious choice (for example, whether to use comparison tolerance). On the other hand, these functions are fairly easy to implement, which allows the programmer to control the details, and also add functionality such as the extended GCD.

A secondary reason is that the GCD falls short as an extension of Or, because its identity element 0 is not total. 0x, for a real number x, is actually equal to |x and not x: for example, 0¯2 is 2 in APL. This means the identity 0x ←→ x isn't reliable in APL.

Identity elements

diff --git a/docs/index.html b/docs/index.html index fc10eaa2..85f6ac77 100644 --- a/docs/index.html +++ b/docs/index.html @@ -1,6 +1,6 @@ -

BQN: finally, an APL for your flying saucer

+

BQN: finally, an APL for your flying saucer

This repository does not yet have a working implementation. However, there are some incomplete implementations you can use, with one you can try online here. See running.md for more.

BQN is a new programming language in the APL lineage, which aims to remove inconsistent and burdensome aspects of the APL tradition and put the great ideas on a firmer footing. BQN is aimed at existing and aspiring APL-family programmers, and using it requires a solid understanding of functions and multidimensional arrays. However, because of its focus on providing simple, consistent, and powerful array operations, BQN should also be a good language for learning array programming and building stronger array intuition.

BQN maintains many of the ideas that made APL\360 revolutionary in 1966:

@@ -22,9 +22,9 @@
  • Oh, and it naturally leads to first-class functions, a feature often missed in APL.
  • The new symbols for built-in functionality allow the syntactic role of a primitive to be distinguished at a glance, and aim to be more consistent and intuitive.
  • -

    What kind of name is "BQN"?

    +

    What kind of name is "BQN"?

    It's three letters, that happen to match the capitals in "Big Questions Notation". You can pronounce it "bacon", but are advised to avoid this unless there's puns.

    -

    What does BQN look like?

    +

    What does BQN look like?

    Rather strange, most likely:

    ⊑+`122  # The 12th Fibonacci number
     
    diff --git a/docs/problems.html b/docs/problems.html index b2ea1faa..252cdb1c 100644 --- a/docs/problems.html +++ b/docs/problems.html @@ -28,9 +28,9 @@
  • 𝔽¨´<˘ Apply it between elements of an array, enclosing results to get a new array (NARS).
  • It seems that the first is the most common, but the others aren't really rare. The current list reduction also encourages patterns like +´˘2mat, which don't work on higher-rank arrays and mix the result (possibly unwanted).

    -

    Subtraction, division, and span are backwards

    +

    Subtraction, division, and span are backwards

    The left argument feels much more like the primary one in these cases (indeed, this matches the typical left-to-right ordering of binary operators in mathematics). Not really fixable; too much precedent.

    -

    Can't access array ordering directly

    +

    Can't access array ordering directly

    Only ⍋⍒ use array ordering rather than just array equality or numeric ordering. Getting at the actual ordering to just compare two arrays is more difficult than it should be (but not that difficult: < is TAO ).

    Syntactic type erasure

    A programmer can call a modifier on either a syntactic function or subject, but there's no way to know within the modifier which syntax that operand had. Maybe this is a better design, but it doesn't feel quite right that f˜ is f-Swap if f has a function value. The subject syntax suggests it should be Constant.

    @@ -58,35 +58,35 @@

    Characters ⥊∾⟜⎉⚇˜ and double-struck letters are either missing from many fonts or drawn strangely.

    Index Of privileges the first match

    It could be more sound to look at all matches, but using just the first one is too convenient. J has an index-of-last function; in BQN you have to reverse the left argument and then do arithmetic: ⊣-1+⌽.

    -

    Glyphs that aren't great

    +

    Glyphs that aren't great

    Blanket issue for glyphs that need work. Currently I find ⥊⊏⊑⊐⊒⍷⎉⚇ to not be particularly good fits for what they describe.

    Axis ordering is big-endian

    The most natural ordering for polynomial coefficients and base representations is little-endian, because it aligns element i of the list with power i of the argument or base. It also allows a forward scan instead of a reverse one. Array axes go the other way. However, there are advantages to this ordering as well. For example, it's common to act only on the first few axes, so having them at the beginning of the array is good (a ←→ a).

    -

    Trains don't like monads

    +

    Trains don't like monads

    If you have the normal mix of monads and dyads you'll need a lot of parentheses and might end up abusing . Largely solved with the "nothing" glyph ·, which acts like J's Cap ([:) in a train, but still a minor frustration.

    Inverse is not fully specified

    So it seems a bit strange to rely on it for core language features like /. On the other hand, this is a good fit for since we are taking an arbitrary branch of a complex function that has many of them. I'm pretty sure it's impossible to solve the issue as stated but it might be possible to move to less hazardous constructs. Structural Under is a start.

    -

    Monadic versus >

    +

    Monadic versus >

    Both pull out elements and reduce the depth. But they face in opposite directions.

    The directions of ⊏⊐ and so on were mainly chosen to line up with : the argument that indices apply to (that is, the one that is searched or selected from) corresponds to the open side of the function. I'd probably prefer new glyphs that don't have this sort of directionality, however.

    Converting a function expression to a subject is tricky

    You can name it, you can write Expr, and if it doesn't use special names you can write {Expr}. All of these are at least a little awkward in reasonable cases. Should there be a dedicated syntax? Note that going the other way, from subject to function, isn't too bad: the modifier {𝔽} does it.

    -

    Monadic argument corresponds to left for / and

    +

    Monadic argument corresponds to left for / and

    Called dyadically, both functions shuffle cells of the right argument around, which is consistent with other selection-type functions. But the monadic case applies to what would be the left argument in the dyadic case.

    -

    Prefixes/Suffixes add depth and Windows doesn't

    +

    Prefixes/Suffixes add depth and Windows doesn't

    It's an awkward inconsistency. Prefixes and Suffixes have to have a nested result, but Windows doesn't have to be flat; it's just that making it nested ignores the fact that it does have an array structure.

    -

    Rank/Depth negative zero

    +

    Rank/Depth negative zero

    A positive operand to Rank indicates the cell rank, so positive zero means to act on 0-cells. A negative operand indicates the frame length, so negative zero should act on the entire array. But it can't because it's equal to positive zero. Similar issue with Depth. Positive/negative is not really the right way to encode the frame/cell distinction, but it's convenient. Fortunately ∞ can be used in place of negative zero, but there can still be problems if the rank is computed.

    -

    Must read the body to find explicit definition's type

    +

    Must read the body to find explicit definition's type

    You have to scan for headers or double-struck names (and so does a compiler). A little inelegant, and difficult to describe in BNF.

    -

    Can't take Prefixes or Suffixes on multiple axes

    +

    Can't take Prefixes or Suffixes on multiple axes

    This is a natural array operation to do, and results in an array with a joinable structure, but as Prefixes and Suffixes are monadic there's no way to specify the number of axes to use.

    -

    And/Or/Max/Min are all tangled up

    +

    And/Or/Max/Min are all tangled up

    Boolean And () and Or () are identical to Min () and Max () when restricted to Boolean arguments, and this would fit nicely with their monadic role as sorting functions: for example ab ←→ ⊑∧ab. Furthermore the pairing of Min with Floor and Max with Ceiling is mnemonic only and not especially natural. The reason I have not used these glyphs for Min and Max, and have instead extended them to the somewhat superfluous arithmetic logical functions is that Min and Max have different identity elements of and ¯∞ rather than 1 and 0. Having to code around empty arrays when using ´ would be a fairly big issue.

    The other drawback of Min () and Max () is that the symbols are counterintuitive, but I have found a way to remember them: consider the graph of variables ax and b¬x for x from 0 to 1: two crossed lines. Now the graph of ab is a caret shape and ab is a vee.

    Acting on windows can be awkward

    When taking Windows along more than one axis, acting on the resulting array requires the Rank modifier, duplicating either the right argument rank or (negated) left argument length. A nested Windows would only require Each.

    -

    Group doesn't include trailing empty groups

    +

    Group doesn't include trailing empty groups

    But there are workarounds, described in its documentation. dzaima has suggested allowing a single extra element in the index argument to specify the result shape. Another possibility is for the result prototype to be specified to allow overtaking.

    Scan ordering is weird

    Scan moves along the array so that it uses results as left arguments, which is opposite to the usual right-to-left order of evaluation. But I think this is still better than scanning the array in reverse. You can always use Swap on the operand, or recover the APL scan ordering by doing a Reduce-Each on Prefixes.

    @@ -104,16 +104,16 @@

    I went with "Index of" and "Less Than or Equal to" but the last word blends into surrounding text. Should they be fully capitalized or hyphenated?

    Solved problems

    Problems that existed in mainstream APL or a transitional BQN that have in my opinion been put to rest (while in some cases introducing new problems). Listed in reverse chronological order by time solved, by my recollection.

    -

    "Modifier" and "composition" terminology

    +

    "Modifier" and "composition" terminology

    1-modifiers and 2-modifiers used to be called "modifiers" and "compositions", respectively, and sometimes "operators" collectively. The new names are much better, although they do leave a disconnect between the names for modifiers, and those for their inputs—"operands".

    -

    Can't return from inner functions

    +

    Can't return from inner functions

    Fixed by adding block returns such as label to jump out of a block with header name label. Hopefully these don't cause too many new problems.

    This was an issue with using functions as control flow. For example, when looping through an array with Each, you can't decide to exit early. In a curly-brace language you would just use a for loop and a return. In BQN, we need… longjmp? Maybe not as crazy as it sounds, and potentially worth it in exchange for replacing control structures.

    Ambivalent explicit functions

    Fixed with multiple bodies: if there are two bodies with no headers such as {2×𝕩;𝕨-𝕩}, they are the monadic and dyadic case.

    -

    How to choose a partitioning function?

    +

    How to choose a partitioning function?

    Fixed with Group, which I found May 2020. Group serves as a much improved Partition. However, it doesn't partition along multiple axes, so a dedicated partition function that does this could also be wanted. Or could Group be made to work with multiple axes as well as multidimensional indices?

    -

    Key doesn't do what you want

    +

    Key doesn't do what you want

    Fixed with Group to my satisfaction, except for the trailing-empty-group problem. There were various issues with Key operators in J and Dyalog, such as the fact that the ordering and presence of groups depends on where and whether the keys appear. Also, Dyalog's Key can return keys and values, but they are in a different format than the input: an array of pairs instead of two arrays. Monadic Group returns indices, which can be used how the programmer wants.

    Greek letter issues

    Fixed by not using Greek letters. In particular, the idea of using fancy Latin letters as fixed names for function arguments was suggested in proto-BQN sessions, possibly by Nathan Rogers.

    @@ -125,8 +125,8 @@

    Fixed with the casing conventions for variable names, which I think I first saw in APL\iv, although the cases are swapped relative to BQN.

    Selective assignment requires a named variable

    Fixed with structural Under, which I developed in 2017 and 2018.

    -

    It's hard use an array as a major cell

    +

    It's hard use an array as a major cell

    Fixed with : dyadic form from A+ and monadic/dyadic pair from J.

    -

    Scan and Windowed Reduce shouldn't always reduce

    +

    Scan and Windowed Reduce shouldn't always reduce

    Fixed with Prefix, Suffix, and Infix operators in J. Changed to functions in BQN.

    diff --git a/docs/running.html b/docs/running.html index f0050150..ae4ca9ac 100644 --- a/docs/running.html +++ b/docs/running.html @@ -2,12 +2,12 @@

    How to run BQN

    BQN is in a very early stage of development, and there is currently no complete implementation of the language. However, it's a relatively simple language to implement, and a few implementations come close.

    -

    BQN2NGN

    +

    BQN2NGN

    BQN2NGN is a prototype implementation in Javascript build to experiment with the langauge, which is now abandoned. Because you can use it online, this is probably the quickest way to get started with BQN. It has good primitive support, with the main issues being that it uses a J-style insert instead of BQN-style vector reduction, that it has a different version of Group (), and that it is missing Choose (). There are also some spelling differences, with Deduplicate () spelled with and Valences () spelled with . It is missing value blocks and function headers.

    For automated testing I run BQN2NGN using the bqn executable, which is just a symlink to apl.js in the BQN2NGN repository. It requires Node to run.

    -

    dzaima/BQN

    +

    dzaima/BQN

    dzaima/BQN is an implementation in Java created by modifying the existing dzaima/APL. It should be easy to run on desktop Linux and Android. It is still in development and has almost complete syntax support but incomplete primitive support.

    -

    dzaima+reference BQN

    +

    dzaima+reference BQN

    This repository contains a dzaima/BQN script dzref that fills in the gaps in primitive support using BQN implementations of primitives which are not yet up to spec (reference implementations of all primitives starting from a small set of pre-existing functions are part of BQN's specification). These alternate implementations can be very slow.

    You can run dzref from ordinary dzaima/BQN using the EX command; see for example dcshim.bqn. For testing, it is run as a Unix script, in which case it depends on an executable dbqn that runs dzaima/BQN on a file argument. I use the following script, using the path to a clone of dzaima/BQN for the jar file.

    #! /bin/bash
    diff --git a/docs/spec/evaluate.html b/docs/spec/evaluate.html
    index 66e49930..9f9781d3 100644
    --- a/docs/spec/evaluate.html
    +++ b/docs/spec/evaluate.html
    @@ -1,6 +1,6 @@
     
     
    -

    Specification: BQN evaluation

    +

    Specification: BQN evaluation

    This page describes the semantics of the code constructs whose grammar is given in grammar.md. The formation rules there are not named, and here they are identified by either the name of the term or by copying the rule entirely if there are several alternative productions.

    Here we assume that the referent of each identifier, or equivalently the connections between identifiers, have been identified according to the scoping rules.

    Programs and blocks

    diff --git a/docs/spec/grammar.html b/docs/spec/grammar.html index 8a3ead18..f6bf3810 100644 --- a/docs/spec/grammar.html +++ b/docs/spec/grammar.html @@ -1,6 +1,6 @@ -

    Specification: BQN grammar

    +

    Specification: BQN grammar

    BQN's grammar is given below. Terms are defined in a BNF variant. However, handling special names properly is possible but difficult in BNF, so they are explained in text along with the braced block grammar.

    The symbols s, F, _m, and _c_ are identifier tokens with subject, function, 1-modifier, and 2-modifier classes respectively. Similarly, sl, Fl, _ml, and _cl_ refer to literals and primitives of those classes. While names in the BNF here follow the identifier naming scheme, this is informative only: syntactic classes are no longer used after parsing and cannot be inspected in a running program.

    A program is a list of statements. Almost all statements are expressions. However, explicit definitions and valueless results stemming from ·, or 𝕨 in a monadic brace function, can be used as statements but not expressions.

    diff --git a/docs/spec/literal.html b/docs/spec/literal.html index 8cac38c5..928e64fc 100644 --- a/docs/spec/literal.html +++ b/docs/spec/literal.html @@ -1,6 +1,6 @@ -

    Specification: BQN literal notation

    +

    Specification: BQN literal notation

    A literal is a single token that indicates a fixed character, number, or array. While literals indicate values of a data type, primitives indicate values of an operation type: function, 1-modifier, or 2-modifier.

    Two types of literal deal with text. As the source code is considered to be a sequence of unicode code points ("characters"), and these code points are also used for BQN's character data type, the representation of a text literal is very similar to its value. In a text literal, the newline character is always represented using the ASCII line feed character, code point 10. A character literal is enclosed with single quotes ' and its value is identical to the single character between them. A string literal is enclosed in double quotes ", and any double quotes between them must come in pairs, as a lone double quote marks the end of the literal. The value of a string literal is a rank-1 array whose elements are the characters in between the enclosing quotes, after replacing each pair of double quotes with only one such quote.

    The format of a numeric literal is more complicated. From the tokenization rules, a numeric literal consists of a numeric character (one of ¯∞π.0123456789) followed by any number of numeric or alphabetic characters. Some numeric literals are valid and indicate a number, while others are invalid and cause an error. The grammar for valid numbers is given below in a BNF variant. Only four alphabetic characters are allowed: "i", which separates the real and imaginary components of a complex number, "e", which functions as in scientific notation, and the uppercase versions of these letters.

    diff --git a/docs/spec/token.html b/docs/spec/token.html index 9a121561..c12fc3e4 100644 --- a/docs/spec/token.html +++ b/docs/spec/token.html @@ -1,6 +1,6 @@ -

    Specification: BQN token formation

    +

    Specification: BQN token formation

    This page describes BQN's token formation rules (token formation is also called scanning). Most tokens in BQN are a single character long, but quoted characters and strings, identifiers, and numbers can consist of multiple characters, and comments, spaces, and tabs are discarded during token formation.

    BQN source code should be considered as a series of unicode code points, which we refer to as "characters". The separator between lines in a file is considered to be a single character, newline, even though some operating systems such as Windows typically represent it with a two-character CRLF sequence. Implementers should note that not all languages treat unicode code points as atomic, as exposing the UTF-8 or UTF-16 representation instead is common. For a language such as JavaScript that uses UTF-16, the double-struck characters 𝕨𝕎𝕩𝕏𝕗𝔽𝕘𝔾 are represented as two 16-bit surrogate characters, but BQN treats them as a single unit.

    A BQN character literal consists of a single character between single quotes, such as 'a', and a string literal consists of any number of characters between double quotes, such as "" or "abc". Character and string literals take precedence with comments over other tokenization rules, so that # between quotes does not start a comment and whitespace between quotes is not removed, but a quote within a comment does not start a character literal. Almost any character can be included directly in a character or string literal without escaping. The only exception is the double quote character ", which must be written twice to include it in a string, as otherwise it would end the string instead. Character literals require no escaping at all, as the length is fixed. In particular, literals for the double and single quote characters are written ''' and '"', while length-1 strings containing these characters are "'" and """".

    diff --git a/docs/spec/types.html b/docs/spec/types.html index 4570d2da..d3f71050 100644 --- a/docs/spec/types.html +++ b/docs/spec/types.html @@ -1,6 +1,6 @@ -

    Specification: BQN types

    +

    Specification: BQN types

    BQN programs manipulate data of six types:

    • Character
    • -- cgit v1.2.3