用 Prolog 开发 Hello World 程序

序言

本文演示如何用 Prolog 来实现经典的 Hello World 程序。

搭建开发环境

为了可以运行 Prolog 程序,需要先安装一个 Prolog 语言的实现。这里我选择的是 SWI-Prolog,到这里下载对应平台的安装包,安装完毕后,运行命令swipl --version可以看到相应的输出

➜  /tmp swipl --version
SWI-Prolog version 9.0.4 for x86_64-darwin

接着再打开这个链接,给 VSCode 安装相应的插件,实现语法高亮,效果如下图所示

语法高亮 语法高亮

运行 Prolog 程序

使用 VSCode 将下列代码保存到名为hello_world.pl的文件中

:- initialization(main, main).

main(_) :-
    writeln("Hello, world!").

然后运行命令swipl ./hello_world.pl即可输出Hello, world!到屏幕上,如下图所示

hello_world执行结果 hello_world执行结果

展开说说

接下来对上述源文件hello_world.pl做一番讲解。

源文件命名

Prolog 源文件的后缀名通常为.pl,因此上文中的文件名为hello_world.pl

程序入口

与 C 语言不同,Prolog 并没有规定程序启动的时候要调用哪一个函数,而是由开发者使用命令(Prolog 的术语为directive:- initialization来指定的。可以将initialization视为一个两个参数的函数:

  • 第一个参数为Goal,表示要调用的函数的名字。在这里就是main
  • 第二个参数为When,表示在什么时候调用Goal。当它的值为main的时候(注意,这里的main是一个固定的模式,与作为参数Goal的函数的名字无关),就表示是在程序启动的时候调用。

因此,:- initialization(main, main).的意思,就是在程序启动的时候,调用名为main的函数。

函数定义

在 Prolog 中,使用操作符:-来定义函数。它的左侧是函数的名字和参数列表,在上文的例子中,函数名为main,它有一个参数。由于这个参数在函数体中并未被用到,因此将其命名为_——这是 Prolog 中的匿名变量的意思,它可以避免触发编译器对于一个变量仅出现了一次的警告。而在:-的右侧直到英文句号(即.这个符号)的代码则属于函数体,在这里是writeln("Hello, world!")

如果函数体中有多于一个语句,那么它们之间由英文逗号(即,这个符号)分隔。例如,将前文中的代码改写如下

:- initialization(main, main).

main(_) :-
    write("Hello, "),
    writeln("world!").

可以看到,两个语句之间正是由,分隔。

字符串

就像其它许多语言一样,SWI-Prolog 也支持以双引号的语法来表示一个字符串对象,因此上文中的"Hello, world!"是字符串类型,而不是一个 atom(atom 是 Prolog 中的一种数据类型,前文中的main就是一个 atom)。

输出

函数writewriteln都可以用于将字符串输出到屏幕,区别在于后者会在最后输出一个换行符。