Coursera公开课Functional Programming Principles in Scala习题解答:Week 2

引言

OK.时间非常快又过去了一周。第一周有五一假期所以感觉时间绰绰有余,这周中间没有假期仅仅能靠晚上加周末的时间来消化,事实上还是有点紧张呢!

后来发现每堂课的视频还有相应的课件(Slide)、字幕(subtitles)能够下载。这样下载视频学习和在线学习就仅仅差课程中间的Exercise了

Week 2主要讲函数,函数在Scala里是first-class citizen,能够在随意域内出现。这门课事实上也是在借Scala来讲函数式编程原理。

好了,不多说。进入习题解析。

这周的作业主要是使用函数来表示一个集合,能够通过传递给函数一个整型值得到布尔值来验证此整型值是否属于此集合。好,说太绕了,以下是给出的一个栗子:

(x: Int) => x < 0


这是一个匿名函数,将一个传入的x映射为布尔值,从而推断x是否属于这个函数表示的集合。非常明显。这个集合是负整数集。

题目就从这里開始,使用一个Int到Boolean的函数作为集合的表示,并给其赋了一个别名:

type Set = Int => Boolean


所以。在本此作业中定义的集合要以函数的形式给出。前面说到的函数是一等公民,当然能够作为返回值。相应的,推断一个值是否在给定集合内的方法例如以下:

def contains(s: Set, elem: Int): Boolean = s(elem)


能够看出contains函数传进一个Set和一个Int作为參数,前面提到Set是一个输入为Int类型的函数,所以将s应用到elem上,就得到一个Boolean类型的返回值。

Exercise 2.1 Basic Functions On Sets

练习2.1完毕集合的一些简单操作的定义。

singletonSet

開始当然是定义一个集合啦~这个集合是个单例集合,其仅仅能存放一个值,签名例如以下:

def singletonSet(elem: Int): Set

能够使用Int类型的參数来初始化这个函数,返回的是一个Set类型,也就是Int => Boolean的函数。我们已经知道集合中仅仅包括elem这个元素,那么仅仅须要推断一个元素是否等于elem就能够了。

代码自己写吧……

union, intersect and diff

上面我们定义了一个最简单的集合,接下来能够通过简单集合的不断组合生成新的集合。

比較经常使用的三种操作是union、intersect和diff,其原型例如以下:

def union(s: Set, t: Set): Set
def intersect(s: Set, t: Set): Set
def diff(s: Set, t: Set): Set

以上三个操作均是通过组合两个Set得到一个新的Set。分别表示两个集合的并集、交集和差集,这些概念都比較简单。

1.union就是在s中或者在t中的元素组成的集合。所以仅仅须要推断一个元素是否在这两者其一就可以

2.intersect就是在s中且在t中的元素组成的集合,所以须要推断一个元素是否同一时候在这两者中

3.diff就是在s中且不在t中的元素组成的集合,须要推断一个元素在s且不在t中

代码。自己写。

filter

接下来是要实现一个filter函数,即选取集合s中符合断言p的元素。这些元素组成的相同是一个集合。filter的原型例如以下:

def filter(s: Set, p: Int => Boolean): Set

这个事实上比較简单了。实质上是intersect的变形,仅仅只是intersect的第二个入參是filter第二个入參的别名罢了。

Exercise 2.2 Queries and Transformations on Sets

作业2.2是完毕一些在Set上的操作。

forall

第一个函数给定一个断言,推断Set中的全部元素是否都满足这个断言。签名例如以下:

def forall(s: Set, p: Int => Boolean): Boolean

我们定义Set的方式决定了无法实际列举Set内的全部元素,仅仅能推断给定元素是否属于这个Set,所以假设要完毕这个功能。我们须要遍历全部的整型数。

这是不现实的,所以将其限定在-1000到1000范围内。

对于以上的forall函数,题目给出了一个框架,仅仅须要在框架内把对应的部分(即???

部分)填写完成就可以:

def forall(s: Set, p: Int => Boolean): Boolean = {
 def iter(a: Int): Boolean = {
   if (???

) ??? else if (???) ?

?

?

else iter(???

) } iter(???)

}


能够看到forall内部定义了一个函数iter,并将一个iter的实例作为forall的返回值(注意,这里又强调了一次函数是一等公民的概念。)

那么依据上述提示,我们须要遍历-1000到1000内的整型,依次推断其是否符合断言p,当然前提条件是这个整型也属于集合s。p是一个Int映射到Boolean类型的函数。仅仅须要将整型数传递给它。推断其返回值就可以知道此整型数是否符合p。

推断一个数是否属于集合s能够使用Exercise 2.1中定义的contains函数来实现。

Main.scala中还定义了一个上界:

  /**
   * The bounds for `forall` and `exists` are +/- 1000.
   */
  val bound = 1000


事实上这个还是比較简单,仅仅须要从-1000到1000。依次推断当中属于集合s的元素是否都符合断言p就可以。假设有一个不符合上述条件。那么返回false;假设都符合,返回true。

请自行实现。

exists

第二个须要实现的函数为exists。即推断集合s中是否含有符合给定断言的元素,签名例如以下:

def exists(s: Set, p: Int => Boolean): Boolean


注意,题目要求exists须要通过调用forall来实现。这个场景好熟悉啊……这不就是高中课本里的题目:“抛N枚硬币全部面都朝上的概率”。和“抛N枚硬币有一次面朝下的概率”之间的关系是一样的么?

OK。分析一下。

推断集合s中是否有符合给定断言的元素,即推断集合s中全部元素是否都不符合给定断言。

假设s中全部元素都不符合给定断言,那么返回false;否则返回true。

懂了吧?下一题。

map

最后一道题目是写一个map函数,将给定集合映射到另外一个集合。签名例如以下:

def map(s: Set, f: Int => Int): Set

当中第二个參数f是用来将原集合的元素映射到新集合的函数(一等公民。)

题目看起来简单。仅仅是推断s中的元素经过f映射后。是否有和输入整型相等的就可以。

这当中包括两个步骤:

1.s中是否有符合某个特定条件(断言)的元素

2.特定条件(断言)为经过f映射。等于输入參数

记得返回类型为Set,即Int => Boolean类型的函数(一等公民!)!

结语

整体来说,Scala有别于其它面向对象语言的一个最大的特点是其混合了非常多函数式编程的概念和方法,这在使用Scala的过程中尤其要注意!Scala能够看做是O教(面向对象编程)和F教(函数式编程)的合体。

PS:此次附带的FunSetSuite.scala中仅仅有非常少一部分測试用例,另一些是被打上了ignore标签,假设自己有兴趣,可以试着写一些单元測试,保证可以覆盖到一些特殊情况,这样就不至于重复在Coursera的server上提交不完美的答案了!

PPS:如今补上了作业题目的下载链接和题面(防止网页失效带来的不便。以离线网页的形式给出),方面以后看到的同学自己练习。

第二章题目下载地址:http://download.csdn.net/detail/doggie_wangtao/7343177

Coursera公开课Functional Programming Principles in Scala习题解答:Week 1 

声明:

本文为原创,禁止用于不论什么商业用途。转载请注明出处:http://blog.csdn.net/asongoficeandfire/article/details/25661661

原文地址:https://www.cnblogs.com/jzssuanfa/p/7273518.html