j + k = jk (just kidding)

txlyre 7b140a9581 make %: work with chars 1 Minggu lalu
.gitignore dcd441be2a initial 4 minggu lalu
build.sh 4935e3aace add foreign 2 minggu lalu
jk.c 7b140a9581 make %: work with chars 1 Minggu lalu
readme.md 5bad7b1ebc upd help 2 minggu lalu

readme.md

jk

jk is a recreational tacit array programming language inspired by J and K (so j + k = jk).
this is an implementation of the jk interpreter in C. Requires libgc (a.k.a. bdwgc) to build.

Examples

Compute factorial

    fac:*/!. / analytic
    fac 5
120
    facr:<.;1?.(]*(s.<)),:(:1) / recursive
    facr 5
120
    / or simply use *.
    *.5
120

Compute Nth fibonacci

    fib:*x?:(+\|)!2 / iterative
    fib 10
55
    fib"!.10
1 1 2 3 5 8 13 21 34 55
    fibr:<.;1?.((s.<)+(s.(<<))),:] / recursive
    fibr"!.10
1 1 2 3 5 8 13 21 34 55
    / or just +.
    +.!.10
1 1 2 3 5 8 13 21 34 55

Remove consecutive duplicates

    rcd:]&.(1~:".)
    rcd 'abobaabuuss'
abobabus

Check if an array is palindrome

    ispal:]=:|
    ispal 'aboba'
1
    ispal 'hi'
0

Count occurences

    occs:?,"(#"]@#:)
    occs 'abracadabra'
a 5
b 2
r 2
c 1
d 1
    occs 'Hello World!'
H 1
e 1
l 3
o 2
  1
W 1
r 1
d 1
! 1
    *it@<:{."it / get most frequent
l 3

Make multiplication table

    *\.;.!.9
1  2  3  4  5  6  7  8  9
2  4  6  8 10 12 14 16 18
3  6  9 12 15 18 21 24 27
4  8 12 16 20 24 28 32 36
5 10 15 20 25 30 35 40 45
6 12 18 24 30 36 42 48 54
7 14 21 28 35 42 49 56 63
8 16 24 32 40 48 56 64 72
9 18 27 36 45 54 63 72 81

Duplicate zeroes keeping the same shape

    dzks:##]#.(>0=)
    dzks 1 0 2 3 0 4 5 0
1 0 0 2 3 0 0 4

Quick reference (also available in the interpreter itself)

/ comment
5+5 / also comment
5+5/not comment (no whitespace before /)
nil udf                   / special, nil and undefined
'a'%2                     / = nan, nan used to denote illegal numeric operation
+1 2 3                    / = udf, attempt to transpose flat vector, udf/undefined used to denote illegal operation
5 5.5 -5 42               / number (double-precision floats)
1`000 1`000`000           /
.5 .429                   /
0xff 0o4 0b0101           /
nan inf                   /
'a' 'b' 'g'               / chars (bytes)
4t.0                      / 0 NUL byte
(4t.0),:(4t.16),:(4t.22)  /
1 2 3                     / numbers array
'hello world!' 'bla''bla' / quote, array of chars
,'a'                      / 1-char string
,1                        / 1-elt array
()                        / unit, empty array
1,:(5+5),:1 2 3           / strand, mixed array literal
-1                        / negative num literal
- 1                       / application of - negate to 1
-1 -2 -3                  / array of negative nums
- 1 2 3                   / application of - negate to an array of nums
5-5                       / array of numbers 5 and -5
5- 5                      / 5 minus 5
+                         / verb
5+5                       / dyadic expr
#1 2 3                    / monadic expr (no left side)
+/ *;.                    / adverb
+;1 -;* +^:^.             / conjunction
:x+y                      / function literal
:1                        / function that always yields 1
x:123                     / bind name
sq:*;.                    /
fac:*/1+!                 / bind function
f:x+y                     /
f:-x                      / overload function by arity
f 5                       / = -5
5 f 5                     / = 10
*/!.                      / hook, fgx -> f(g(x)), xfgy -> f(g(x, y))
+/%#                      / fork, fghx -> g(f(x), h(x)), xfghy -> g(f(x), h(y))
1+!                       / over, nfgx -> f(n, g(x)), xnfgy -> f(n, g(x, y))
1+                        / bond, nfx -> f(n, x), xnfy -> f(n, f(x, y))

:  monadic const         create a function that always yields x
:  dyadic  bind          bind y to symbol x
:: monadic unbind        unbind symbol x
:: dyadic  obverse       insert inverse for x
+  monadic flip          transpose matrix
+  dyadic  plus          add numbers
+. monadic fibonacci     compute xth fibonacci number
+. dyadic  gcd           compute gcd(x, y)
+: monadic sin           compute sin(x)
+: dyadic  combine       combine digits of x and y, same as 10_.(10_:),(10_:)
-  monadic negate        negate number
-  dyadic  minus         subtract numbers
*  monadic first         yield first element of x
*  dyadic  times         multiply numbers
*. monadic factorial     x!
*. dyadic  lcm           compute lcm(x, y)
*: monadic double        x * 2
*: dyadic  replicate     repeat y x times
%  monadic reciprocal    1 / x
%  dyadic  divide        divide numbers
%. monadic sqrt          compute square root of x
%. dyadic  root          compute xth root of y
%: monadic halve         x % 2
%: dyadic  idivide       same as % divide, but result is always integer
!  monadic enum          [0, x)
!  dyadic  mod           modulo of numbers
!. monadic iota          [1, x]
!. dyadic  range         [x, y] (also works for chars and even if x > y)
!: monadic odometer      !:10 10 is 0 0,:0 1,: ... 1 0,:1 1,: ... 9 8,:9 9
!: dyadic  chunks        split y into x-sized chunks
^  monadic exp           e^x
^  dyadic  power         raise number to a power
^. monadic nlog          ln(x)
^. dyadic  log           log(y)/log(x)
=  monadic permute       generate permutations of x
=  dyadic  equals        test whether x and y are equal
=. monadic occurences    count occurences of elts, =.'Hello World!' is 0 0 0 1 0 0 0 1 0 2 0 0
=. dyadic  mask          mask one array in another, 'abxyzabayxxyabxyk'=.'xy' is 0 0 1 1 0 0 0 0 0 0 2 2 0 0 3 3 0
=: monadic classify      assign unique index to each unique elt, =:'Hello World!' is 0 1 2 2 3 4 5 3 6 2 7 8
=: dyadic  match         same as = equals, but rank 0, so compares x and y as whole
~  monadic not           logical not, nil udf () 0 4t.0 are not truthy, everything else is truthy
~  dyadic  notequals     test whether x and y are not equal
~. monadic sign          sign of x, -1 for negative, 0 for 0, 1 for positive
~. dyadic  insert        insert x between elts of y, 0~.1 2 3 is 1 0 2 0 3
~: dyadic  notmatch      rank 0 version of ~ notequals
<  monadic pred          x - 1
<  dyadic  less          test whether x is lesser than y
<. monadic floor         round x down
<. dyadic  lesseq        test whether x is equal or lesser than y
<: monadic gradedown     indices of array sorted descending
<: dyadic  nudgeleft     shift elts of y to the left filling gap with x
>  monadic succ          x + 1
>  dyadic  greater       test whether x is greater than y
>. monadic ceil          round x up
>. dyadic  greatereq     test whether x is equal or greater than y
>: monadic gradeup       indices of array sorted ascending
>: dyadic  nudgeright    shift elts of y to the right filling gap with x
,  monadic enlist        put x into 1-elt array
,  dyadic  join          concat x and y
,. monadic enfile        same as , enlist but with infinite rank, ,.1 2 3 is (,1),:(,2),:(,3)
,. dyadic  enpair        put x and y into 2-elt array
#  monadic count         yield count of elts of x
#  dyadic  take          take x first elts of y (or last if x < 0)
#. monadic where         #.0 0 1 0 1 0 is 2 4
#. dyadic  copy          repeat each elt of x by corresponding number in y, 5 2 3 3#.0 2 2 1 is 2 2 3 3 3
#: monadic group         #:'mississippi' is (,0),:1 4 7 10,:2 3 5 6,:8 9
#: dyadic  buckets       group elts of y into buckets according to x, e.g. 0 -1 -1 2 0#:a b c d e is (a,.e),:(),:(,d)
_  monadic nub           mark all unique elts of x, e.g. _'abracadabra' yields 1 1 1 0 1 0 1 0 0 0 0
_  dyadic  drop          remove first x elts of y (or last if x < 0)
_. monadic unbits        _.1 0 1 is 5
_. dyadic  unbase        10_.4 5 6 is 456
_: monadic bits          _:5 is 1 0 1
_: dyadic  base          10_:4242 is 4 2 4 2
?  monadic unique        distinct elts of x, same as ]#._
?  dyadic  find          find all indices of x in y
&  monadic flatten       flatten an array, same as ,//.
&  dyadic  minand        get min of two numbers (logical and for 0/1s)
|  monadic reverse       reverse an array
|  dyadic  maxor         get max of two numbers (for 0/1s is same as logical or)
|. monadic round         round x
|. dyadic  rotate        rotate array x times clockwise (-x for counterclockwise)
|: monadic depth         find max depth of x, |:,,,y yields 3
|: dyadic  windows       yields all contiguous x-sized subarrays of y
@  monadic abs           |x|
@  dyadic  at            pick elts from x by indices from y
@. monadic shuffle       shuffle elts of x
@. dyadic  member        check whether x is in y
@: dyadic  indexof       yield index of x in y or #y if x not in y
{  monadic head          first two elts of x, same as 2#
{  dyadic  bin           bin search, e.g. 1 3 5 7 9{8 9 0 yields 3 4 -1
{. monadic tail          last elt of x
{: monadic prefixes      prefixes of x, same as |}.\.
{: dyadic  shl           x << y
}  monadic behead        all elts of x except first, same as 1_
}  dyadic  xor           x ^ y
}. monadic curtail       all elts of x except last, same as -1_
}: monadic suffixes      suffixes of x, same as }.\.
}: dyadic  shr           x >> y
[  monadic factors       compute prime factors of x
[  dyadic  left          yield x
[. monadic bnot          ~x
[. dyadic  bor           x | y
[: monadic primes        find primes in range [2, x]
[: dyadic  parts         split y into x parts
]  monadic same          yield x (i.e. identity)
]  dyadic  right         yield y (i.e. right argument)
]. monadic sort          sort x ascending, shortcut for ]@>:
]. dyadic  outof         the number of ways of picking x balls from a bag of y balls, e.g. 5].10 is 252
]: monadic unsort        sort x descending, shortcut for ]@<:
]: dyadic  explode       split y by delim x
`. monadic symbol        cast x to a symbol
`. dyadic  apply1        apply x to y
`: monadic square        x ^ 2
`: dyadic  apply2        apply x to y (y is 2-elt array of args)
$  monadic shape         yield shape of x
$  dyadic  reshape       reshape y to shape x
$. monadic repr          yield string repr of x
$. dyadic  format        format y by template x, e.g. '{0}+{1}*{-1}+_'$.1 2 3 4 is 1+2*4+1
$: monadic eye           identity matrix of size x
$: dyadic  implode       join y inserting x between

p. monadic print         print x
P. monadic println       print x and a \n
c. monadic putch         print char x
s. monadic selfref1      monadic reference to current function or rhs of bind or top-most train
s. dyadic  selfref2      dyadic reference to current function or rhs of bind or top-most train
F. monadic read          read file (x=0 to read stdin)
F. dyadic  write         write file (y=0 to write to stderr)
t. monadic type          type of x, array=0, verb=1, symbol=2, number=3, char=4, nil=5, udf=6
r. monadic deal          yield random elt of x
r. dyadic  roll          roll xdy (note: y is 0-based, so >xr.y for 1-based)
e. monadic eval          eval expression, yields udf on parse error
i. monadic import        load and eval source file
i. dyadic  foreign       call external function (lhs is array of arguments), e.g. .5i.'libm.so:dd:sin'
y. monadic system        exec system command (yields output)
y. dyadic  system2       exec system command with input
E. monadic exit          exit with exit code
L. dyadic  tackleft      prepend x to y
R. dyadic  tackright     append x to y
"v. monadic value         get value of var x (udf if not defined)

f"         each          >"1 2 3 yields 2 3 4
xf"        merge         1 2 3,"a b c yields (1,.a),:(2,.b),:(3,.c)
f".        eachprior     -".1 2 2 3 5 6 yields 1 0 1 2 1
xf".       eachpriorwith 0-".1 2 2 3 5 6 yields 1 1 0 1 2 1
f/         fold          +/1 2 3 yields 6
xf/        foldwith      1+/1 2 3 yields 7
f\         scan          +\1 2 3 yields 1 3 6
xf\        scanwith      1+\1 2 3 yields 1 2 4 7
f/.        converge      1;_/.1 2 3 yields ()
f\.        converges     1;_\.1 2 3 yields 1 2 3,:2 3,:(,3),:()
xf/.       eachright     1-/.1 2 3 yields 0 1 2
xf\.       eachleft      1-\.1 2 3 yields 0 -1 -2
f":        rank          #":1 2 3$1 yields 3 3, #":inf 2 3$1 yields 1 1 1,:1 1 1
xf":       rank2         1 2 3 *:":1 1 2 3 yields (,1),:2 2,:3 3 3
n`         amend         'gw'0 3`'cross' yields 'grows'
f&.        filter        >;0&.-2!.2 yields 1 2, basically shortcut for ]#.f
f/:        span          =;' '/:'x y z' yields (,'x'),:(,'y'),:(,'z')
xf/:       stencil       3+//:!10 yields 3 6 9 12 15 18 21 24, shortcut for f"x|:
f;.        reflex        *;.5 yields 25, 5%;.2 yields 0.4

f;g        bond          */;!.5 yields 120, +;1 5 yields 6, 5;- 1 yields 4
f?.x       pick          >;5?.((2*),:<)"3 6 yields 6 5
f?:F       while         <;5?:>0 yields 5
n?:f       repeat        5?:*;2 1 yields 32
f&:F       if            1+&:+2 yields 2
f;:F       monaddyad     -;:+5 yields -5, 1-;:+5 yields 6

inverse of a function f is a function ~f that undoes the effect of f

f::~f  obverse  define inverse ~f for f

f-:x       inverse       ~fx
xf-:y      inverse2      (~fx)~f~fx
f^:Fx      under         ~FfFx
xf^:Fx     under2        ~F(Fx)f(Fx)

Prebuilt binaries

There is prebuilt ELF executables with statically linked libgc for x86-64 and aarch64 Linux: