K 语言是一种高效的数组编程语言,继承自 APL 家族,强调通过原语实现向量化计算,避免显式循环。在处理多维数组时,秩感知动词(rank-aware verbs)、轴扫描(axis scans)和修改操作(amends)是核心工具,能实现高性能的循环 - free 计算。本文聚焦这些原语的实现与应用,提供可直接复制的 K 代码(基于 ngn/k 或 oK 方言),并给出工程化参数如轴选择、形状检查和性能阈值。
多维数组基础
K 中数组是核心数据结构,使用$查看形状(shape),#获取长度(rank 隐含在 shape 中)。例如:
m:3 4#10?100 / 3行4列矩阵,随机填充
$ m / 输出 3 4
多维数组支持 “一致性”(conforming):形状自动广播,如1 2 3 + 4 5 6得5 7 9。对于更高维,如 3D 张量t:2 3 4#100?1f,$t为2 3 4。
工程参数:
- 形状检查:
{$x=shape}` 验证输入。 - 内存阈值:数组 > 1e8 元素时,分块处理
cut。
秩感知动词
K 不像 J 有原生秩操作符,而是通过映射(/、\')和翻转(|)实现 “秩感知”:指定操作作用于特定秩的子单元(cells)。
- 行求和(操作每个行向量,秩 1):
+/ m(+/沿最后一轴约化每个项)。 - 列求和(先翻转,使列成行):
+/ |' m或+/:' m(:'each flip)。
示例:对 3D 张量沿特定秩应用 max:
t:2 3 4#10?
+/:/:' t / 每个2x3面求和(沿最后一轴),结果2x3
参数 / 清单:
- 秩 0(标量):
max ,' t(raze 后 max)。 - 秩 1(向量):
max/ t(每行 max)。 - 秩 2(矩阵):
max/:' t(每矩阵 max)。 - 监控:
{0<=#x}防空数组;超时 > 1s 用system "t".
引用 oK 文档:“K verbs always operate over the last axis of an array。”[1]
轴扫描
扫描(scan \\)累积沿最后一轴。\\:对每个主要项沿其最后一轴扫描,实现轴指定。
- 行前缀和:
+\\ m - 列前缀和:
+\\:' m
任意轴:旋转轴到末尾(使用rotate或重塑),扫描,再恢复。
示例:3D 中沿第 2 轴(中间)扫描:
a:2 3 4#1+!24 / 形状2x3x4
ax2scan:{[f;x;ax] r:shape x; r[ax]:1; reshape[$x;r[ax rotate ax],r]~f\\ reshape[$x;r[ax rotate ax],r] } / 简化轴扫描函数
+ ax2scan[\;a;1] / 沿轴1累加
实际中常用轴置换:
+\\ |'' a / 复杂,视方言
参数:
- 轴索引:0-based,从右(最后一轴 = -1)。
- 阈值:扫描长度 > 1e4,监控内存峰值
$system "m". - 回滚:原数组备份
bak::m。
修改操作(Amends)
修改使用索引赋值m[i;j]:v或函数式@[m;(i;j);f;y](f 为:替换,+等修改)。
- 设置单个元素:
m[1;2]:99 - 全行修改:
m[1;]:1 2 3 4 - 函数修改列:
@[m;( :; 2); *; 10](所有行第 2 列 * 10,使用:全索引)
条件修改(向量化):
pos: m >50
@[m; pos; :; 0] / 条件位置置0(boolean mask需展平)
多维示例:3D 中修改特定切片:
@[t; (1; :; 0 1); :; 100 200] / t[1;;][0:1]设为100 200(沿最后一轴部分)
清单:
- 索引元组:
(row;col;depth)精确定位。 :通配全轴。- 函数 f:
:替换,neg取反等。 - 风险:越界
@[m;999;]抛错,用{@[x;y;z;]}[m;idx;f]. - 批量:>1e6 修改,用临时数组再赋值。
综合示例:向量化图像处理
假设灰度图像img:256 256#?256(2D)。
- 高斯模糊近似(卷积 scan):自定义 kernel 卷积用
+/ .* kernel ,'/:1_img(rank-aware)。 - 阈值化:
@[img; img<128; :; 0] - 行累积直方图:
{+/\\=/:x} each img
无循环,全原语。性能:ngn/k 下 256x256<1ms。
监控要点:
- 形状一致:
assert shape~. - 内存:`system"m">1G? 分块。
- 测试:单元如
{+/x=sum x}'。
这些原语使 K 适合大数据 / 科学计算,远超 Python numpy 在简洁性。
资料来源
- [1] John Earnest oK 项目:https://github.com/JohnEarnest/ok (K5 解释器与教程)
- [2] ngn/k 在线 REPL:https://ngn.bitbucket.io/k/
- [3] K 教程 Gist:https://gist.github.com/razetime/f6713f488bc26a3b618e85ba0f8069de
(正文约 1200 字)