改变世界的编程语言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:搞懂配置文件,我们不见不散。

相关推荐
2401_863801461 小时前
探索 12 种 3D 文件格式:综合指南
前端·3d
callJJ2 小时前
从 0 开始理解 Spring 的核心思想 —— IoC 和 DI(2)
java·开发语言·后端·spring·ioc·di
珍宝商店3 小时前
前端老旧项目全面性能优化指南与面试攻略
前端·面试·性能优化
bitbitDown3 小时前
四年前端分享给你的高效开发工具库
前端·javascript·vue.js
gnip4 小时前
实现AI对话光标跟随效果
前端·javascript
你的人类朋友4 小时前
JWT的组成
后端
脑花儿5 小时前
ABAP SMW0下载Excel模板并填充&&剪切板方式粘贴
java·前端·数据库
北风朝向5 小时前
Spring Boot参数校验8大坑与生产级避坑指南
java·spring boot·后端·spring
canonical_entropy5 小时前
一份关于“可逆计算”的认知解码:从技术细节到哲学思辨的完整指南
后端·低代码·deepseek
lumi.6 小时前
Vue.js 从入门到实践1:环境搭建、数据绑定与条件渲染
前端·javascript·vue.js