The Crow Programming Language

Arrays and Tensors

Arrays are ordered and homogeneous. Indexing is zero-based; negative indices count from the end:

1
2
3
4
5
6
7
nums = [10, 20, 30]
log[nums[0]]
log[nums[-1]]
log[len[nums]]
more = push[nums, 40]
log[more]
log[concat[[1, 2], [3, 4]]]

expected output — from the book, verified by crow test --book

10
30
3
[10, 20, 30, 40]
[1, 2, 3, 4]

push and concat return new arrays — Crow collections are immutable-by-rebuild, which is part of what keeps parallel loops safe.

Numeric Arrays Are Tensors

An all-numeric array literal is backed by a real tensor, so math works on it wholesale — + adds element-wise against another tensor or broadcasts a scalar; the dotted operators .*, ./, .^ are explicit element-wise multiply/divide/power:

1
2
3
4
5
a = [1.0, 2.0, 3.0]
b = [10.0, 20.0, 30.0]
log[a .* b]
log[a + b]
log[a * 2.0]

expected output — from the book, verified by crow test --book

[10, 40, 90]
[11, 22, 33]
[2, 4, 6]

Nest literals and you have a matrix — m[0] is a row, .shape tells you the dimensions, and use math unlocks the full toolkit (zeros, eye, matmul, reductions along axes — chapter 10 puts it to work):

1
2
3
m = [[1, 2], [3, 4]]
log[m[0]]
log[m.shape]

expected output — from the book, verified by crow test --book

[1, 2]
[2, 2]