33个版本 (6个破坏性更新)
0.9.1 | 2024年7月3日 |
---|---|
0.8.25 | 2024年6月27日 |
0.7.3 | 2024年3月22日 |
#38 在 编程语言
每月344次下载
1MB
9K SLoC
mers
cargo install mers
Mers是一种简单、安全的编程语言。
特性
- mers的语法简单、简洁
- mers是类型检查的,但行为几乎像动态类型语言
- 没有null或异常
- mers中的引用是显式的:
&var
与仅var
- 没有
goto
(或break
或return
) - 锁定(对多线程很有用,任何引用都可以被锁定)
示例
你好,世界!
在mers中,.function
是用于调用函数的语法。在 .
之前的是函数的参数。在这种情况下,我们的参数是包含 你好,世界! 的字符串。
变量
我们使用 name := value
来声明一个变量,在这种情况下是 my_var
。然后我们可以在需要使用其值时简单地写出 my_var
。
如果
if
用于条件执行代码。显然,由于我们的条件始终是 true
,我们的代码将始终运行。
if
中的条件必须是 bool,否则...
否则
我们可以在 if
后直接添加 else
。这是当条件为 false
时将运行的代码。
使用If-Else生成值
根据你习惯的语言,你可能想写这样
var result
if (condition) {
result = "Yay"
} else {
result = "Nay"
}
但在mers中,一个 if-else
可以轻松生成值
我们可以通过编写来进一步缩短
如果分支没有相同的类型怎么办?
Rust还允许我们通过 if-else
构造返回值,只要它们的类型相同
if true {
"Yep"
} else {
"Nay"
}
但是,当我们混合两种不同类型时,它就不再能编译了
if true {
"Yep"
} else {
5 // Error!
}
在mers中,这并不是一个问题
变量 result
被简单分配了类型 String/Int
,因此mers总是知道它必须是这两个中的一个。
如果我们添加一个类型注解,我们就能看到这一点
显然,if-else
并不总是返回一个 Int
,这就是我们得到错误的原因。
使用If而不使用Else来产生一个值
如果没有 else
分支,mers显然必须显示错误
或者你以为如此...但是不,mers并不在乎。如果条件为假,它就会退回到一个空元组 ()
数字之和
其他东西的总和?
如果我们的 numbers
元组中的所有元素实际上不是数字,这将不会起作用。相反,我们会得到一个类型错误
循环
这个程序会要求用户输入一个数字。如果他们输入一个有效的数字,它就会打印那个数字。如果他们没有输入一个有效的数字,他们就会被再次要求。
这是因为 parse_float
返回 ()/(Float)
,这与mers中循环的工作方式相吻合
一个 loop
会执行代码。如果是 ()
,它就会再次执行。如果是 (v)
,循环停止并返回 v
有了这个,我们可以无限循环
我们可以实现一个while循环
或者一个for循环
else (())
告诉mers在条件返回 false
时退出循环并返回 ()
函数
函数以 arg -> something
的形式表达,其中 arg
是函数的参数,而 something
是函数应该做什么。通常方便将函数分配给变量,这样我们就可以轻松使用它
由于函数只是普通值,我们可以将它们传递给其他函数,也可以从其他函数返回它们
在这里,do_twice
是一个函数,它接受一个函数并返回一个新的函数,该函数执行原始函数两次。所以,add_one.do_twice
成为一个新函数,它可以写成 x -> x.add_one.add_one
当然,这根本不会损害类型安全
Mers告诉我们,我们不能用 String
调用 add_two
,因为这将调用在 do_twice
中定义的 func
,并且这个 func
是 add_one
,然后它会调用 sum
并将那个 String
和一个 Int
一起传递,这是不可行的。
错误可能有点长,但它告诉我们出了什么问题。我们可以通过给我们的函数添加一些类型注解来使其更明显。
高级变量
在mers中,我们可以声明具有相同名称的两个变量
只要第二个变量在作用域内,我们就无法再访问第一个变量,因为它们具有相同的名称。这不同于给x赋新值
第二个x
仅在由代码块({
)创建的作用域内存在,所以,在其结束时(}
),x
又指向原始变量,其值未改变。
要给原始的x赋新值,我们必须写成&x =
引用
写入&var
返回对var
的引用。然后我们可以将该引用赋值
...
在这里,我们实际上并没有给ref
赋值,我们是在给ref
所引用的变量赋值。这之所以有效,是因为等号左侧不需要是&var
。只要它返回一个引用,我们就可以给那个引用赋值
这被例如get_mut
函数所使用
在这里,我们将列表(&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