Skip to content

模块与导入 ​

一个文件就是一个模块 ​

每个 .cp 文件就是一个模块,不需要声明模块名。模块之间通过 daochu(导出 / export)和 daoru(导入 / import)共享函数。

导出 ​

函数默认只在本文件里可见。加上 daochu,其他文件才能导入:

cpro
// util.cp
daochu hs double(x z64) z64 { fanhui x * 2 }    // 对外可见
hs helper(x z64) z64 { fanhui x + 1 }           // 只在本文件可见
cpro
// util.cp
导出 函数 double(x i64) i64 { 返回 x * 2 }      // 对外可见
函数 helper(x i64) i64 { 返回 x + 1 }           // 只在本文件可见
cpro
// util.cp
export fn double(x i64) i64 { return x * 2 }    // 对外可见
fn helper(x i64) i64 { return x + 1 }           // 只在本文件可见
  • 只有函数能跨文件使用,模块级变量不能导出
  • 结构体不能导出,但可以导出返回结构体的函数,调用方用变量接住即可

导入 ​

导入本地文件 ​

按名字导入,用 laizi(来自 / from)指定文件,导入后直接用函数名调用:

cpro
daoru { double } laizi "./util.cp"

rukou() {
    dayin(double(21))       // 42
}
cpro
导入 { double } 来自 "./util.cp"

入口() {
    打印(double(21))        // 42
}
cpro
import { double } from "./util.cp"

rukou() {
    print(double(21))       // 42
}

整个文件导入,之后用 文件名.函数名 调用:

cpro
daoru "./util.cp"

rukou() {
    dayin(util.double(21))  // 42
}
cpro
导入 "./util.cp"

入口() {
    打印(util.double(21))   // 42
}
cpro
import "./util.cp"

rukou() {
    print(util.double(21))  // 42
}
  • 路径相对当前文件所在目录,必须以 ./ 或 ../ 开头,必须带 .cp 扩展名
  • 路径分隔符一律用 /,Windows 上也一样
  • 文件名大小写必须和磁盘上完全一致

起别名 ​

两个文件有同名函数时,用 zuowei(作为 / as)改名:

cpro
daoru { open zuowei open_file } laizi "./file.cp"
daoru { open zuowei open_conn } laizi "./conn.cp"
cpro
导入 { open 作为 open_file } 来自 "./file.cp"
导入 { open 作为 open_conn } 来自 "./conn.cp"
cpro
import { open as open_file } from "./file.cp"
import { open as open_conn } from "./conn.cp"

导入标准库 ​

标准库只能整个导入,然后用 模块名.函数名 调用:

cpro
daoru "io"

rukou() {
    io.cuowu_dayin("写到标准错误")
}
cpro
导入 "io"

入口() {
    io.eprint("写到标准错误")
}
cpro
import "io"

rukou() {
    io.eprint("写到标准错误")
}

写成 daoru { eprint } laizi "io" 会报错。

字符串模块不需要导入,直接用。部分标准库模块有拼音名,导入时用哪个名字,调用时就用哪个:

拼音英文
zifuchuanstring
huanjingenv
wenjianfs
wangluonet
—io
—http
cpro
daoru "wenjian"         // 之后写 wenjian.xxx(...),不能写 fs.xxx(...)
cpro
导入 "wenjian"          // 之后写 wenjian.xxx(...),不能写 fs.xxx(...)
cpro
import "wenjian"        // 之后写 wenjian.xxx(...),不能写 fs.xxx(...)

标准库模块名(包括拼音名)是保留的,不能用作变量名、函数名,本地文件也不能叫 io.cp 这样的名字。

导入第三方包 ​

第三方包写全名 发布者/包名,只能按名字导入:

cpro
daoru { add } laizi "zhangsan/math"
cpro
导入 { add } 来自 "zhangsan/math"
cpro
import { add } from "zhangsan/math"

包要先在 cpro.json 里声明并安装,见 使用第三方包。只有自己清单里声明的包才能导入,即使磁盘上装着别的包也不行。

转发导出 ​

daoru 进来的函数默认只在本文件可用。要让它也从本文件对外导出,写 daochu daoru:

cpro
// api.cp
daoru { helper } laizi "./internal.cp"                           // 仅本文件可用
daochu daoru { double, double zuowei fanbei } laizi "./util.cp"  // 对外可见
cpro
// api.cp
导入 { helper } 来自 "./internal.cp"                          // 仅本文件可用
导出 导入 { double, double 作为 fanbei } 来自 "./util.cp"     // 对外可见
cpro
// api.cp
import { helper } from "./internal.cp"                        // 仅本文件可用
export import { double, double as fanbei } from "./util.cp"   // 对外可见

这样可以做一个"门面"文件,把分散在多个文件里的函数集中对外提供。转发要每一层都写 daochu daoru,不会自动往外传。

访问边界 ​

  • 不能直接导入标准库的内部文件,只能通过 daoru "模块名" 使用
  • 不能用相对路径导入第三方包里的文件,只能按名字导入它公开的函数
  • 第三方包不能用相对路径导入包外的文件

规则汇总 ​

写法结果
daoru { f } laizi "./a.cp"✓ 本地文件,按名字导入
daoru "./a.cp"✓ 本地文件,整个导入,之后 a.f()
daoru "io"✓ 标准库,之后 io.f()
daoru { f } laizi "io"✗ 标准库不能按名字导入
daoru { f } laizi "zhangsan/pkg"✓ 第三方包
daoru "zhangsan/pkg"✗ 第三方包不能整个导入
daoru { f } laizi "a.cp"✗ 相对路径要以 ./ 开头
daoru { f } laizi "./a"✗ 要带 .cp 扩展名
导入没有 daochu 的函数✗

cpro 目前处于测试阶段