33个版本 (6个破坏性更新)

0.9.1 2024年7月3日
0.8.25 2024年6月27日
0.7.3 2024年3月22日

#38编程语言

Download history 112/week @ 2024-04-25 22/week @ 2024-05-02 6/week @ 2024-05-16 6/week @ 2024-05-23 106/week @ 2024-06-06 582/week @ 2024-06-13 1105/week @ 2024-06-20 562/week @ 2024-06-27 277/week @ 2024-07-04 5/week @ 2024-07-11 292/week @ 2024-07-25 52/week @ 2024-08-01

每月344次下载

MIT/Apache

1MB
9K SLoC

mers

cargo install mers

Mers是一种简单、安全的编程语言。

特性

  • mers的语法简单、简洁
  • mers是类型检查的,但行为几乎像动态类型语言
  • 没有null或异常
  • mers中的引用是显式的:&var 与仅 var
  • 没有 goto (或 breakreturn)
  • 锁定(对多线程很有用,任何引用都可以被锁定)

示例

你好,世界!

image

在mers中,.function 是用于调用函数的语法。在 . 之前的是函数的参数。在这种情况下,我们的参数是包含 你好,世界! 的字符串。

变量

image

我们使用 name := value 来声明一个变量,在这种情况下是 my_var。然后我们可以在需要使用其值时简单地写出 my_var

如果

image

if 用于条件执行代码。显然,由于我们的条件始终是 true,我们的代码将始终运行。

if 中的条件必须是 bool,否则...

image

否则

image

我们可以在 if 后直接添加 else。这是当条件为 false 时将运行的代码。

使用If-Else生成值

根据你习惯的语言,你可能想写这样

var result
if (condition) {
  result = "Yay"
} else {
  result = "Nay"
}

但在mers中,一个 if-else 可以轻松生成值

image

我们可以通过编写来进一步缩短

image

如果分支没有相同的类型怎么办?

Rust还允许我们通过 if-else 构造返回值,只要它们的类型相同

if true {
  "Yep"
} else {
  "Nay"
}

但是,当我们混合两种不同类型时,它就不再能编译了

if true {
  "Yep"
} else {
  5 // Error!
}

在mers中,这并不是一个问题

image

变量 result 被简单分配了类型 String/Int,因此mers总是知道它必须是这两个中的一个。

如果我们添加一个类型注解,我们就能看到这一点

image

显然,if-else 并不总是返回一个 Int,这就是我们得到错误的原因。

使用If而不使用Else来产生一个值

如果没有 else 分支,mers显然必须显示错误

image

或者你以为如此...但是不,mers并不在乎。如果条件为假,它就会退回到一个空元组 ()

image

数字之和

image

其他东西的总和?

如果我们的 numbers 元组中的所有元素实际上不是数字,这将不会起作用。相反,我们会得到一个类型错误

image

循环

image

这个程序会要求用户输入一个数字。如果他们输入一个有效的数字,它就会打印那个数字。如果他们没有输入一个有效的数字,他们就会被再次要求。

这是因为 parse_float 返回 ()/(Float),这与mers中循环的工作方式相吻合

一个 loop 会执行代码。如果是 (),它就会再次执行。如果是 (v),循环停止并返回 v

image

有了这个,我们可以无限循环

image

我们可以实现一个while循环

image

或者一个for循环

image

else (()) 告诉mers在条件返回 false 时退出循环并返回 ()

函数

函数以 arg -> something 的形式表达,其中 arg 是函数的参数,而 something 是函数应该做什么。通常方便将函数分配给变量,这样我们就可以轻松使用它

image

由于函数只是普通值,我们可以将它们传递给其他函数,也可以从其他函数返回它们

image

在这里,do_twice 是一个函数,它接受一个函数并返回一个新的函数,该函数执行原始函数两次。所以,add_one.do_twice 成为一个新函数,它可以写成 x -> x.add_one.add_one

当然,这根本不会损害类型安全

image

Mers告诉我们,我们不能用 String 调用 add_two,因为这将调用在 do_twice 中定义的 func,并且这个 funcadd_one,然后它会调用 sum 并将那个 String 和一个 Int 一起传递,这是不可行的。

错误可能有点长,但它告诉我们出了什么问题。我们可以通过给我们的函数添加一些类型注解来使其更明显。

image

高级变量

在mers中,我们可以声明具有相同名称的两个变量

image

只要第二个变量在作用域内,我们就无法再访问第一个变量,因为它们具有相同的名称。这不同于给x赋新值

image

第二个x仅在由代码块({)创建的作用域内存在,所以,在其结束时(}),x又指向原始变量,其值未改变。

要给原始的x赋新值,我们必须写成&x =

image

引用

写入&var返回对var的引用。然后我们可以将该引用赋值

image

...

image

在这里,我们实际上并没有给ref赋值,我们是在给ref所引用的变量赋值。这之所以有效,是因为等号左侧不需要是&var。只要它返回一个引用,我们就可以给那个引用赋值

这被例如get_mut函数所使用

image

在这里,我们将列表(&list)的引用和索引0传递给get_mut。然后get_mut返回一个()/(&{Int/String}) - 要么没有(如果索引超出范围)或对列表中元素的引用,一个Int/String。如果是引用,我们可以给它赋新值,这将改变列表。

多线程

(...)


注意:所有图片都是运行clear; mers pretty-print file main.mers && echo $'\e[1;35m输出:\e[0m' && mers run file main.mers后的Alacritty截图。

依赖项

~1–11MB
~76K SLoC