1  递归

首先来看一个知识库:
father(zeb,john_boy_sr).
father(john_boy_sr,john_boy_jr).ancestor(X,Y):-father(X,Y).
ancestor(X,Y):-father(X,Y),ancestor(Z,Y).

规则ancestor/2有两个子句。 如果一个规则由多个子句组成,那么其中一个子句为真,则这个规则为真。

下面我们来测试一下:
|?-ancestor(zeb,Who).Who=john_boy_sr?aWho=john_boy_jrno

这些都是以前就讲过的了,不多赘述。尤其要强调的是: 每个递归的子目标都会使用栈空间,最终你很可能会耗尽栈空间。声明式语言通常使用一种称为 尾递归优化的技术来解决这个问题。 如果你将一个递归的子目标放到递归规则的末尾,Prolog会通过丢弃调用栈来优化这次调用,并保持内存占用不变。这里的调用就是一个尾递归,因为递归子目标ancestor(Z,Y)是递归规则中的最后一个目标。

2  列表和元组

可以用[1,2,3]来指定一个 列表,也可以用(1,2,3)来指定一个 元组。列表是 变长容器,而元组则是 定长容器。

合一,第二部分

|?-(A,B,C)=(1,2,3).A=1
B=2
C=3yes
|?-[2,2,3]=[X,X,Z].X=2
Z=3yes

例子很简单。列表拥有一项元组不具备的能力,即你可以通过 [Head|Tail]解构列表。当你将一个列表与这种结构合一时,Head将绑定列表的第一个元素,而Tail将绑定剩余元素,像这样:

|?-[a,b,c]=[Head|Tail].Head=a
Tail=[b,c]yes

注意, [Head|Tail]不能与一个空列表合一,不过单元素列表可以。

|?-[]=[Head|Tail].no
|?-[a]=[Head|Tail].Head=a
Tail=[]yes

再来看两个复杂的例子:

|?-[a,b,c]=[a|Tail].Tail=[b,c]yes
|?-[a,b,c]=[a|[Head|Tail]].Head=b
Tail=[c]yes
|?-[a,b,c,d,e]=[_,_|[Head|_]].Head=cyes

“_”是一个通配符,可以与任何对象合一。

3  列表与数学运算

count(0,[]).
count(Count,[Head|Tail]):-count(TailCount,Tail),Count is TailCount+1.sum(0,[]).
sum(Total,[Head|Tail]):-sum(Sum,Tail),Total is Head+Sum.average(Average,List):-sum(Sum,List),count(Count,List),Average is Sum/Count.

这些规则很简单。下面逐步说明他们的工作方式。

  • 发起查询count(What,[1]),由于列表非空,无法与第一个规则合一。继续满足第二个规则count(Count,[Head|Tail])中的目标。进行合一操作,What绑定为Count,Head绑定为1,Tail绑定为[]。
  • 和以后,第一个目标变为count(TailCount,[]),我们尝试证明这个子目标。这次,我们与第一条规则进行合一。TailCount绑定为0。现在第一个规则满足了,所以接下来处理第二个目标。
  • 现在,对Count的求值为TailCount+1。我们可以合一变量。TailCount绑定为0,因此将Count绑定为0+1或1.
其他类似,不再赘述。

4  两个方向上使用规则

下面我们讨论 append规则。如果List3为List1+List2,那么规则append(List1,List2,List3)为真。

|?-append([oil],[water],[oil,water]).yes
|?-append([oil],[water],[oil,slick]).no

下面是一个列表构造器:

|?-append([tiny],[bubbles],What).What=[tiny,bubbles]yes

下面的代码用于列表减法操作:

|?-append([dessert_topping],Who,[dessert_topping,floor_wax]).Who=[floor_wax]yes

下面的代码用于计算出可能的排列:

|?-append(One,Two,[apples,oranges,bananas]).One=[]
Two=[apples,oranges,bananas]?aOne=[apples]
Two=[oranges,bananas]One=[apples,oranges]
Two=[bananas]One=[apples,oranges,bananas]
Two=[]no

下面我们来看一下实现append需要多少代码。重新实现Prolog的append,不过将它称为concatenate。步骤如下:

  • 编写一个规则concatenate(List1,List2,List3),它可以将一个空列表与List1连接在一起。
  • 添加一个规则,它可以将List1中的一个元素与List2连接在一起。
  • 添加一个规则,它可以将List1中的两个元素或三个元素与List2连接在一起。
  • 看看我们可以泛化哪些东西。
代码如下:
concatenate([],List,List).
concatenate([Head|[]],List,[Head|List]).
concatenate([Head1|[Head2|[]]],List,[Head1,Head2|List]).
concatenate([Head1|[Head2|[Head3|[]]]],List,[Head1,Head2,Head3|List]).

这只是前面提到的简单规则的使用,不赘述,下面看一个使用了嵌套规则的concatenate:

concatenate([],List,List).
concatenate([Head|Tail1],List,[Head|Tail2]):-concatenate(Tail1,List,Tail2).

这段代码非常简单,首先, 判断第一个列表是否为空,如果为空并且第二个和第三个列表系统,那么规则为真,这表明将一个空列表与List连接在一起,你将得到那个List。第二个子句表明如果List1和List3的Head相同,并且你可以证明将List1的Tail和List2连接在一起将得到List3的Tail,那么将List1和List2连接在一起将会得到List3。

欢迎大家留言讨论,共同进步!

转载于:https://www.cnblogs.com/snake-hand/p/3181447.html

七周七语言——Prolog(二)相关推荐

  1. 图书封面的故事之——“巴别塔”选自《七周七语言:理解多种编程范型》

    我认为,图书的封面很重要,因为首先映入读者眼帘的就是封面,他可以诱发潜在的读者去注意图书,图书的封面可以显示出很多信息,例如书名.推荐语.评价.出版单位等,最重要的还是要给图书起一个好的名字,一本好书 ...

  2. 七周七并发模型与七周七语言

    借助Java.Go等多种语言的特长,深度剖析所有主流并发编程模型 基于锁和线程的并发模型是目前最常用的一种并发模型,但是并发编程模型不仅仅只有这一种,本书几乎涵盖了目前所有的并发编程模型.了解和熟悉各 ...

  3. 《七周七语言:理解多种编程范型》书评整理

    任何一个想在程序开发这条路上走远点的人都应当多了解几门语言,多接触一些编程泛型,才能打开眼界,提高自己. 国内绝大多数程序员可能就知道个OOP,借着javascript的兴起可能有小部分人能够对原型有 ...

  4. 七周七语言:Scala Day 3

    这一天的内容还是比较丰富的,不仅介绍了Scala中的对于XML的处理.正则,更有比较重要的"并发". Scala支持并发的方式代表了并行编程领域的一次重大进步.actor模型和线程 ...

  5. 《七周七并发模型》笔记

    <七周七并发模型>笔记 1 概述 1.1 并发并行 1.2 并行架构 1.3 并发:不只是多核 并发的世界,并发的软件 分布式的世界,分布式的软件 不可预测的世界,容错性强的软件 复杂的世 ...

  6. 《七周七数据库》一一2.4 第3天:全文检索和多维查询

    本节书摘来自异步社区出版社<七周七数据库>一书中的第2章,第2.4节,作者: [美]Eric Redmond,更多章节内容可以访问云栖社区"异步社区"公众号查看. ## ...

  7. 七周七并发模型 | 读后感

    七周七并发模型 | 读后感 这本书,感觉有两种看法,第一种是粗略的看,有点像21天速成教程,讲了好几种通用模型,几乎是了解性质的介绍,明白其优缺点及适用的场景,等到需要用的时候,再去挑选合适的武器:第 ...

  8. 七周七并发之线程与锁

    2019独角兽企业重金招聘Python工程师标准>>> 七周七并发之线程与锁 博客分类: java 1.概述 1.1并发还是并行(Concurrent or Parallel) A ...

  9. 高中生学python培养思维能力_python学习(七周七第二章结构化思维及如何学习)...

    20180908星期六 总结中,为没有华丽的语句感到烦恼.是因为自己忘记初衷,如果是学习就记录今天学习内容.感想.问题:如果是工作就记录今天最优成就的一件事.今天遇见的问题:如果是生活就记录今天最开心 ...

  10. 【第七周:Python(二)】7周成为数据分析师

    本课程共七个章节,课程地址:7周成为数据分析师(完结)_哔哩哔哩_bilibili 数据分析思维 业务知识 Excel 数据可视化 SQL 统计学 Python 第七周:Python(P86-P143 ...

最新文章

  1. 周源:知乎的未来是什么
  2. MPI 集合通信函数 MPI_Reduce(),MPI_Allreduce(),MPI_Bcast(),MPI_Scatter(),MPI_Gather(),MPI_Allgather(),MPI_S
  3. 下拉插件dropload js时间计算(几天前)
  4. dealloc时取weakself引起崩溃
  5. 今天没白过之《ls命令的颜色》
  6. Tcpdump的详细用法
  7. 从拉萨骑行到珠峰大本营
  8. SQL server 2008 T-sql 总结
  9. 自定义更改虚拟机中Ubuntu的ip地址
  10. java specification_java规范(Java specification).doc
  11. 极客日报第 31 期:编写贩卖《和平精英》游戏外挂,5人被判刑;苹果推出轻App码
  12. Angular 基础
  13. 树莓派ASP.NET环境配置
  14. C语言-求各位数之积(简易版)
  15. 【jQuery小实例】---3 凤凰网首页图片动态效果
  16. opencv-图像融合拼接
  17. python 大智慧股池_跟我从零开始学会大智慧股票池自动交易
  18. AI技术驱动下的语音识别:让语音交互更加自然、智能
  19. 【react】【antd】一个既可以自定义输入又可以下拉选择的输入框
  20. JavaScript 编程规范(一)

热门文章

  1. 在 Mac 上修复 Touch ID 问题的 6 种方法
  2. 升级macOS Big Sur 无法开机/死机怎么办?
  3. matlab中fopen 和 fprintf函数总结
  4. javascript在使用时要注意的东西
  5. PHP下载文件(隐藏真实的下载地址)
  6. 数据结构(四)之冒泡排序
  7. C# WinForm 使用FlowLayoutPanel控件做为导航菜单按钮的容器
  8. 水晶報表之Datetime TO shortDate
  9. PHP学习之十二:自定义函数
  10. iOS CocoaPods:Updating local specs repositories一直停在那里了