summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRaghu R <rraghu.11502@gmail.com>2024-05-15 06:56:14 +0800
committerGitHub <noreply@github.com>2024-05-14 16:56:14 -0600
commit901d3924220b0ec9a02a5ce1041d3f99ce0c1daa (patch)
tree946343c11ebff6a97c78bc94e95ae4fbbc92d8e0
parente543ca4e52e2fc65b0ada75eded4af775a1c3bb2 (diff)
[bqn/en] Add BQN tutorial (#4523)
-rw-r--r--bqn.html.markdown289
1 files changed, 289 insertions, 0 deletions
diff --git a/bqn.html.markdown b/bqn.html.markdown
new file mode 100644
index 00000000..58c2f787
--- /dev/null
+++ b/bqn.html.markdown
@@ -0,0 +1,289 @@
+---
+language: bqn
+filename: learnbqn.bqn
+contributors:
+ - ["Raghu Ranganathan", "https://github.com/razetime"]
+translators:
+---
+
+BQN is a modern array language (similar to APL) that aims to eliminate burdensome aspects of the APL tradition.
+
+It is recommended to try these code examples out in a REPL. The [online REPL](https://mlochbaum.github.io/BQN/try.html) is
+recommended for quick start, since it comes with keyboard and easy to access help. You can try building
+[CBQN](https://github.com/dzaima/CBQN) for a local install, but it will need keyboard setup.
+
+```bqn
+# This is a comment.
+# The characters ',' and `⋄` are statement separators.
+
+##################
+# Main datatypes #
+##################
+
+# Numbers
+1,2,3,4
+¯1,¯2,¯3 # Negative numbers are written with a high minus
+π,∞,¯π,¯∞ # Pi and Infinity are defined constants
+1_234_456 # You can add underscores in between numbers
+ # This does not change their value
+1.3E4 # Scientific notation is supported
+
+# Characters
+'a','⥊'
+'
+' # Yes, you can put *any* character in a character literal
+@ # Null character ('\0' in C)
+# Arrays
+1‿2‿3 # Stranding, good for simple lists
+⟨1,2,3⟩ # General list notation
+⟨1‿2,2‿3⟩ # Both can be mixed
+[1‿2,2‿3] # Array notation
+ # An array is multidimensional, as opposed to containing sublists.
+ # It must be rectangular in shape (a grid structure rather than a tree structure)
+[1‿2‿3,4‿5] # This is hence invalid
+ # May be familiar coming from Numpy, MATLAB and similar languages.
+"asdf" # Character array (String)
+"newline
+separated" # Allows newlines
+"quo""tes" # Escape a double quote by typing it twice
+# Functions
+1{𝕨+𝕩}3 # All functions are infix
+ # 𝕨 is left argument, 𝕩 is right argument
+{-𝕩}5 # 𝕨 can be omitted
+1+3 # Same as the above
+{𝕊𝕩} # 𝕊 is a recursive call
+ # (this function will loop forever)
+{𝕨 𝕊 𝕩: 𝕨+𝕩} # Functions can have headers (too many cases to discuss here)
+ # Headers can define arity
+{𝕊 a‿b: a}1‿2 # and also do basic pattern matching
+ # (returns 1)
+
+# Modifiers (higher order functions)
+{𝕗,𝔽,𝕘,𝔾} # 𝔽 and 𝔾 are the operands as callable functions
+ # 𝕗 and 𝕘 are the operands as values
+{𝔽𝕩} # 1-modifiers use 𝔽/𝕗 ONLY
+˜,˘,¨,⁼,⌜ # primitive 1-modifiers are superscripts
+{𝕨𝔽𝔾𝕩} # 2-modifiers MUST use both 𝔽/𝕗 and 𝔾/𝕘 in body or header
+⊸,∘,○,⟜ # primitive 2-modifiers all have circles
++{⟨𝕗⟩} # returns ⟨ + ⟩
+1-{𝔽 𝕨 𝔾 𝕩 }×2 # returns ¯2 (operators are *also* infix)
+ # (same as 1 -○× 2)
+
+# Trains (Special form of function composition)
+(+´÷≠) # Average (but how?)
+# The above train is an F G H train, where
+# (F G H) 𝕩 → (F 𝕩) G (H 𝕩)
+# F ← +´, G ← ÷, H ← ≠
+# In explicit form, this is
+{(+´𝕩)÷≠𝕩}
+# The second pattern is (f g) 𝕩 → f g 𝕩.
+# longer trains are complex arrangements of these patterns, involving constants and Nothing (·).
+# Read more about trains at https://mlochbaum.github.io/BQN/doc/train.html
+
+# Evaluation order:
+# BQN evaluates functions right to left with no precedence rules governing *functions*. Functions are what
+# one would call operators in a mainstream language.
+1÷2+3 # 1÷(2+3) = 0.2
+(1÷2)+3 # ((1÷2)+3) = 1.5
+
+# Modifiers:
+# Modifiers are higher order functions, and bind tighter than functions. Modifiers execute left to right.
+# Modifiers can take non-function arguments e.g. Constant (`˙`)
++
+1+˜2+○-∘×3 # 1(+˜)(2((+○-)∘×)3)
+
+# Variables
+# Since the case of a variable matters to determine what it means, BQN variables are *case insensitive*
+# The case that a variable is written in can change the way it is interpreted by BQN.
+# Eg. `F` refers to a value as a callable function, whereas `f` refers to the same variable as just a value.
+# Variable assignment is done with `←`. Variables have naming conventions based on their value:
+subject ← 1‿2‿3 # Arrays, single values, namespaces come under this
+ # name must start with with a lowercase letter
+Function ← {𝕨+𝕩} # Primitive and user defined functions come under this, both monadic and dyadic
+ # Starts with an uppercase letter
+_1modifier ← {𝕨𝔽𝕩} # Starts with an underscore
+_2modifier_ ← {𝔽𝕨𝔾𝕩} # Starts and ends with an underscore
+# Variable modification is done with `↩`. An existing name cannot be reassigned with `←`.
+Func ↩ {"Hello"∾𝕩}
+array_or_atom +↩ 2 # You can use a dyadic function for modification
+ #≡ 3‿4‿5
+array_or_atom -↩ # Or a monadic function.
+ #≡ ¯3‿¯4‿¯5
+# Due to all functions being infix, you can use your own functions for modification as well:
+array_or_atom {2⋆𝕩}↩ #≡ ⟨ 0.125, 0.0625, 0.03125 ⟩
+
+##################
+# BQN Primitives #
+##################
+# All of BQN's base primitives are a single character long. Refer to https://mlochbaum.github.io/BQN/help/index.html for
+# examples.
+# Here we will look at a few primitives from each section. You will want to consult the docs for detailed explanations.
+
+# Primitive Functions
+# All BQN functions are variadic, and can take one or two arguments. The base functions have both monadic and dyadic overloads.
+# Usually the two overloads for a function are related.
+
+## Arithmetic Functions
++, -, ×, ÷ # Add, Subtract, Signum/Multiply, Reciprocal/Divide , '*' does NOT do multiplication
+ # ⌊∘÷ does floor division
+√, ⋆ # Square root/Nth root, e^x/Power
+# All Arithmetic functions vectorize:
+1 + 2‿3‿4 #≡ 3‿4‿5
+1‿2‿3 + 2‿3‿4 #≡ 3‿5‿7
+# Character arithmetic(+ and - only):
+"abc"+3 #≡ "def"
+'a'-'d' #≡ ¯3
+
+## Logic Functions
+∧, ∨, ¬ # For Booleans, retrun 1 or 0
+≤, <, >, ≥, = # Vectorizing comparisons
+≡, ≢ # Nonvectorizing comparisons
+
+## Array manipulation Functions
+↕ # Make a range
+∾, ≍, ⋈ # Joining arrays together
+a←1‿2‿3,b←4‿5 # Let us take a and b.
+a∾b #≡ 1‿2‿3‿4‿5
+a≍b # Same as previous, since a and b are not multidimensional
+ # Adds an extra dimension, similar to a ⋈ for multidimensional arrays.
+a⋈b #≡ ⟨1‿2‿3, 4‿5⟩
+⊑, ⊏ # Indexing
+1⊑1‿2‿3 #≡ 2 (BQN is 0-indexed)
+1‿2⊏1‿2‿3 #≡ 2‿3 (for multiple indices)
+↑, ↓ # Getting a prefix, suffix of an array.
+ # together they can be used for slicing
+⥊ # Reshape/repeat items to create a new array
+
+# Primitive 1-Modifiers
+## Looping combinators
+¨, ˘, ⌜ # Mapping/Zipping
+´, ˝ # Fold from right
+` # Scan from left
+
+## General combinators
+˜ # duplicate argument/swap args - Very useful!
+˙ # Create constant function
+1 -˜ 2 #≡ 2 - 1
++˜ 2 #≡ 2 + 2
+
+# Primitive 2-modifiers
+## Control Flow
+◶ # Choose from a list of funcs
+⍟ # Repeat n times
+
+## General Combinators
+⊸, ⟜ # hook, hookf
+∘, ○ # simple function composition
+
+##########
+# Blocks #
+##########
+# Code delimited by {}
+# Lexically scoped
+# For more info: https://mlochbaum.github.io/BQN/doc/block.html
+# Can have headers, which are ways to explicitly define what a block should be.
+# A block without headers is automatically inferred from its special variables (𝕨, 𝕩, ...).
+
+# Function blocks
+# Implicit variables(Capitals are functions):
+# - 𝕨, 𝕎 left argument
+# - 𝕩, 𝕏 right argument
+# - 𝕤, 𝕊 represent the block itself
+# Optional: one or more headers that trigger based on
+# - pattern match (':') o
+# - condition ('?') (similar to if-then-else)
+
+{ # A factorial using headers:
+ 𝕊 0: 1;
+ 𝕊 𝕩: 𝕩×𝕊 𝕩-1
+}
+{ # Factorial with predicates
+ 𝕩<2 ? 1; # Similar to an if-else pattern.
+ 𝕩×𝕊 𝕩-1
+}
+
+# Modifier blocks
+# create 1-modifiers and 2-modifiers, which have separate types
+# Implicit variables(Capitals are functions):
+# - has 𝕨 and 𝕩 if needed
+# - 𝕗, 𝔽 left operand
+# - 𝕘, 𝔾 right operand (only in 2-modifiers)
+# - 𝕣 represents the block itself* (requires underscores as per convention)
+# Same header rules as functions.
+{ 𝕨=0 ? 𝔽 𝕩; 𝔾 𝕩 } # execute 𝔽 or 𝔾 based on whether left argument is 0.
+
+# Namespace blocks
+# Create immutable namespaces with fields
+# Require exports (`⇐`) for accessible fields.
+# Use '.' for field access
+n←{
+ A←+
+ b⇐4
+}
+n.b #≡ 4
+n.a # ERROR
+
+# Immediate Blocks
+# No arguments taken
+# Run the code inside and return the last statement
+# Often responsible for strange errors.
+# Can be mistaken for other blocks easily
+# Good for avoiding scoping issues
+{
+ 1‿2‿3
+}
+{+} # Trick for returning a function as a value
+####################
+# Basic constructs #
+####################
+# Functional programming
+# `¨` is used for mapping, as discussed before:
+{𝕩∾2}¨1‿2‿3 #≡ ⟨1‿2,2‿2,3‿2⟩
+# ⋈¨ is a plain zip, which produces pairs.
+# `¨` acts as a zipWith when used with two arguments:
+1‿2‿3 {⟨𝕩+2,2⥊𝕨⟩} 4‿5‿6 #≡ ⟨⟨6,1‿1⟩,⟨7,2‿2⟩,⟨8,3‿3⟩⟩
+# `/` is replicate, which serves several purposes *including* filtering.
+# elements in 𝕩 are repeated by the corresponding number in 𝕨.
+1‿2‿3‿0/4‿5‿6‿7 #≡ 4‿5‿5‿6‿6‿6
+# a simple filter idiom is F⊸/:
+{2|𝕩}⊸/67‿42‿83 # keep the odd elements
+ #≡ 67‿83
+
+# Conditionals
+# There are two main ways to define a conditional.
+## Predicate headers
+{
+ 𝕩 > 2: "greater than 2";
+ 𝕩 < 2: "lesser than 2";
+ "equal to 2"
+}
+
+## Choose (function-based)
+# - 2-modifier
+# - 𝔾: list of functions that serve as bodies
+# - 𝔽: condition function that specifies which function from 𝔾 to select
+# The same conditional as above would be:
+{⊑/⟨𝕩>2, 𝕩<2, 𝕩=2⟩}◶⟨
+ {𝕊: "greater than 2"}
+ {𝕊: "lesser than 2"}
+ {𝕊: "equal to 2"}
+⟩
+
+## Some helpers for conditionals
+If ← {𝕏⍟𝕎@}´ # Used as If ⟨Condition, Block⟩
+IfElse ← {c‿T‿F: c◶F‿T@} # Used as IfElse ⟨Condition, Block, ElseBlock⟩
+
+# Looping
+# The primary form of unbounded looping is recursion (performed with 𝕊).
+# BQN does not eliminate tail calls, but the while idiom can be used to work around this:
+While ← {𝕩{𝔽⍟𝔾∘𝔽_𝕣_𝔾∘𝔽⍟𝔾𝕩}𝕨@}´ # While 1‿{... to run forever
+DoWhile ← {𝕏@ ⋄ While 𝕨‿𝕩}´
+# A For loop can be done with ¨, functions need not be pure.
+```
+
+## Ready for more?
+
+- [Quickstart guide](https://mlochbaum.github.io/BQN/doc/quick.html)
+- [Full length, explained documentation](https://mlochbaum.github.io/BQN/doc/index.html)
+- [Short docs](https://mlochbaum.github.io/BQN/help/index.html)
+- [BQN community!](https://mlochbaum.github.io/BQN/community/index.html)