改变世界的编程语言MoonBit:项目文件详解

大家好,我是 MoonBit 使用者,也是 MoonBit 布道师,我的个人网站是 https://chensuiyi.me
这是我的 《改变世界的编程语言MoonBit》 系列文章,将自己学习和理解 MoonBit 的过程分享给大家,希望能带来参考和帮助。
全部文章可以前往 MoonBit 开发网 https://moonbit.edgeone.apphttps://moonbit.pages.dev 查看,我坚信,MoonBit 将会改变世界。


上一篇文章 👉改变世界的编程语言 MoonBit:背景知识速览

很多编程语言入门教程,一开始都会教你这个编程语言的语法细节,我觉得这会让我们过早地进入细节而不知全貌。

正所谓一叶障目,不见泰山。如果一开始就林中行走,很难对这门语言产生一个更直观,更整体的印象,我们要登高望远,要横看成岭侧成峰,要远近高低各不同。

所以本文呢,来讲一讲,MoonBit的目录架构

语言文件

MoonBit 语言的专属语言扩展名是 .mbt,可能有人会疑惑为什么不是 .mb?这里我没有找到官方的相关说明,根据我的猜测,.mb 这种二字目扩展名基本已经被很多软件或项目使用了,所以把 MoonBiT 中的 3 个大写字母提取出来作为扩展名,可以有效地防止扩展名歧义和冲突。

测试文件

测试 是保证一个项目,文件,功能,代码的正确性,可用性,维护性的重要环节,在 MoonBit 中,专门为 测试 系统进行了 人性化 的设计。

mbt 复制代码
test "test_name" {
  assert_eq(1 + 1, 2)
  assert_eq(2 + 2, 4)
  inspect([1, 2, 3], content="[1, 2, 3]")
}

除了可以在 .mbt 文件中写 测试块 之外,还提供了 黑盒测试白盒测试

只能访问包中公开成员的测试称为 黑盒测试,能够访问包中所有成员的测试称为 白盒测试,二者都提供了单独的文件来编写和管理测试用例。

黑盒测试的文件扩展名以 _test.mbt 结尾,白盒测试的文件扩展名以 _wbtest.mbt 结尾。

包管理

不管你是前端还是后端,是 JavaScript、Java、Go、Rust 还是 PHP 或 Python,一个现代化的语言,包管理 功能是基础的,也是必备的。

以下是编程语言的包管理机制:

  • JavaScript :npm / yarn / pnpm → package.json
  • Java :Maven / Gradle → pom.xml
  • Go :Go Modules → go.mod
  • Rust :Cargo → Cargo.toml
  • Python :pip / pipenv / poetry → requirements.txt
  • PHP :Composer → composer.json

所以 MoonBit 的包管理是什么呢?那就是 moonmoon.mod.jsonmoon.pkg.json

与 JavaScript 的 npm 一样,moon 不仅承载了包管理的功能,还包括了发布,安装,管理,编译,运行,查看等一系列功能。

模块

一个 项目 对应一个 模块,一个 模块 对应一个 moon.mod.json 文件。

moon.mod.json 文件位于项目的根目录,可以看成是现代前端开发中的 package.json 文件。

一个模块是由 1 个或多个 组成的,每个 moon.pkg.json 文件进行标识和定义。

项目结构

mbt 复制代码
my_project
├── Agents.md
├── cmd
│   └── main
│       ├── main.mbt
│       └── moon.pkg.json
├── LICENSE
├── moon.mod.json
├── moon.pkg.json
├── my_project_test.mbt
├── my_project.mbt
├── README.mbt.md
└── README.md -> README.mbt.md

MoonBit 的项目组织方式与其他语言稍有不同,如上,是通过 moon new 创建的一个新项目,常见的 LICENSEREADME.md 自不必多说,分别是 许可协议项目说明书

README.mbt.md 则是 MoonBit 独有的文件,可以理解为 可编程的说明书,也就是说在 README.mbt.md 文件中写的 MoonBit 代码,与在 .mbt 文件中写代码是没有区别的,照样可以做到编译器的语法校验,提示,修复等。

那么 my_project.mbtmy_project_test.mbt 呢,则是根据项目名称 my_project 默认创建的 同名 语言文件。

模块配置文件 moon.mod.json 的内容如下,chensiuyi 是我们的用户名,my_project 是项目 (模块) 名,用这 2 个名称,可以唯一标识一个项目或模块。

json 复制代码
{
    "name": "chensuiyi/my_project",
    "version": "0.1.0",
    "readme": "README.md",
    "repository": "",
    "license": "Apache-2.0",
    "keywords": [],
    "description": ""
}

所以,我们在说到 的时候,一般是要带上 模块前缀 的,比如根目录下的 moon.pkg.json 则是 chensuiyi/my_project 包。

cmd/main 目录下的 moon.pkg.json,则是 chensuiyi/my_project/cmd/main 包。

所以以上项目一共有 2 个 ,分别是 chensuiyi/my_project 包和 chensuiyi/my_project/cmd/main 包。

chensuiyi/my_project/cmd/main 包是我们的主包,其 moon.pkg.json 文件内容如下:

json 复制代码
{
    "is-main": true,
    "import": [
        {
            "path": "chensuiyi/my_project",
            "alias": "lib"
        }
    ]
}

主包用 is-main 字段为 true 来标记,表示这个包是 moon run 指令的入口,同时也是 moon build 的入口,一个项目可以有 0个多个 主包。

import 则是包与包之间的互相依赖,如上配置,主包 chensuiyi/my_project/cmd/main 依赖了 chensuiyi/my_project 包,并为其设置别名为 lib

凡是有 moon.pkg.json 文件的目录都是 ,而根目录下的 moon.pkg.json 文件则是一个空文件,默认内容只有一个大括号 {} (更多配置后文详解),表示是一个普通包。

项目架构的哲学

mbt 复制代码
my_project
├── Agents.md
├── cmd
│   └── main1
│       ├── main.mbt
│       └── moon.pkg.json
│   └── main2
│       ├── main.mbt
│       └── moon.pkg.json
├── math
│   ├── plus.mbt
│   └── moon.pkg.json
├── LICENSE
├── moon.mod.json
├── moon.pkg.json
├── my_project_test.mbt
├── my_project.mbt
├── README.mbt.md
└── README.md -> README.mbt.md

按照我的个人的理解来说,本文的 项目结构 部分还不足以说明 MoonBit 的架构哲学,所以我把 项目结构 进行了如上扩展。

那么先问个问题,以上有几个 ?答案是 4个,很简单,有几个 moon.pkg.json 就有几个 ,就是如此简单。

根目录下的 moon.pkg.jsoncmdmath 目录下的 moon.pkg.json 没有区别,就像是一个班级的学生,大家都是平等的

is-main 配置为 truefalse 则表明了这个学生的是否有职务,为 true 则在普通包的基础上,有了 主包入口职务

所以当我们执行 moon build --target all 命令的时候,就会生成上图中的 jsnative(exe)wasmwasm-gc 4 种编译结果 (llvm目前还不稳定,只在nightly版本下生成),每个编译结果都有 main1main2 两个文件,与我们上面的配置一致。

如果你写过 go 语言,会发现在 go 约定成俗的规范中,cmd 目录就是应用程序的主入口目录,也是用于生成二进制的目录,所以写过 go 的小伙伴对这个 哲学 应该不会陌生。

内部包

mbt 复制代码
my_project
├── Agents.md
├── cmd
│   └── main1
│       └── internal
│           └── math
│               ├── minus.mbt
│               └── moon.pkg.json
│       ├── main.mbt
│       └── moon.pkg.json
│   └── main2
│       ├── main.mbt
│       └── moon.pkg.json
├── math
│   ├── plus.mbt
│   └── moon.pkg.json
├── LICENSE
├── moon.mod.json
├── moon.pkg.json
├── my_project_test.mbt
├── my_project.mbt
├── README.mbt.md
└── README.md -> README.mbt.md

如果你想创建一个包,但是只能被 main1 包使用,那可以在 main1 目录下创建一个 internal 目录,那么这个目录下的包就只能被 main1 及其子目录使用。

虚拟包

虚拟包是一个实验性功能,可能存在错误和未定义的行为。

json 复制代码
{
    "virtual": {
        "has-default": true
    }
}

moon.pkg.json 文件中,有定义 virtual 字段的,就是 虚拟包

顾名思义,虚拟包就是对 实现的定义,而不是 具体的实现,它们可以在构建时被特定的实现替换。

目前,虚拟包只能包含普通函数。虚拟包在保持代码不变的情况下,可以在不同的实现之间进行切换。

发布包

MoonBit 的中文名称叫做 月兔,每个模块称之为 月饼,放月饼的仓库就是 https://mooncakes.io

所有人都可以发布自己的 月饼 到仓库中,被其他人依赖并使用。

结尾

这就是 MoonBit 目录,文件 的架构 哲学,带大家飞到天上总览全局,有一个大概的轮廓和印象。

下一篇 改变世界的编程语言MoonBit:搞懂配置文件,我们不见不散。

相关推荐
AI绘画哇哒哒6 小时前
【值得收藏】手把手教你用PyTorch构建Transformer英汉翻译系统,从训练到推理
人工智能·pytorch·ai·语言模型·程序员·大模型·transformer
用户6120414922136 小时前
C语言做的城市天气数据管理与统计
c语言·后端·敏捷开发
拜无忧6 小时前
three.js纸飞机飞行撞建筑
前端·three.js
ursazoo6 小时前
记一次线上API调用失败的排查过程:从405到时间同步
后端
无光末阳6 小时前
前端 vue3+router 比较好用的自定义日志插件
前端·vue.js
聪明墨菲特6 小时前
HttpClient工具类优化实践:提升性能与可维护性
后端·设计模式
liercats6 小时前
ECharts图表正常但动画不显示?问题排查指南:大概率是宽高问题
前端
Java中文社群6 小时前
面试官:如何提升项目并发性能?
java·后端·面试
摸鱼的鱼lv7 小时前
sonarQube全流程实战:从VSCode开发到CI/CD质量门禁
前端