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_atom
和format
是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环境中自己运行
编译运行,完美!