那迷人的被遗忘的语言:Prolog

在进入正题以前,咱们先一块儿思考一个问题:当咱们在编程时,咱们在作什么?html

看到这个问题,有些同窗可能会第一时间要回答:前端

  • 在听音乐
  • 在打字
  • 在发呆
  • 在装做很忙的样子
  • ……

呃,我不是那个意思,说认真的:当咱们在编程时,咱们在作什么?程序员

咱们在把所想的「解决方案」转换成计算机可理解的「计算机语言」。编程

JavaScript, Python, Java, Ruby, C++ …… 等等等等,哪怕是世界上最好的语言 PHP,也大抵如此:「解决方案」->「计算机语言」bash

但你有没有想过反过来?「计算机语言」->「解决方案」 这样,咱们使用「计算机语言」描述问题,而计算机来告诉咱们「解决方案」?微信

或许你会想到人工智能、深度学习等等概念,但那些热门话题不是咱们今天要讨论的。编程语言

今天,咱们来一块儿聊聊那迷人的被遗忘的语言:Prolog.函数

Prolog 简介

Prolog(Programming in Logic)是一种逻辑编程语言。它建立在逻辑学的理论基础之上, 诞生与 1972 年,最初被运用于天然语言等研究领域,距今 46 年历史。当下火热的 JavaScript 语言 23 岁,年龄恰好是 Prolog 的一半。学习

说到 Prolog 是一种逻辑编程语言,那么跟通常的函数式语言有什么区别呢?答:彻底不是一码事情。在 Prolog 里,最基本的作法是先描述事实(定立对象与对象之间的关系),而后用询问目标的方式来查询各类对象之间的关系,系统会自动进行匹配、回溯,并给出答案。ui

举个例子:

咱们使用下面的语法来表述一个事实

handsome(ergou).
复制代码

这个语句描述了一个事实:二狗 (ergou) 是无比帅气 (handsome) 的,而后以句号 (.) 结束,代表这个事实描述完毕,无可置疑。

而后接下来咱们在 Prolog 的控制台 (REPL) 里就会获得以下的结论:

?- handsome(X).
X = ergou.

?-
复制代码

其中 ?- 开头的是咱们手动输入的,其余的是 Prolog 返回的。上面的那些操做是:

  1. 咱们首先问 Prolog:谁是世界上最帅的人?handsome(X). 其中 X 是大写字母开头,在 Prolog 里全部大写字母开头的都是变量。
  2. 而后 Prolog 回答说:X = ergou. ,固然是二狗了!

以上,应该能够算做 Prolog 基本思路的一个演示。你能够去下载适用于你的 Prolog 环境,而后在本身的电脑上把玩一下。

建议使用 SWI Prolog(本文的全部演示代码都是在 SWI Prolog 进行的操做):www.swi-prolog.org/

安装完毕以后,执行下面三步,便可复现上面的结果:

  1. 将事实写入文件
echo 'handsome(ergou).' > fact.prolog
复制代码
  1. 启动 Prolog REPL 并加载既定事实:
swipl fact.prolog
复制代码
  1. 在 Prolog REPL 内输入如下语句并回车:
handsome(X).
复制代码

谁是我大爷?

刚才的例子是咱们描述了一个事实,而后又让 Prolog 告诉了咱们这个事实,好像没有太大的用途,接下来咱们试着作一下别的事情:

文件名:grandfather.prolog

father(yigou,ergou).
father(linggou,yigou).

grandfather(X,Z) :- father(X,Y), father(Y,Z).
复制代码

看了上面的代码,应该能够理解到,咱们是描述了三个事实:

  1. 二狗 (ergou) 的父亲是 一狗 (yigou)
  2. 一狗 (yigou) 的父亲是零狗 (linggou)
  3. X 是 Z 大爷的前提条件是:X 是 Y 的父亲,Y 是 Z 的父亲

有了这些事实,咱们能够干什么?能够找到二狗爷爷啊!

载入既定事实

swipl grandfather.prolog
复制代码

执行询问语句

?- grandfather(X,yigou).
false.

?- grandfather(X,ergou).
X = linggou.

?-
复制代码

能够看到一狗 (yigou) 是没有爷爷的,二狗 (ergou) 的爷爷是零狗 (linggou) 。

我和小红的共同爱好是什么?

像刚才那个例子,咱们再举一个来加深一下这种思惟方式:

文件名:music.prolog

listen(ergou, bach). % 二狗 听 巴赫
listen(ergou, beethoven). % 二狗 听 贝多芬
listen(ergou, mozart). % 二狗 听 莫扎特
listen(xiaohong, mj).  % 小红 听 迈克尔·杰克逊
listen(xiaohong, dylan). % 小红 听 鲍勃·迪伦
listen(xiaohong, bach). % 小红 听 巴赫
listen(xiaohong, beethoven). % 小红 听 贝多芬
复制代码

上面这些代码描述了二狗和小红的听歌品味,如今若是二狗想要找出本身与小红在听歌品味上的共同之处,该怎么办?

载入既定事实

swipl music.prolog
复制代码

执行询问语句

?- listen(ergou, X),listen(xiaohong,X).
X = bach ;
X = beethoven ;
false.

?-
复制代码

咱们在加载了既定事实以后,开始询问:有什么音乐是二狗 (ergou) 和小红 (xiaohong) 都有在听的呢?

?- listen(ergou, X),listen(xiaohong,X).
复制代码

而后咱们获得了下面的答案:

?- listen(ergou, X),listen(xiaohong,X).
X = bach
复制代码

若是你有在跟着文章手动操做,若是你是个细心的同窗,你会发现此次询问以后光标停留在了 X = bach 这里,而不是换行显示出 ?-。这是为何呢?

这时候 Prolog 是在说:问题还有别的解答,按下 ; 寻求更多,按下 Enter 表示接受当前答案。在上边了例子中,咱们持续按下 ; ,直到返回 false 才停下来。

因而咱们获得了二狗和小红共同欣赏的音乐,是巴赫和贝多芬。

鸡兔同笼问题

接下来咱们来一个经典问题:

今有雉兔同笼,上有三十五头,下有九十四足,问雉兔各几何?

—— 《孙子算经》

翻译成白话文:

有若干只鸡兔同在一个笼子里,从上面数,有35个头,从下面数,有94只脚。问笼中各有多少只鸡和兔?

停!快中止思考!

若是你在使用 JavaScript、Python 等等语言的思路去尝试编程解决问题的话,赶忙停下来,如今咱们要用描述既定事实的方式,让 Prolog 给咱们答案!

文件名:chicken-and-rabbits.prolog

% 首先,咱们引入一个 clpq 的库来帮助咱们进行运算符描述
:- use_module(library(clpq)).

% 而后,咱们定义事实:脑壳的总数量(H) 应当等于 鸡的总数量(C) 加上 兔子的总数量(R)
head(C,R,H) :- {H = C + R}.

% 而后,咱们定义事实:脚的总数量(F) 应当等于 鸡的总数量(C)乘以二 加上 兔子的总数量(R)乘以四
foot(C,R,F) :- {F = C*2 + R*4}.
复制代码

咱们定义好了事实,那么接下来让咱们去询问 Prolog 答案:

载入既定事实

swipl chicken-and-rabbits.prolog
复制代码

执行询问语句

?- head(C,R,35),foot(C,R,94).
C = 23,
R = 12.
复制代码

答:鸡有 23 只!兔有 12 只!

哈哈哈哈,没错!不再须要去绞尽脑汁思考怎么告诉计算机去计算啦!只须要告诉 Prolog 既定事实,剩下的,就是提出正确的问题啦!

古老的 Prolog 在计算机科学中的逐渐退热,必然有对应的缘由,但这种语言所特有的思惟方式,也不妨去探寻一下。在当下的编程氛围里,或许 Prolog 就像是夏日的一杯加冰柠檬水,给咱们带来凉爽和清新呢!

好了,关于 Prolog 的讨论,咱们今天就到这里了,多谢各位!

还有更多关于 Prolog 的资料,感兴趣能够继续阅读:


文 / 王二狗 职业程序员,周末爱好者

编 / 荧声

本文已由做者受权发布,版权属于创宇前端。欢迎注明出处转载本文。本文连接:knownsec-fed.com/2018-08-09-…

想要看到更多来自知道创宇开发一线的分享,请搜索关注咱们的微信公众号:创宇前端(KnownsecFED)。欢迎留言讨论,咱们会尽量回复。

感谢您的阅读。

相关文章
相关标签/搜索