Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

默认作用域中的通常函数的实现进展记录 #18

Open
umajho opened this issue Mar 31, 2023 · 4 comments
Open

默认作用域中的通常函数的实现进展记录 #18

umajho opened this issue Mar 31, 2023 · 4 comments

Comments

@umajho
Copy link
Owner

umajho commented Mar 31, 2023

考虑到现在对通常函数的定义方式尚未稳固下来,仍可能会有会导致要修改每处通常函数定义的重构(先前已经过两次),目前刻意压低了实现的通常函数的数量。

运算符

由于解析代码时会单独对待运算符,运算符相比于这里列出的其他通常函数要更加基本。
为体现这种特征,也许可以分出两份默认作用域:第一份只含运算符;第二份延伸自第一份,包含这里提及的所有通常函数。

优先级已在文档中列出,这里不复述。

虽然是运算符,但不是通常函数

实现? 形式 名称 说明 相当于 备注
a |> b(...) 管道 参见 Elixir 等语言对应构造。 b(a, ...)
a # b 反复 反复求值 ab,返回包含那些求值结果的列表。

关键词形式的运算符

实现? 形式 名称 说明 相当于 备注
部分 a or b 逻辑或 a || b 尚未实现短路(参考 #13)。
部分 a and b 逻辑与 a && b 尚未实现短路。
not a 逻辑非 !a

一般的运算符

实现? 形式 名称 说明 相当于 备注
a == ba != b 相等、不等 a === ba !== b 目前只允许整数及整数之间,或者布尔值及布尔值之间进行判断。
部分 a < ba > ba <= b a >= b (略) (与形式相同) 只允许整数之间。应该也允许布尔值之间。
a ~ b~ b 范围内随机 等概率取范围内(包括两侧)的整数,a 默认为 1。 (略)
a + ba - ba * b 加、减、乘 (略)
a // b 整除 (略)
a % b 求余 (略) a 必须是非负数, b 必须是正数。
a ^ b 指数 a ** b
a d bd ba d% bd% b 掷骰 a 默认为 1% 事实上导致结果 -1 (略)

在考虑去掉 d%,毕竟其实质上只是 d… - 1,其存在还可能导致混淆(比如第一眼把 3d%4 看成了 3d%4)。

可以直接用括号调用的

投骰子

实现? 举例 名称 说明 相当于
部分 reroll(3d10, 2)…(3#d10, 2)、`…(…, x -> x <= 2)…(…, ..=2)` 重投
部分 explode(3d10, 8)…(3#d10, 8)、`…(…, x -> x >= 8)…(…, 8..)` 爆炸骰

目前仅实现以闭包作为判断条件。

备注:
表中的 ..=28.. 是设想中(优先级很低)的范围运算符(参见 #8)。最理想的情况下,投掷表达式的概率可以准确算出来,那么就无需暴力投掷,可以直接根据范围运算符产出结果。

不过目前的想法就只是设置执行上限,防止理论或事实上的死循环。

列表实用

实现? 形式 名称 说明 相当于 备注
abs(a) 绝对值 (略)
count(a) 列表长度 a.length
count(a, f) 列表长度 a.filter(f).length
has?(a, b) 列表包含元素? a.indexOf(b) >= 0 名称应该尽量和 Elixir 看齐。另外应该考虑有用闭包查找的版本?
sum(a) 列表求和 (略)
product(a) 列表求积 (略)
min(a) 列表最小 (略)
max(a) 列表最大 (略)
all?(a) 列表全部 是否全部元素为 true a.every((x) => x) 应该考虑用闭包判断的版本。
部分 any?(a) 列表任意 是否任意元素为 true a.some((x) => x) 应该考虑用闭包判断的版本。另外,目前的实现没考虑短路。
sort(a) 列表排序 由小到大排序 a.sort((x, y) => x - y) 这个函数在整数之外还支持布尔值,与比较运算符不一致。那些比较运算符也应该支持布尔值之间的比较。
sort(a, f) 列表排序 由小到大排序 a.sort((x, y) => x - y) 用闭包比较的版本。
reverse(a) 列表翻转 a.reverse()
concat(a, b) 列表拼接 [...a, ...b]
prepend(a, b) 列表首部添加 [b, ...a]
append(a, b) 列表尾部添加 [...a, b]
at(a, b) 列表索引取值 a[b] 越界会导致运行时错误。
at(a, b, c) 列表索引取值 b < a.length ? a[b] : c 越界会导致运行时错误。
duplicate(a, b) 重复 Array(b).fill(a) b 的语义是?如果把 b 固定下来,会导致通常函数间的语义不一致;如果不固定,那除了能被捕获外就和 # 没区别了。
flatten(a, b) 列表扁平化 a.flat(b)
flattenAll(a) 列表完全扁平化 a.flat(Infinity) 名字还没完全定下来。

这方面还有很多可以实现的函数,但目前就打算实现这么多了。

函数式

实现? 形式 名称 说明 相当于 备注
map(a, f)
flatMap(a, f)
filter(a, f)
foldl(a, b, f)
foldr(a, b, f)
unfold(a)
iterate(a)
head(a)
tail(a)
last(a)
init(a)
take(a, b)
takeWhile(a, f)
drop(a, b)
dropWhile(a, f)
zip(a, b)
zipWith(a, b, f)

目前就打算实现这么多。

内部调试

实现? 形式 名称 说明 相当于 备注
抛弃 inspect(a) 观测理所当然会导致观测对象失去惰性。目前实现有问题,打印的和返回的会分别求一次值,并不稳定。

控制流

实现? 形式 名称 说明 相当于 备注
if(a, b, else: c)
@umajho
Copy link
Owner Author

umajho commented Apr 7, 2023

#/2 不能作为通常函数。
在没有涉及到闭包时是否是通常函数没有区别(如 3#d43#(3#d4))。
另一方面,闭包参数会赋予变量名称,导致变量的值固定。
因此像是 3#\(x->x).(d4) 这种表达式,如果将 #/2 处理通常函数,其右侧就会是 d4 一次运算后固定下来的值,最终的结果是重复同一个值三次。
但实际期待的行为是 # 右侧的表达式每次都要重新执行,变量只在闭包内部固定(比如 3#\(x->3#x).(d4),内层数组间的元素相同,外层数组相独立)。

@umajho umajho mentioned this issue Apr 8, 2023
19 tasks
@umajho
Copy link
Owner Author

umajho commented Apr 27, 2023

也许 **/2 作为幂运算符更合适。
那么 ^/2 是作为别名,是像 //2 那样提示使用 **/2,还是干脆不识别?

@umajho
Copy link
Owner Author

umajho commented Jun 27, 2023

  • FIXME: 像是 sum/1 这样的函数没有处理空数组的情况。

@umajho
Copy link
Owner Author

umajho commented Oct 10, 2023

补遗:

  • 笔记中的一些想法 #21 提及但没放过来的的:
    • identity/1id/1
    • shuffle/1
  • 比较基础的:
    • rem/2mod/2。(相比 %/2 允许负数,但两种函数对负数的处理不同。)
  • 衍生:
    • sortDesc/*
    • keepHighest/*keepLowest/*dropHighest/*dropLowest/*
      • 别名,如 [kd][hl]/*
  • 拼接:
    • ++/2。如果以后还有字符串的话:<>/2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant