Learn Kap in 10 minutes

I adapted this from the BQN tutorial, originally by razetime.

⍝ This is a comment.
⍝ The character ⋄ is statement separator.
⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝
⍝ Main datatypes ⍝
⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝
⍝ Numbers
1 2 3 4 ⍝ a four element array, can be defined with or without ,
¯1,¯2,¯3 ⍝ Negative numbers are written with a high minus
πmath:pi ⍝ Variable assignment is done with ←
math:inf
π,π⍝ Define nicer looking variable names for Pi and Infinity
1.3E4 ⍝ Scientific notation is supported
⍝ Keywords
default:foo ⍝ all symbols belong to a namespace
:foo ⍝ if the namespace is blank, it is assumed to be a keyword
⍝ Characters
@a, @⍝ @ in front of character tells it's a single character
⍝ and not a string
⍝ Arrays
1 2 3 ⍝ an array of 3 numbers
(1,2,3) ⍝ General array notation
(1;2;3) ⍝ with semicolons it is 3-tuple, a container for values (different from an array)
"asdf" ⍝ Character array (String)
"newline
separated" ⍝ Allows newlines
"quo\"tes" ⍝ Escape a double quote by adding \ in front
⍝ Functions
1{+}3 ⍝ All functions are infix
⍝ ⍺ is left argument, ⍵ is right argument
{-}5 ⍝ ⍺ can be omitted
1+3 ⍝ Same as the above
leftArg myFun rightArg { ⍝ Functions can have headers
leftArg+rightArg ⍝ Headers can define arity
}
⍝ Trains and forks (Special form of function composition)
+/«÷» ⍝ Average (but how?)
⍝ The above fork is an F G H fork, 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.
⍝ Read more about forks and trains at https://kapdemo.dhsdevelopments.com/reference.html
⍝ Evaluation order:
⍝ Kap 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) = 1/5
(1÷2)+3 ⍝ ((1÷2)+3) = 7/2
⍝ Modifiers:
⍝ Modifiers are higher order functions, and bind tighter than functions.
⍝Modifiers execute left to right.
+
1+⍨2+⍥-⍛×3 ⍝ 1(+⍨)(2((+⍥-)⍛×)3)
⍝ Variables
⍝ Since the case of a variable matters to determine what it means, Kap variables are
⍝ *case insensitive*. Variable assignment is done with ←, functions with ⇐.
subject 1 2 3 ⍝ an array, defined with ←
⍝ first letter in name can be in any case
function ⇐ {+} ⍝ a function
⍝ An existing name can be reassigned with ←/⇐.
function ⇐ { "Hello, ",⍕ }
⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝
⍝ Kap Primitives ⍝
⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝
⍝ All of Kap's base primitives are a single character long.
⍝ Refer to https://kapdemo.dhsdevelopments.com/reference.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
⍝ Almost all Kap base functions can take one or two arguments.
⍝ 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, return 1 or 0
≤, <, >, ≥, = ⍝ Vectorizing comparisons
≡, ⍝ Nonvectorizing comparisons
⍝⍝ Array manipulation Functions
⍝ Make a range
, ⍝ Joining arrays together
a1 2 3b4 5 ⍝ Let us take a and b.
a,b ⍝≡ 1 2 3 4 5
ab ⍝ Same as previous, since a and b are not multidimensional
ab ⍝≡ (1 2 3) (4 5)
⊃,⍝ Indexing
11 2 3 ⍝≡ 2 (Kap is 0-indexed)
1 21 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!
1 -⍨ 2 ⍝≡ 2 - 1
+⍨ 2 ⍝≡ 2 + 2
⍝⍝ General Combinators
∘, ⍝ hook, hookf
∘, ⍝ simple function composition
⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝
⍝ Blocks ⍝
⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝
⍝ Code delimited by {}
⍝ Lexically scoped
⍝ A block is automatically inferred from its special variables (⍺, ⍵, ...).
⍝ Function blocks
⍝ defined with a ∇, has a header and a body
⍝ Implicit variables:
⍝ - ⍺ left argument
⍝ - ⍵ right argument
⍝ ∇ header {
⍝ body
⍝ }
⍝ The header has the following possible forms:
⍝ name — Declare a function named name. In body, the left argument
⍝ is accessed using ⍺ and the right argument using ⍵.
⍝ name x — The right argument is accessed using the name x.
⍝ The left argument is not accessible.
⍝ x name y — The left argument is accessed using the name x,
⍝ and the right argument has the name y.
⍝ (a;b) name (d;e) — The left and right arguments are assumed to be
⍝ n-tuples and are destructured prior to evaluating the body.
⍝ (a name) x — Monadic operator deriving a monadic function.
⍝ x (a name b) y — Dyadic operator deriving a dyadic function.
⍝ Finds prime factors of a number
primeFactors n {
pf ⇐ { (=1)
if (0=|) { , ((÷) pf) }
else { pf (+1) }
}
(n pf 2)
}
⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝
⍝ 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 7 8) (1 2)
⍝ / 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.
⍝⍝ a when clause
{ when {
( > 2) { "greater than 2" }
( < 2) { "lesser than 2" }
(1) { "equal to 2" }
} }
⍝⍝ if clauses
{ if (<2) {"lesser than 2"} else { if (>2) {"greater than 2"} else {"equal to 2"} } } 5
⍝ Looping
⍝ The primary form of unbounded looping is a while clause.
{
n
while (n>0) { io:println n n n-1 }
} 4
⍝ You can also do recursion (with a named function).
⍝ This example is from Structure and Implementation of Computer Programs:
sqrt x {
improve ⇐ { (+(x÷))÷2 }
goodenough ⇐ { 0.001>|(×)-x }
try ⇐ { if (goodenough) { } else { try (improve) } }
(try 1)
}