前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Gleam,一种新的函数式编程语言简介

Gleam,一种新的函数式编程语言简介

作者头像
云云众生s
发布2024-06-24 10:55:06
700
发布2024-06-24 10:55:06
举报
文章被收录于专栏:云云众生s云云众生s

Gleam 是一种类型安全的函数式编程语言,用于构建可扩展的并发系统。它是否像声称的那样友好?我们来了解一下。

译自 Introduction to Gleam, a New Functional Programming Language,作者 David Eastman。

当我的同事读完我的 Virgil 帖子 后,他立刻建议我看看 Gleam。它很酷且很新——版本 1 在今年 3 月 发布——并且在编程生活的函数式方面表现得很出色。

Gleam 是一种类型安全的函数式编程语言,用于构建可扩展的并发系统。它编译为 ErlangJavaScript,因此与其他“BEAM”语言(如 Erlang 和 Elixir)具有直接的互操作性。(BEAM 是在 Erlang 运行时系统中执行用户代码的虚拟机。我相信它的缩写是 Bogdan’s Erlang Abstract Machine。别问。)

Erlang 是一种早期的电信行业语言,非常注重并发性和容错性。它的做事方式仍然受到尊重,并且解释了 Elixir 的流行。在这篇文章中,我不会假设你熟悉这些;实际上,Gleam 特别友好,因此它也没有做出太多假设。

让我们从 hello world 开始:

代码语言:javascript
复制
import gleam/io
pub fn main() {
  io.println("hello world!")
}

这与 Zig 中的相同内容非常相似。

有一个非常愉快的 语言之旅,它利用 Gleam 编译到 JavaScript 来提供动态检查。你还可以将其用作游乐场。安装 Gleam 也意味着安装 Erlang。对于我的 Mac,我只使用了 Homebrew:

代码语言:javascript
复制
brew install gleam

Homebrew 会自动安装 Erlang。

Gleam 带有一个模板(或项目)生成器,很像 Rails。因此,要创建一个新的 hello 项目,我只需键入:

目前还没有节省时间,“hello world”风格的一行代码已经作为 hello.gleam 中的默认代码存在:

如果我运行整个项目:

请注意,这两个包仅在第一次运行时编译。

包管理

有两个 .toml 文件(显然是 Tom’s Own Markup Language。别问),它们充当配置。

由于它们应该很简单,我们可以快速浏览一下。在 gleam.toml: 中:

代码语言:javascript
复制
[dependencies]
gleam_stdlib = ">= 0.34.0 and < 2.0.0"

请注意,它们有一个 版本约束——提到最大版本以减少不兼容性。

下载和使用的实际版本在 manifest.toml 中提到。

如果我们 遵循 一个简单的示例,我们可以学习一些 Gleam 并使用包管理器。我们将添加几个包,并编写一些代码来打印环境变量。我将使用相同的 hello 项目模板,但插入了新代码。

首先,我们将添加新包以允许读取环境( envoy)和读取命令行参数( argv)——你可能希望它们是内置的,但可能反映系统差异。

因此,让我们用打印环境变量的代码替换 hello.gleam 中的代码:

代码语言:javascript
复制
import argv
import envoy
import gleam/io
import gleam/result
pub fn main() {
  case argv.load().arguments {
    ["get", name] -> get(name)
    _ -> io.println("Usage: get <name>")
  }
}
fn get(name: String) -> Nil {
  let value = envoy.get(name) |> result.unwrap("")
  io.println(format_pair(name, value))
}
fn format_pair(name: String, value: String) -> String {
  name <> "=" <> value
}

添加到公共 main 入口点,我们有两个函数。它们使用与我们在 Virgil 中看到完全相同的格式。事实证明,类型注释是可选的,但被认为是良好的实践。现在,我们变得有点函数化。argv 加载执行你期望的操作,并拉入一个列表,该列表希望恰好包含两个字符串——第一个字符串等于“get”。这在 case 语句中使用。

简单说一下,Gleam case 比大多数非函数式语言中的更灵活。在这里,我们看到列表的内容正在被比较:

代码语言:javascript
复制
let result = case x {
  [] -> "Empty list"
  [1] -> "List of just 1"
  [4, ..] -> "List starting with 4"
  [_, _] -> "List of 2 elements"
  _ -> "Some other list"
}

因此, 模式可以在 case 语句中进行比较。下划线 _ 表示默认值,并且可能的情况被穷举检查。

回到我们的环境变量读取代码,如果模式 不是 两个字符串的列表,那么将显示帮助文本。否则,它将调用 get 函数。 我们看到了管道函数,它只是帮助使从左到右的长函数调用更具可读性。

代码语言:javascript
复制
let value = envoy.get(name) |> result.unwrap("")

这与以下内容相同:

代码语言:javascript
复制
let value = result.unwrap(envoy.get(name),"")

因为 Gleam 不会抛出异常,它使用内置的 Result 类型,而 unwrap 获取正确的路径值。

最后的奇点是:

代码语言:javascript
复制
name <> "=" <> value

…这只是字符串连接。

我在这里运行它,第二次使用必需的参数:

Gleam 没有 null、没有隐式转换,也没有异常。因此,如果它编译,那么你很好。此外,没有数字运算符重载,因此用于添加整数的代码与用于添加浮点数的代码不同:

代码语言:javascript
复制
io.debug(1 + 1) //ints
io.debug(1.0 +. 1.5) //floats

相等适用于任何类型。最好通过使用函数式语言一段时间来体验不变性的总体概念,因此我不会对此进行详细说明。它确实有助于消除一整套错误。

代数数据类型

最后,我们看到了代数数据类型 (ADT) 用于 Virgil,因此我热衷于了解 Gleam 中的等效项如何工作。事实上,我们已经看到了 case 语句的使用。

我们得到自定义类型,我们对其进行模式匹配。因此,我们已经完成了一部分:

代码语言:javascript
复制
pub type Season { 
  Spring 
  Summer
  Autumn  
  Winter 
} 
 
fn weather(season: Season) -> String { 
  case season { 
    Spring -> "Mild" 
    Summer -> "Hot" 
    Autumn -> "Windy" 
    Winter -> "Cold" 
  } 
}

类型可以在记录中保存数据,这就是我们接近我的 Virgil 示例的方式:

代码语言:javascript
复制
import gleam/io
 
pub type Travel {
  Walk(hours: Int)
  Cycle(hours: Int)
  Drive(hours: Int, speed: Int)
}
 
pub fn main() {
  let walking = Walk(1)
  let cycling = Cycle(1)
  let bus_trip = Drive(2, 50)
 
  let trip = [walking, cycling, bus_trip]
  io.debug(trip)
}
 
// [Walk(hours: 1), Cycle(hours: 1), Drive(hours: 2, speed: 50)]

我认为我无法在类型内部关联一个方法,但我可以访问记录值以获得与我们在 Virgil 中获得的结果类似的结果。我将把它留给更流利的用户作为练习!

对于像我这样不太使用函数式代码的人来说,Gleam 非常容易理解,并且不会立即用“柯里化”和其他函数式冲击之类的术语来让我不知所措。但是,如果你还没有成为拥护者,它应该是一种让你欣赏编程的不可变优势的好方法。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-06-232,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 包管理
  • 代数数据类型
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档