我是一个沉迷于编程语言的人~我喜欢学习新的语言,并在电脑上编译他们。我的硕士学位选修的是伦敦Birkbeck大学提供的“编程范式和语言”模块,并且Keith Mannock和Trevor Fenner发表了很多优秀的论文。 该模块的目的是让学生了解各种编程范例之间的根本区别,以及这些范例适用于不同的编程问题。
这是我爱上Prolog的原因,Prolog是一种在计算语言学和一般人工智能中大量使用的逻辑编程语言。
在这篇文章中,我将简要介绍语言及其基本特征。 阅读后,你应该能够在Prolog中编写简单的程序,并理解语言的基本原则
安装
首先,让我们开始安装Prolog的工作。 就本文而言,我将使用SWI-Prolog(V7.2.3),请注意,Prolog版本可能有所不同。 MacOS和Windows用户可以在这里下载可执行文件。 在Ubuntu或任何其他基于Debian的发行版上,您可以使用apt-get命令。
sodu apt-get update && sodu apt-get install swi-prolog
或者,您也可以使用官方docker镜像。
docker run -it swipl:stable # or for the most recent version use the latest tag docker run -it swipl:latest
现在我们设置完配置以后可以进入Prolog。 然而,在获得技术之前,它背后的动机是什么?
学习Prolog(或任何其他语言)的动机是什么
为什么你懒得学习Prolog呢? 那么,有几个原因,但在这一点上,我反而要提到“实用型程序员”。
小提示#8“定期投入您的知识组合”:
每年至少学习一种新语言。 不同的语言以不同的方式解决相同的问题。 通过学习几种不同的方法,可以帮助你开阔思路,避免陷入困境。 此外,而且互联网上免费提供的大量软件和资料,现在学习多种语言要容易得多。
话虽如此,试着解决一个数独谜题,例如在Java或C~或者Prolog中,你可以用简单的几行代码来完成。
但是,在我们深入到Prolog之前,先来想一下“逻辑编程”是什么?
逻辑编程
说出你想要什么,而不是你想要做什么。
逻辑编程是一个编程范式,它要有数学逻辑的基础。 与Java或C语言相比,使用Prolog等逻辑编程语言编写的程序不是由指令序列组成,而是由一系列公理或定义对象之间关系的规则组成。 他们也遵循声明而不是强制性的方法。 但是,这是什么意思?
命令式编程和声明式编程的区别
让我们想一下“点一杯咖啡”的比喻,就像我们在程序页面上一样。 想象一下,当你走进你最喜欢的咖啡店,你想点咖啡。
必要的流程:
1.进入咖啡店
2.排队等候时咖啡师询问你想要点什么
3.点咖啡
4.好的,我要打包,谢谢
5.支付费用
6.出示您的会员卡以收集积分
7.收好你的小票,走出去
声明式的方法:
1.打包一大杯拿铁
所以,不是通过像x或y这样的步进指令(命令性的),而是告诉系统你需要什么,并让它试着想出一个解决方案(声明式编程)。
关于Prolog
Prolog基于Horn子句(一阶逻辑的子集),它可能是逻辑编程系列中最著名的逻辑编程语言。 这是Alain Colmerauer,Phillipe Roussel(艾克斯 - 马赛大学)和爱丁堡大学的Robert Kowalski的进行了相当长一段时间得合作项目,。 它的第一个版本在1972年出现,如Smalltalk和C。是“Programmation en logique”(法语为逻辑编程)的缩写。
Prolog在定理证明,专家系统,自然语言处理和人工智能领域(特别是IBM的Watson2)都有很大的影响力。 这也影响了Erlang编程语言的发展。
语言结构
有一点特别吸引我的是它简单的执行模型。 Prolog有四个构建块,逻辑或,逻辑和,项重写和联合。通过结合这四个块,我们可以执行任何我们关心的计算问题。
Prolog和SQL一样,有两个主要方面,一个是表示数据,另一个是查询。逻辑编程的基本结构,项和语句,都是从逻辑方法上继承下来的。有三个基本的陈述:
事实是关于问题领域的基本论断(例如“苏格拉底是一个人”)
规则是对领域事实的推论(例如“所有人都是凡人”)
查询是关于这个领域的问题(例如“苏格拉底是凡人吗?”)
事实和规则存储在知识库中,Prolog编译器将其转换成更有效的查询形式。当我们“提出”一个问题时,Prolog通过事实和规则的“数据库”进行了详尽的搜索,直到找到结果,并在内部使用回溯。
基本事实和查询
Prolog有一个简单的语法。 你会很快掌握这几条规则。 让我们从早些时候将苏格拉底的例子转变成一个实际的Prolog程序,并分析编译器内部的东西。
man(socrates). mortal(X) :- man(X). ?- mortal(socrates).
第一行写为“苏格拉底是人”,它是一个基本逻辑子句,这是一个简单的事实。 第二行是一条规则,并且转化为:“如果X是人,则X是凡人”,或者“所有的人都是凡人”。这个规则用于确定它的输入X何时是“凡人”。 规则是语言的一个关键概念,并允许我们对对象及其关系作一般性陈述。 它们由一个由一个类似十字旋转门的符号连接的头部和身体组成:-(发音为“如果”)。 第三行的内容是:“苏格拉底是否是凡人?” ?- “提出一个Prolog查询结果”。
如果您仔细阅读了这三行代码,您可能已经观察到了有区分大小写的情况。 与大多数其他语言相比,Prolog中的大小写区分非常重要。 以小写字符开头的字符串是不可变的,称为原子,您可以将它们与Ruby中的符号类型进行比较。 以大写字母或下划线开始的字符串是变量,可以更改它们的值。 在我们的例子中,socrates是一个原子,大写的X是一个变量。 另外请注意,每个子句后面的句号都是强制性的。
让我们用先前定义的知识库向Prolog提出另一个问题。
?- mortal(plato).
当然,Prolog会回应错误的,因为我们的知识库没有plato的定义。 那么下一个问题呢?
?- mortal(X).
也就是说,“谁(X)是凡人的?”。 Prolog会回应X = socrates,并将Socrates绑定到变量X.你是否注意到了命令式和声明式风格之间的巨大差异?
与命令式编程的相比较,我们没有向程序提供任何指令来定义变量。我们刚才问程序一个问题,它自动绑定一个值给我们的变量X!这个将变量与项目相匹配的过程称为统一,这也恰恰是逻辑编程的优势所在。
联合
赋值语句是大多数命令式编程语言的基础。在Java或Ruby中,表达式x = 10意味着将值10分配给变量x。两种语言的变量都是可变的,这意味着x = 20会将值20重新赋值给变量,并且之前的值会丢失。在Prolog和其他声明性语言中,变量只有在第一次被绑定和联合之后才是“可变的”。因此,我们使用联合这个术语:联合或成为整体的一个过程。我们通常可以在用于启用类型推断的命令式语言中来找到联合的应用的例子。
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。 2KB翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。2KB项目(www.2kb.com,源码交易平台),提供担保交易、源码交易、虚拟商品、在家创业、在线创业、任务交易、网站设计、软件设计、网络兼职、站长交易、域名交易、链接买卖、网站交易、广告买卖、站长培训、建站美工等服务