Coursera公開課Functional Programming Principles in Scala習題解答:Week 2

引言

OK.時間很是快又過去了一週。第一週有五一假期因此感受時間綽綽有餘,這週中間沒有假期僅僅能靠晚上加週末的時間來消化,事實上仍是有點緊張呢!java

後來發現每堂課的視頻還有相應的課件(Slide)、字幕(subtitles)可以下載。這樣下載視頻學習和在線學習就僅僅差課程中間的Exercise了編程

Week 2主要講函數,函數在Scala裏是first-class citizen,可以在隨意域內出現。這門課事實上也是在借Scala來說函數式編程原理。框架

好了,很少說。進入習題解析。ide

 

這周的做業主要是使用函數來表示一個集合,可以經過傳遞給函數一個整型值獲得布爾值來驗證此整型值是否屬於此集合。好,說太繞了,如下是給出的一個栗子:函數式編程

(x: Int) => x < 0


這是一個匿名函數,將一個傳入的x映射爲布爾值,從而推斷x是否屬於這個函數表示的集合。很是明顯。這個集合是負整數集。函數

題目就從這裏開始,使用一個Int到Boolean的函數做爲集合的表示,並給其賦了一個別名:post

type Set = Int => Boolean


因此。在本此做業中定義的集合要以函數的形式給出。前面說到的函數是一等公民,固然可以做爲返回值。相應的,推斷一個值是否在給定集合內的方法例如如下:學習

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


可以看出contains函數傳進一個Set和一個Int做爲參數,前面提到Set是一個輸入爲Int類型的函數,因此將s應用到elem上,就獲得一個Boolean類型的返回值。ui

 

Exercise 2.1 Basic Functions On Sets

練習2.1完畢集合的一些簡單操做的定義。.net

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

相關文章
相關標籤/搜索