1. Hello world

打招呼,作为人际关系中最重要的一环,在和了解一门语言时也是同样重要的,这里我们也惯例从 Hello world 开始。

2. 在idle中

?- write('Hello World!'), nl.
Hello World!
true.

?-

ok,你成功的打了一声招呼,用prolog

write nl 是内部谓词,即编译器提供的基本谓词,分别是输出字符串和输出一个换行符的功能

3. 代码中

我相信REPL环境中的那一丢丢成就感是满足不了你的,那么我们把Hello world写到代码里运行它吧!像其他简单的语言一样!

hello :-
    write('Hello World!'), nl.

运行它

在win环境中,pl文件一般会关联到swipl的ide中,直接双击运行就能唤醒ide。如果没有的话可以使用命令行或者在ide中加载它

询问

?- hello.
Hello World!
true.

嗯嗯嗯!有点样子了。

这里运行脚本swipl会默认输出一些烦人的版本信息提示信息,如果想去掉它可以在运行cli命令中增加--quiet选项(简写 -q)
如 : $ swipl -q ./hello.pl

4. main函数

还要手动调用...屁股后面还返回个true,什么鬼啊?这是人写的?

嘛,毕竟prolog嘛,这就是他的风格。不过想自动执行是可以的,和其他(简单的)语言一样!

:- initialization(main).

main :-
    write('Hello World!'), nl.

注意:hello规则更名main并不是必须的

运行它 (并带上 -q)

$ swipl -q ./code/hello/hello.pl
Hello World!
1 ?-

在询问我们之前,我们的main函数就执行了

这里它仍然继续询问,不想它出现的话
把nl改为halt,即输出hello内容之后就退出

5. 编译二进制文件

脚本脚本,根本满足不了写"程序"的瘾啊!

常见的脚本语言,js py往往都因解释器臃肿难以打包,pl不然,它的解释器可以算是牺牲效率来减小空间占用,那么打包成无环境依赖的二进制文件自然也是易如反掌

(就测试,解释器打包下来大概800kb大小,完全无压力)

$ swipl -o ./hello -c ./hello.pl

注意 -c 指令和文件名需要放在最后(很奇怪,我在官方文档里也没找到原因)

执行编译后将生成可执行文件,swipl将根据当前系统环境打包,当然你也可以指定

在命令行中调用它,我们就能看到熟悉的那行输出了。

更多指令的用法可以通过 swipl -help 查看

6. Hello world 的四种写法

更常见的,Hello world会有一个普遍的需求,但我们调用Hello world程序时可以传进一个参数表示Name

如:

$ hello.exe lukr
Hello lukr!

pl可以做到吗?完全可以

swipl中提供了initialization/2接口,第一个参数表示gold不变,第二个参数则是接受参数表的规则,也可以同时指向同一个规则

看代码

:- initialization(main,main).

main([_]) :-
    write("Hello world!"),
    halt.

main([_|Name]) :-
    write("Hello "),
    write(Name),
    write("!"),
    halt.

编译然后执行试试

这里暴露了pl最重要的一个设计理念,"推导无处不在",在第二个规则中,我们的推导是在参数列表(看上去)中进行的。带来的便利可想而知

6.1. 改进一下

如果你够调皮,可能会像下面这样来调用我们编译的程序

$ hello zhang san
$ hello AMD YES
$ hello _ _ _

然后你会拿到一堆错

报错信息不是很明显,但是bug是显而易见的,我们的匹配规则将后面的List都看做是一个项了。fix也不麻烦,我们只取第二个就行了,扔掉后面的

main([_|Name|_]) :-
    write("Hello "),
    write(Name),
    write("!"),
    halt.

6.2. 再改一改

不行,我就是要显示全部参数!AMD必须YES!

首先,write输出list的话会以[x,x,x,x....]的形式,那么看来我们需要一个打印列表的函数

% print_ls([]) :- !.

print_ls([P|[]]) :-
    write(P).

print_ls([P|NP]) :-
    write(P),
    tab(1),
    print_ls(NP).

改造一下main

main([_|Argv]) :-
    write("Hello "),
    print_ls(Argv),
    write("!"),
    halt.

编译执行,给力!

6.3. 终改!

concat_atomformat 是swipl的标准库,会造轮子不一定会造车,"多看官方文档"可以算是教程中出现的最不负责任的一句话,但是它绝对是正确的

#!/usr/bin/env swipl

:- initialization(main,main).

main([_]) :-
    write("Hello world!"),
    halt.

main([_|Argv]) :-
    concat_atom(Argv, ' ', ArgString),
    format('~w ~w~w',["Hello",ArgString,"!"]),
    halt.

#!/usr/bin/env swipl 可以让脚本在linux环境中自己运行

编译运行,完美!

Copyright © zhzluke96 2020 all right reserved,powered by Gitbook该文件修订时间: 2020-07-05 10:51

results matching ""

    No results matching ""