背景(spec 已定,本条求把 key 侧写准)
map 结构现有 spec 写法:
memhead : memitemkey_langtype · memitemvalue_langtype = {}
更准确的定义是:
memhead : memitemkey_langtype_formatter · memitemvalue_langtype = {}
即 memitemkey 不是"一个值类型",而是一个"把 key 值格式化成路径段字符串的格式器"——因为 memitemkey 永远活在路径系统里(memhead·<key 文本>),从不进入任何 XValue 的 body。key 侧压根没有 body 可承载类型,key 的类型完全是字符串层面的事,故必须由 formatter 规定"什么值的 key 格式化成什么字面量文本"。
现象(实测 kvlanglayout vet)
| 用例 |
结果 |
a:int32·int32 = {} + a·200 = 7 |
✅ 通过(裸标量键,访问键 a·200) |
a:[int32]·int32 = {} + a·[200] = 7 |
✅ 通过(1 元标量元组键,访问键 a·[200]) |
b:[2]int32·[]char/utf8 = {} |
❌ error: invalid langtype "[2]int32·[]char/utf8" on container literal target "b" |
b2:[int32,int32]·[]char/utf8 = {} + b2·[1,2] = "x" |
✅ 通过(访问键 b2·[1,2]) |
spec 03-类型系统/07 的非法例也含:[.]·int64(map 键含维度)、[foo,int32]·int64(元组键含非标量)。
为什么:[2]float32 与 [float64,float64] 是两回事
[2]float32:数组形状(dims + 元素种类),描述"一段连续打包进 body 的等宽元素"——属于 value 的 langtype。做键时它描述不了路径段文本,故非法。
[float64,float64]:标量元组键,描述"一个由 2 个标量组成的 key 值",formatter 产出 [3.252,235124.23]——只约束真实的 key 文本,没有 body 含义。
同一道理,a:int32·int32 与 a:[int32]·int32 是两个不同的 formatter(裸标量 a·200 vs 一元元组 a·[200]),按逐字铁律不得互相转换。
建议的 spec 措辞(三选一 key + formatter 输出即访问键)
| memitemkey_langtype |
formatter 输出(=访问键) |
例 |
裸标量(bool + 十个定宽数字种类) |
该标量的字面量文本 |
b·200 |
标量元组 [scalar,…] |
[v0,v1,…](逗号分隔、无空格) |
a·[3.252,235124.23] |
[]char/<编码> |
字符串本身(裸名) |
m·a / kv·set(m,"a",v) |
禁止:[N]T / [d0,d1]T 等数组形状作键(形状是 value/body 的 langtype,键没有 body);元组键元素必须全是标量;键含维度([.])非法。
逐字铁律照旧:访问键必须等于 formatter(key value) 的输出逐字文本,kvspace 与 kvlangruntime 均不得归一化/加壳。
影响面
- spec:03-类型系统/07(文法与合法性)、03/14(map 容器)、03/15(成员访问)、附录/03(类型表达式文法)。
- 实现:layout
valid_key / expand_atom(实测已按此行为,需把规则与诊断串写准,现在报的是笼统的 invalid langtype);runtime 成员解析(base·<key 文本> 逐字寻址)。
- 锚例:
tutorial/10-types/05-tuple-key.kv、tutorial/04-ndarray/geo_coord.kv;建议按上表 4 例补一条"裸标量键 vs 一元元组键 vs 拒绝形状键"的锚例。
验收
- spec 把 key 侧写成
memitemkey_langtype_formatter 并在正文解释上面两组对比(int32 vs [int32]、[2]int32 vs [int32,int32])。
- 四条用例:两条通过、两条按 formatter 规则拒绝,附 err 文案(不要只报
invalid langtype)。
- 三后端 tutorial 不回归。
背景(spec 已定,本条求把 key 侧写准)
map 结构现有 spec 写法:
更准确的定义是:
即 memitemkey 不是"一个值类型",而是一个"把 key 值格式化成路径段字符串的格式器"——因为 memitemkey 永远活在路径系统里(
memhead·<key 文本>),从不进入任何 XValue 的 body。key 侧压根没有 body 可承载类型,key 的类型完全是字符串层面的事,故必须由 formatter 规定"什么值的 key 格式化成什么字面量文本"。现象(实测
kvlanglayout vet)a:int32·int32 = {}+a·200 = 7a·200)a:[int32]·int32 = {}+a·[200] = 7a·[200])b:[2]int32·[]char/utf8 = {}error: invalid langtype "[2]int32·[]char/utf8" on container literal target "b"b2:[int32,int32]·[]char/utf8 = {}+b2·[1,2] = "x"b2·[1,2])spec 03-类型系统/07 的非法例也含:
[.]·int64(map 键含维度)、[foo,int32]·int64(元组键含非标量)。为什么:
[2]float32与[float64,float64]是两回事[2]float32:数组形状(dims + 元素种类),描述"一段连续打包进 body 的等宽元素"——属于 value 的 langtype。做键时它描述不了路径段文本,故非法。[float64,float64]:标量元组键,描述"一个由 2 个标量组成的 key 值",formatter 产出[3.252,235124.23]——只约束真实的 key 文本,没有 body 含义。同一道理,
a:int32·int32与a:[int32]·int32是两个不同的 formatter(裸标量a·200vs 一元元组a·[200]),按逐字铁律不得互相转换。建议的 spec 措辞(三选一 key + formatter 输出即访问键)
bool+ 十个定宽数字种类)b·200[scalar,…][v0,v1,…](逗号分隔、无空格)a·[3.252,235124.23][]char/<编码>m·a/kv·set(m,"a",v)禁止:
[N]T/[d0,d1]T等数组形状作键(形状是 value/body 的 langtype,键没有 body);元组键元素必须全是标量;键含维度([.])非法。逐字铁律照旧:访问键必须等于
formatter(key value)的输出逐字文本,kvspace 与 kvlangruntime 均不得归一化/加壳。影响面
valid_key/expand_atom(实测已按此行为,需把规则与诊断串写准,现在报的是笼统的invalid langtype);runtime 成员解析(base·<key 文本>逐字寻址)。tutorial/10-types/05-tuple-key.kv、tutorial/04-ndarray/geo_coord.kv;建议按上表 4 例补一条"裸标量键 vs 一元元组键 vs 拒绝形状键"的锚例。验收
memitemkey_langtype_formatter并在正文解释上面两组对比(int32vs[int32]、[2]int32vs[int32,int32])。invalid langtype)。