函数式编程语言-Neut


Neut是一门函数式编程语言,它最大的特点就是静态内存管理。啥叫静态内存管理就是编译器在编译代码的时候就已经把内存的分配和释放安排完成。号称彻底告别内存泄漏的问题且还不用垃圾回收(GC)机制!采用MIT协议授权。
主要特性:
1. 完全支持 λ 演算:喜欢函数式编程的朋友们,你们的菜来了!
2. 可预测的自动内存管理:Neut 的核心功能点,从此告别内存泄漏?
3. 类型系统没有烦人的注解:写代码更清爽,不用被一堆类型注解搞得眼花缭乱。
其他特性:
除了静态内存管理,Neut 还有一些其他的特性:
1. 值调用(Call by value)
2. 非纯函数式(Impure):可以有副作用,更方便我们写代码
3. 编译到 LLVM IR 和二进制文件:性能有保障
4. 类型系统:类似于 CoC + ADT + T-必要性 + fix, 熟悉函数式编程的朋友应该不陌生
5. 内置 LSP 支持:代码补全、错误提示等功能都有,开发体验更棒
6. 内置快速原型开发体验:像脚本语言一样,快速验证想法
7. 内置代码格式化工具:像 Go 一样,不用操心代码风格。
Neut的模块系统也有特色。它用 tar 包的摘要(checksum)来区分不同的模块,用版本信息来定义模块的身份。Neut作为一门新语言,它吸收了Rust在内存安全上的一些优点,同时通过类型系统进行内存管理,避免了手动管理内存的繁琐,也避免了GC带来的性能损耗。
当然每种语言都有自己的优劣,具体选择哪种语言,还是要根据实际需求来决定。
静态内存管理是怎么回事?
Neut 没有 GC,也没有像 Rust 那样的区域(regions)。它是怎么做到静态内存管理的呢?
答案是:类型!
Neut 会把每个类型都翻译成一个函数,这个函数可以复制或者丢弃这个类型的值。编译器会利用这些函数,把你的代码翻译成每个变量都只会被使用一次的形式。
说明示例:
// 假设有这么一段代码,变量 xs 被用了两次
let xs: list(a) = [value-1, value-2] in
some-func(xs, xs)
// Neut 会把它翻译成这样:
let xs: list(a) = [value-1, value-2] in
let (xs1, xs2) = copy-list-a(xs) in // xs 只被用了一次,复制出了两个新的
some-func(xs1, xs2)
看到没?Neut 通过复制变量,保证了每个变量都只会被使用一次;这样一来,内存的分配和释放就变得非常可控了。
可能会问: “等等,这不对啊!如果只是想获取一个列表的长度,难道也要把整个列表都复制一遍吗?这也太浪费了吧!”
Neut 当然也考虑到了这个问题。它引入了一个叫做 T-必要性 的概念(听起来很高大上,其实就是借鉴了模态逻辑)。这个 T-必要性可以实现类似 Rust 里的借用(borrowing)的功能,避免不必要的复制。具体怎么实现的就不在这里展开了,感兴趣的朋友可以去看 Neut 官网的文档,里面有详细的解释。
Neut vs Rust vs Go
最新版本:0.17
v0.17.16于2025年3月上旬发布。
项目主页:
https://vekatze.github.io/neut/
https://github.com/vekatze/neut
主要特性:
1. 完全支持 λ 演算:喜欢函数式编程的朋友们,你们的菜来了!
2. 可预测的自动内存管理:Neut 的核心功能点,从此告别内存泄漏?
3. 类型系统没有烦人的注解:写代码更清爽,不用被一堆类型注解搞得眼花缭乱。
其他特性:
除了静态内存管理,Neut 还有一些其他的特性:
1. 值调用(Call by value)
2. 非纯函数式(Impure):可以有副作用,更方便我们写代码
3. 编译到 LLVM IR 和二进制文件:性能有保障
4. 类型系统:类似于 CoC + ADT + T-必要性 + fix, 熟悉函数式编程的朋友应该不陌生
5. 内置 LSP 支持:代码补全、错误提示等功能都有,开发体验更棒
6. 内置快速原型开发体验:像脚本语言一样,快速验证想法
7. 内置代码格式化工具:像 Go 一样,不用操心代码风格。
Neut的模块系统也有特色。它用 tar 包的摘要(checksum)来区分不同的模块,用版本信息来定义模块的身份。Neut作为一门新语言,它吸收了Rust在内存安全上的一些优点,同时通过类型系统进行内存管理,避免了手动管理内存的繁琐,也避免了GC带来的性能损耗。
当然每种语言都有自己的优劣,具体选择哪种语言,还是要根据实际需求来决定。
静态内存管理是怎么回事?
Neut 没有 GC,也没有像 Rust 那样的区域(regions)。它是怎么做到静态内存管理的呢?
答案是:类型!
Neut 会把每个类型都翻译成一个函数,这个函数可以复制或者丢弃这个类型的值。编译器会利用这些函数,把你的代码翻译成每个变量都只会被使用一次的形式。
说明示例:
// 假设有这么一段代码,变量 xs 被用了两次
let xs: list(a) = [value-1, value-2] in
some-func(xs, xs)
// Neut 会把它翻译成这样:
let xs: list(a) = [value-1, value-2] in
let (xs1, xs2) = copy-list-a(xs) in // xs 只被用了一次,复制出了两个新的
some-func(xs1, xs2)
看到没?Neut 通过复制变量,保证了每个变量都只会被使用一次;这样一来,内存的分配和释放就变得非常可控了。
可能会问: “等等,这不对啊!如果只是想获取一个列表的长度,难道也要把整个列表都复制一遍吗?这也太浪费了吧!”
Neut 当然也考虑到了这个问题。它引入了一个叫做 T-必要性 的概念(听起来很高大上,其实就是借鉴了模态逻辑)。这个 T-必要性可以实现类似 Rust 里的借用(borrowing)的功能,避免不必要的复制。具体怎么实现的就不在这里展开了,感兴趣的朋友可以去看 Neut 官网的文档,里面有详细的解释。
Neut vs Rust vs Go
特性 | Neut | Rust | Go |
内存管理 | 静态内存管理,类型驱动 | 所有权、借用、生命周期 | 垃圾回收(GC) |
类型系统 | CoC + ADT + T-必要性 + fix | 强类型,静态类型,支持泛型 | 强类型,静态类型,支持接口 |
学习曲线 | 较陡峭,需要理解类型系统和内存管理机制 | 较陡峭,需要理解所有权和生命周期概念 | 相对平缓,语法简单,易于上手 |
性能 | 理论上可以达到很高的性能 | 非常高的性能,接近 C/C++ | 较高性能,但受 GC 影响 |
适用场景 | 对内存安全和性能有极致要求的场景 | 系统编程,WebAssembly,嵌入式开发 | 网络编程,云计算,微服务 |
成熟度 | 早期阶段,生态系统不完善 | 较为成熟,生态系统丰富 | 非常成熟,生态系统庞大 |
其他特性 | 内置LSP,快速原型开发,内置代码格式化工具 | 强大的社区支持, 零成本抽象, 模式匹配 | 并发编程, 简洁的语法, 快速编译 |
最新版本:0.17
v0.17.16于2025年3月上旬发布。
项目主页:
https://vekatze.github.io/neut/
https://github.com/vekatze/neut