七周七语言——Prolog(二)
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?a Who=john_boy_jr no
这些都是以前就讲过的了,不多赘述。尤其要强调的是:
每个递归的子目标都会使用栈空间,最终你很可能会耗尽栈空间。声明式语言通常使用一种称为
尾递归优化的技术来解决这个问题。
如果你将一个递归的子目标放到递归规则的末尾,Prolog会通过丢弃调用栈来优化这次调用,并保持内存占用不变。这里的调用就是一个尾递归,因为递归子目标ancestor(Z,Y)是递归规则中的最后一个目标。
2 列表和元组
列表,也可以用(1,2,3)来指定一个
元组。列表是
变长容器,而元组则是
定长容器。
合一,第二部分
|?-(A,B,C)=(1,2,3). A=1
B=2
C=3 yes
|?-[2,2,3]=[X,X,Z]. X=2
Z=3 yes
例子很简单。列表拥有一项元组不具备的能力,即你可以通过 [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=c yes
“_”是一个通配符,可以与任何对象合一。
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]?a One=[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。
七周七语言——Prolog(二)的更多相关文章
- 七周七语言之用ruby做点什么
如果你想获得更好的阅读体验,可以前往我在 github 上的博客进行阅读,http://lcomplete.github.io/blog/2013/05/25/sevenlang-ruby/. 每学一 ...
- Seven xxx in Seven Weeks ebooks | 七周七 xxx 系列图书 电子书| share 分享 | free of charge 免费!
Seven xxx in Seven Weeks ebooks | 七周七 xxx 系列图书 电子书| share 分享 | free of charge 免费! Seven Languag ...
- 七周七语言之使用prolog解决爱因斯坦斑马难题
如果你想获得更好的阅读体验,可以前往我在 github 上的博客进行阅读,http://lcomplete.github.io/blog/2013/06/28/sevenlang-prolog/. 目 ...
- 七周七语言之用Io编写领域特定语言
如果你想获得更好的阅读体验,可以前往我在 github 上的博客进行阅读,http://lcomplete.github.io/blog/2013/06/05/sevenlang-io/. Io 语言 ...
- 七周七语言之Ruby
1.安装 Ubuntu 14.04 sudo apt-get install ruby version 1.9.1 2.命令行运行: irb 3.文挡查看:man RDoc 4.猜数字 2.2.7程序 ...
- 第七周C语言代码
#ifndef NMN_LIST_H #define NMN_LIST_H #include <stdio.h> struct list_head { struct lis ...
- C语言--第七周作业评分(5班)
作业链接:https://edu.cnblogs.com/campus/hljkj/CS2017-5/homework/1304 一.评分要求 要求1 完成PTA第七周所有题,总共两次题,每次12.5 ...
- C语言程序设计I—第七周教学
第七周教学总结(14/10-20/10) 教学内容 第二章 用C语言编写程序 2.5 生成乘方表和阶乘表 课前准备 在蓝墨云班课发布资源: PTA:2018秋第七周作业 分享码:FE065DC5D8C ...
- 程序设计入门-C语言基础知识-翁恺-第七周:指针与字符串-详细笔记(七)
目录 第七周:指针与字符串 7.1 指针初步 7.2 字符类型 7.3 字符串 7.3 课后练习 第七周:指针与字符串 7.1 指针初步 sizeof 是一个运算符,给出某个类型或变量在内存中所占据的 ...
随机推荐
- C#读取Excel几种方法的体会
(1) OleDb: 用这种方法读取Excel速度还是非常的快的,但这种方式读取数据的时候不太灵活,不过可以在 DataTable 中对数据进行一些删减修改 这种方式将Excel作为一个数据源,直接用 ...
- 【STM32】STM32 GPIO模式理解
stm32的GPIO的配置模式有好几种,包括: 1. 模拟输入: 2. 浮空输入: 3. 上拉输入: 4. 下拉输入: 5. 开漏输出: 6. 推挽输出: 7. 复用开漏输出: 8. 复用推挽输出 如 ...
- spring mvc 配置
之前配置spring mvc 怎么都访不到对应的jsp,后来把prefix里面的jsp改为views,就能访问到了,然后再改回jsp也可以访问到 搞了两天,都崩溃了,不管怎样先把没问题的例子给记录下来 ...
- 容斥原理算法总结(bzoj 2986 2839)
容斥原理是一个从小学就开始学习的算法.但是很多难题现在都觉得做的十分吃力. 容斥原理大概有两种表现形式,一种是按照倍数进行容斥,这个东西直接用莫比乌斯函数就可以了. #include<iostr ...
- Android手机上监听短信的两种方式
Android手机上监听短信有两种方式: 1. 接受系统的短信广播,操作短信内容. 优点:操作方便,适合简单的短信应用. 缺点:来信会在状态栏显示通知信息. AndroidManifest.xml: ...
- js 正则 非负整数
Javascript 正则表达式 非负整数 /** * 正则判断非负整数 */ function testnum(ob){ var reg=/^[0-9]+?$/; //如果正则需要判断非负整数并带2 ...
- QT类库与Delphi类库的体系结构对比——两者十分类似!
今天在看QT对象内存管理的一篇文章时:http://blog.csdn.net/dbzhang800/article/details/6300025想到了一个问题:就是QT类库体系结构与Delphi类 ...
- 解析Android开发优化之:对Bitmap的内存优化详解
在Android应用里,最耗费内存的就是图片资源.而且在Android系统中,读取位图Bitmap时,分给虚拟机中的图片的堆栈大小只有8M,如果超出了,就会出现OutOfMemory异常.所以,对于图 ...
- Android 颜色Color
Android中使用4个数字来表示颜色,分别是alpha.红(red).绿(green).蓝(blue)四个颜色值(ARGB).每个数字取值0-255,因此一个颜色可以用一个整数来表示.为了运行效率, ...
- Android 通过代码设置radiobutton不同方位图标的两种方法
更换radiobutton中的图片在xml中很好设置,但对于初学者如何在代码中设置还是不容易找的.没法子,通过看原版api找到两个方法,setCompoundDrawables和setCompound ...