木兰重生:与 Python 生态的兼容问题;字符串插值

2020年10月08日

本项目旨在重现「木兰」编程语言的语法和功能,已开源在码云。所有例程演示的语法可用原始的木兰可执行文件 ulang-0.2.2.exe 检验。如发现有异烦请告知,定将礼谢

前两天用木兰调用 pygame 库实现了个井字棋棋盘界面。期间遇到了一些问题,先小结一下。

1 生态兼容问题

注:解决方法限于个人至今对木兰和 Python 的了解。如有高招,烦请指教!

1.1 元组 (tuple)

python 中很常用的结构,可以如下初始化:

>>> t = (1,2)
>>> t
(1, 2)
>>> t = 2, 3
>>> t
(2, 3) 

但木兰中好像没找到类似的简便方法。幸好与 python 相似,函数返回多项时就会打包成元组,因此暂时这样定义函数:

func 多项2(a, b) {
  return a, b
}
func 多项3(a, b, c) {
  return a, b, c
}
...

之后支持变长参数时,就可以合并为一个函数了。

1.2 如何引用 type 属性

下面是 pygame 的常见操作,检查 pygame.event 的 type:

			for event in pygame.event.get():
				if event.type == pygame.QUIT :

但木兰中的 type 是类型定义的关键词,因而如果仍使用 .type 会报错。刚遇到这一问题时,颇为震惊,以为发现了木兰的一个大硬伤,不过还好 python 还有一个__getattribute__('type')可用。另一种方法用在这里就无法获得 type 值:

func getType(个体) {
  for 属性, 值 in 个体.__dict__.items() {
   return 值 if 属性 == 'type'
  }
}

大概因为这个 type 是个 @property(木兰中的应变属性),如果是普通属性如下:

type 人 {
    func $人(名) {
        $type = 名
    }
}

上面两种方法就都可用。

1.3 键 in 字典

python 中判断字典是否包含某键,推荐使用“键 in 字典”,集合也类似。木兰中的 in 关键词并不支持这种操作,也没找到其他语法支持。现在只找到调用__contains__()这一方式。。

2 本周重现功能:字符串插值

python 的字符串插值功能比如“f'{行号}.0'”可以简化字符串拼接。这几天重现了木兰的类似功能,如下对比,比拼接方式简洁不少:

"[" + $词性 + " 行:" + str($行) + " 列:" + str($起) + "~" + str($止) + "], 内容: " + $内容  // 拼接

"[`$词性` 行:`$行` 列:`$起`~`$止`], 内容: `$内容`"  // 插值

除了"`表达式`"格式,木兰还支持“\(表达式\)”格式。至于为何支持两种格式,暂时想到的一种使用场景是带有“`”字符的字符串插值,比如 “`a某变量b”,那么“某变量”就可以用“\(\)”:

a = 3
print("`a\(a\)a") => `a3a
print("`a`a`a") => 3a`a 

这有个实现细节的困惑。在插值的语法树节点创建时,使用的是 ast.Mod() 运算符。但这不是求余操作么?这个 Mod 有详细说明文档吗?


附录:代码量统计

主要部分的代码行数统计,格式为:上次->现在。

  • 木兰代码量
    • 编辑器,实现与测试都是木兰代码:333
    • 木兰测试用例,包括部分实用小程序:2160

 

  • Python 代码量(包括测试部分):2396 -> 2425
    • 分析器/语法分析器.py:958 -> 986
    • 分析器/词法分析器.py:198
    • 测试/运行所有.py,检验所有木兰测试代码片段:185
    • 环境.py,定义全局方法:157
    • 分析器/语法成分.py,从语法分析器中提取出来的枚举常量:79
    • 未变
      • 分析器/语法树.py:178
      • 交互.py,交互环境(REPL):138
      • 功用/反馈信息.py:49
      • 中.py,主程序:41
      • 分析器/错误.py:17
      • 测试/unittest/语法树.py,确保生成的语法树与原始版本一致:67
      • 测试/unittest/交互.py,交互环境相关测试:28
展开阅读全文
0 收藏
分享
加载中
精彩评论
靠,我也发现了,怎么天天这useless的玩意?
2020-10-08 11:02
18
举报
神烦
2020-10-08 10:56
14
举报
如何屏蔽这玩意。。。不好使还喷网友
2020-10-08 14:18
11
举报
又来?
2020-10-08 12:49
7
举报
@吴烜2020 别恶心人了好嘛
2020-10-08 15:48
6
举报
最新评论 (38)
欢迎使用 Useless 语言,来自于没啥用科技。
2020-10-10 09:12
1
回复
举报
骗经费的项目,看到这种新闻都反胃
2020-10-09 12:31
0
回复
举报
这个作者自己实现着玩的,和你说的没什么关系
2020-10-09 21:09
0
回复
举报
这到底是在干啥
2020-10-09 08:08
0
回复
举报
求模就是求余,一个对整数,一个对数值。“in”应该是包装迭代器,属于语句变换,得在解析时做。如果只是查键,可以直接用函数替代。“type”大概是设计理念上的差别,得看源码。元组,没看明白。难道要支持函数返回变参?元组长度不同,就是不同类型的元组,怎么能当同一种类型返回。
2020-10-08 21:42
0
回复
举报
2020-10-11 01:09
0
回复
举报
上面链接看 671 行(不知啥词又敏感了只能分开写)
2020-10-11 01:10
0
回复
举报
2. python 的 in 对应的语法树运算是 cmpop 的 In,但木兰中没看到创建 In 语法树节点,因此判断没有对应语法
2020-10-11 01:11
0
回复
举报
3. 木兰用‘type’关键词的缘由暂不明确,也许它的含义(相对 class)对新手来说更易于理解吧。这个在调用 python 库中带 type 属性的 API 是一个比较少见但必须有解决方案的场景,现在这种方式倒是够用了。
4. 刚试了好像木兰不支持函数返回变参(待再次确认)。也许之前指望合并为一个函数是想当然了。。。
2020-10-11 01:11
0
回复
举报
按“781 运算符=ast.Mult()”的,"运算符=ast.Mod()"应该是用的符号和MOD是一样的。
2020-10-11 11:53
0
回复
举报
嗯,我不明白的是为何 ast.Mod 这个运算符能作用于字符串,因为明显不是“求余”的意思。搜到有类似源码,像这个:form = ast.BinOp(expl_expr, ast.Mod(), format_dict) 但还没找到它的说明文档
2020-10-11 18:22
0
回复
举报
是在“执行插值”函数的返回的语法树,不是对字符串,应该是对右树的。大概是为“右树中所有插值”进行分组的。
2020-10-12 12:32
0
回复
举报
它是一个二元运算,左树是字符串 (ast.Str),右树是多项(ast.Tuple)。猜测是个插值运算(回头试试 python 下的字符串插值是不是同样 ast),好奇的是它为何和求余操作同名。
2020-10-12 16:43
0
回复
举报
回复 @吴烜2020 : 就是这样设定的。我搜了一下,Python通过(%)操作符拼接的。
2020-10-13 11:58
0
回复
举报
回复 @dwcz : 可否移步此 issue 继续讨论?https://gitee.com/MulanRevive/mulan-rework/issues/I1Y286 可否给个链接或者用%操作符拼接字符串的 python 例程?
2020-10-13 13:21
0
回复
举报
生活不如意吗,靠这个恰💰?
2020-10-08 21:36
0
回复
举报
虽然你脸皮厚大家都已经知道,但是这样子大家的确是没想到。这个语言有什么东西,摆明欺负大家智商
2020-10-08 21:17
0
回复
举报
希望提供踩的功能。
2020-10-08 19:31
0
回复
举报
支持!精神可嘉
2020-10-08 18:37
1
回复
举报
感谢。
2020-10-11 00:50
0
回复
举报
怎么屏蔽资讯@红薯
2020-10-08 18:22
0
回复
举报
更多评论
38 评论
0 收藏
分享
返回顶部
顶部