让我们继续对编程语言的探索,有一种大家都知道的编程语言,用的人不多,但是确实很强大。
OCaml 于 1996 年首次发布,已经存在 28 年了。
有趣的是,OCaml 源自于 1985 年首次发布的 Caml。
OCaml 是一种小众编程语言,这意味着在某些环境中使用非常广泛,但不是主流语言。 Jane Street 的一切都使用 OCaml,使用 OCaml 的著名公司有 Facebook、微软和 Docker。
我第一次学习 OCaml 是在 2015 年左右。我已经了解了 Erlang 和 Haskell,所以下一步是 OCaml,顺便说一句,它是命令式的、面向对象的和函数式的。
我们将使用 Jane Street 的核心库,因此您可能需要安装它:
$ opam install core |
好的,让我们进入我们的主题,即创建 LED 数字应用程序。
应用程序应该像这样工作,我们输入1977,它返回:
现在,请记住,我们希望向 OCaml 新手展示这一点,而不是向经验丰富的开发人员展示。
我们要做的第一件事是创建一个 Map(类似于其他语言中的哈希或字典),以保存 LED 数字的所有组成部分:
let leds = [ (‘0’, [” _ “; “| | “; “|_| “]); (‘1’, [” “; “| “; “| “]); (‘2’, [” _ “; ” _| “; “|_ “]); (‘3’, [“_ “; “_| “; “_| “]); (‘4’, [” “; “|_| “; ” | “]); (‘5’, [” _ “; “|_ “; ” _| “]); (‘6’, [” _ “; “|_ “; “|_| “]); (‘7’, [“_ “; ” | “; ” | “]); (‘8’, [” _ “; “|_| “; “|_| “]); (‘9’, [” _ “; “|_| “; ” _| “]) |
我们将每个数字分成三行。例如,如果我们要打印数字6,我们可以这样做:
open Core let get_leds = let () = |
看起来很多吧?好吧,在 Ocaml 中你需要维护一定的结构,所以让我们花点时间来分析一下:
- 我们称之为核心模块。
- 我们正在定义名为get_leds的主函数。
- 在我们的函数中,我们正在定义LED地图。
- 我们将在名为line的变量的定义中使用leds映射变量。该变量将读取地图并获取与ƌ’关联的值。List.Assoc.find_exn允许我们从映射中检索值。~equal:Char.equal允许我们使用字符来查找值。
- 一旦我们有了值,我们就想打印每一行。
- 最后,我们调用我们的 main 函数。
结果是:
_ |_ |_| |
当然,我们想打印多个数字,因此我们的想法是将每个数字的行连接起来,然后打印它们:
open Core let get_leds = let () = |
结果是这样的:
_ _ |_ _| |_| |_ |
当然,我们需要一种方法来自动执行此操作,因为数字越长,我们的打印命令就越长,而且我们不希望有任何硬编码。
好的,我们有 3 行需要打印。但却是一个未知的数字。在运行时了解我们的号码有多少位非常重要,以便我们采取相应的行动。假设我们要打印数字1593,所以我们有4 位数字,我们需要打印 3 行,每行包含这 4 位数字的部分,所以这是我们的应用程序代码:
open Core let get_leds number = let () = |
在这里,我们使用 print_string 请求一个数字,并调用Out_channel.flush stout以确保它打印在终端上。我们定义一个名为 num 的变量,它将保存用户使用In_channel.input_line_exn stdin键入的输入。我们希望在get_leds函数中使用该信息。
在get_leds内部,我们将使用for关键字执行循环操作。外循环将循环 3 次,而内循环将循环输入的位数。
我们不会在变量中存储任何值,而是直接在终端上打印结果。printf允许我们继续打印,除非有明确的print_string \n。对于此示例,我们将打印数字1593。
为了让事情变得更容易,让我们调试我们的应用程序并查看每次迭代中会出现哪些值:
- 我们输入数字1593 ,并以i的值为0开始外循环。
- 在内部循环中,j的值为0,并将一直上升到3(因为我们的数字有4位)。
- 我们将使用let line = List.Assoc.find_exn ~equal:Char.equal leds number.[j]提取数字1593的第一位数字。在 Ocaml 中,字符串只是一个字符列表,因此我们可以轻松地使用number.[j]来获取数字。
- 我们需要调用printf “%s” (List.nth_exn 第 i 行)来提取需要打印的行部分。这里是0。
_ _ _ |
我们可以转到第一个循环的第二次迭代。一切都会重复,但例外的是i的值为1,这意味着它将读取第二行。我们将打印以下内容:
_ _ _ | |_ |_| _| |
我们最终进入第一个循环的第三次也是最后一次迭代。同样,一切都会重复,但i的值为2,这意味着它将读取第三行。我们将打印以下内容:
_ _ _ | |_ |_| _| | _| _| _| |
然后申请就结束了。如果我们将应用程序命名为LED_Numbers.ml,我们可以在终端窗口上运行它,如下所示:
corebuild LED_Numbers.native |
等待?我们的代码扩展名不是.ml吗?是的,但是 corebuild 只需要名称而不需要扩展名。此外,.native将是生成的可执行文件的扩展名。
OCaml官网 https://ocaml.org/