普贤教程 › 生态包
并发容器与数值
四个包,四种「容器与数值」的基础设施:concurrent_map 带锁映射(必须编译)、datastruct 堆/队列/LRU、dist 随机分布、fractions 精确有理数。它们的共同点是都有函数在当前版本里跑不通,逐个写明。
concurrent_map:必须编译,且两个函数是坏的
px
import concurrent_map var m = cm_new() cm_set(m, "a", 1) cm_set(m, "b", 2) print(cm_len(m), cm_get(m, "a"), cm_get(m, "z", 0)) # 2 1 0 print(str(cm_keys(m)), cm_has(m, "b")) # [a, b] true cm_delete(m, "a") print(cm_len(m), str(cm_keys(m))) # 1 [b]
text
2 1 0 [a, b] true 1 [b]
解释轨直接拒绝
px run 跑这个包会在 cm_new() 处终止:R1002: interp 不支持 mutex(Mini 子集排除)。
它是编译期专用:px build 出二进制再跑。用 px run 试包,会误判成「包坏了」。cm_values 与 cm_to_string 恒崩结构体实际键名是
"m"(cm_new() = {"m": {}, "mu": mutex()}),但这两个函数读的是
m["data"]:R1008: 字典没有键 'data'。取所有值请自己 for k in cm_keys(m): cm_get(m, k)。datastruct:堆、队列、LRU
px
import datastruct var h = ds_heap_new() ds_heap_push(h, 3, "c") ds_heap_push(h, 1, "a") ds_heap_push(h, 2, "b") print(ds_heap_peek(h), ds_heap_size(h)) # Ok(a) 3 print(ds_heap_pop(h), ds_heap_pop(h), ds_heap_pop(h)) # Ok(a) Ok(b) Ok(c)
text
Ok(a) 3
Ok(a) Ok(b) Ok(c)最小堆,pop 返 Result;空堆取是 Err 不是 null。
px
var c = ds_lru_new(2) ds_lru_set(c, "a", 1) ds_lru_set(c, "b", 2) ds_lru_get(c, "a") # 触碰 a,b 变成最久未用 ds_lru_set(c, "c", 3) # 容量 2 → 淘汰 b print(ds_lru_has(c, "a"), ds_lru_has(c, "b")) # true false
text
true false
另有 ds_queue_*(FIFO)、ds_stack_*(LIFO)、ds_deque_*,pop 一律返 Result、len 返 int。
dist:随机分布,两个函数用不了
px
import dist print(di_uniform(1, 3)) # 1.806187200134066 print(di_randint(1, 6)) # 4 print(di_normal(0, 1)) # Ok(0.0035649755742717427) print(di_bernoulli(0.5)) # Ok(0) print(di_poisson(3)) # Ok(3) print(di_bernoulli_mean(0.3), di_poisson_mean(3), di_poisson_var(3)) # 0.3 3 3 print(di_choice(["a","b","c"]).ok()) # a
两个函数恒崩,都在「应该很好用」的位置
①
②
要可复现的随机数,用内建
①
di_seed(42) → R1001: 未定义变量: 'srand'——包里调了不存在的内建,无法设种子,也就无法复现随机序列;②
di_normal_cdf(x, mean, sd) → R1001: 未定义变量: 'erf'——正态 CDF 依赖的 erf 语言里没有。要可复现的随机数,用内建
random_int(n)(0..n-1)自己搭。返回值形态:di_uniform / di_randint 直接给数值;di_normal / di_exponential / di_bernoulli / di_poisson / di_choice / di_shuffle 给 Result。同一个包里两种形态并存,用前先看一个 .is_ok() 试探。
fractions:精确有理数,但每步都要 .ok()
px
import fractions var a = frac(1, 3).ok() var b = frac(1, 6).ok() print(frac_to_str(a), frac_to_str(b)) # 1/3 1/6 print(frac_to_str(frac_add(a, b).ok())) # 1/2 print(frac_to_str(frac_mul(a, b).ok())) # 1/18 print(frac_to_str(frac_pow(a, 2).ok())) # 1/9 print(frac_to_float(a)) # 0.3333333333333333 print(frac_to_str(frac(2, 4).ok())) # 1/2(自动约分) print(frac_to_str(frac_from_str("3/4").ok())) # 3/4 print(frac(1, 0).is_err()) # true
text
1/3 1/6 1/2 1/18 1/9 0.3333333333333333 1/2 3/4 true
契约不一致:构造器返 Result,运算器却按 list 取值
frac() 返 Ok([分子, 分母]),但 frac_add(a, b) 内部写的是 a[0] * b[1]——
直接把 Result 传进去就是 R1002: 此类型不支持索引: result。每一步都要 .ok(),
包括 frac_to_str(frac(2,4)) 这种「只算一次」的写法。能力面:frac_add/sub/mul/div/neg/cmp/eq/is_zero/pow/abs/reciprocal/floor/ceil/round/to_float/to_str、frac_gcd。范围是 64 位整数,超了会溢出(要更大用 big)。