【Scheme概括】4 高階函數

高階函數的介紹

高階函數的英文名稱是Higher Order Function,它們是以函數爲參數的函數。主要用於映射(mapping)、過濾(filtering)、歸檔(folding)和排序(sorting)表。高階函數讓程序更具模塊性,讓函數更加通用。markdown

函數sort具備2個參數,一個是須要排序的表,另外一個是定序(Ordering)函數。下面展現了按照大小將一個整數表正序排序。而<函數就是本例中函數的定序函數。數據結構

(sort(420 -130 138 983 0298 783 -783) <)
;Value:(-783 -130 0 138 298 420 783 983)

經過靈活使用定序函數,咱們能夠寫出更強大的函數。app

(sort(783 298 -289 429 892479 -197) (lambda(x y) (< (modulo x 100)(modulo y 100))))
;Value:(-197 -289 429 479 783 492 892 298)

咱們以前講過,modulo函數用來求餘。函數

Scheme並不區別過程和其餘的數據結構,所以你能夠經過將函數看成參數傳遞輕鬆的定義本身的高階函數。並且Scheme並無定義塊結構的語法,所以使用lambda表達式做爲一個塊。ui

映射

映射是將一樣的行爲應用於表全部元素的過程。R5RS定義了兩個映射過程:其一爲返回轉化後的表的map過程,另外一爲注重反作用的for-each過程。spa

map過程的格式以下:.net

(map procedurelist1 list2…)

procedure是個與某個過程或lambda表達式相綁定的符號。做爲參數的表的個數視procedure須要的參數而定。code

(map+(1 3 5)‘(2 4 6))
;Value:(3 7 11)
(map(lambda (x) (* x x))(1 2 3))
;Value:(1 4 9)

經過類比能夠發現後者的lambda表達式至關於前者的+函數。只不事後者只有一個list,而前者有2個。若是想要像前者同樣,讓兩個list中的元素一次相乘,除了用*外,也能夠用lambda表達式。server

(map(lambda (x y) (* x y))(1 2 3)(2 4 6))
;Value:(2 8 18) 

可是若是咱們這樣寫:blog

(map (lambda (x) (* x x))(1 2 3)(1 3 5))

它並不會得出(1 4 9) (1 9 25)。

若是咱們這樣寫:

(map (lambda (x y) (* x x) (* y y))(1 2 3)(1 3 5))

它得出的結果是(1 9 25),這是由於其只有一個返回值。可是(* x x)這一部分確實計算了。經過下面的例子咱們能夠確信這一點。

(map(lambda (x y) (let ((list1 (* x x)) (list2(* y y))) list1))(1 2 3)(1 3 5))
;Value:(1 4 9)
(map(lambda (x y) (let ((list1 (* xx)) (list2(* y y))) list1 list2))(1 2 3)(1 3 5))
;Value:(1 925) 這裏一樣是由於其只能有一個返回值。

而map函數最終的返回值以運算結果來判斷。

(map - '(3 2 0) '(3 1 1 3))
;Value:(0 1 -1)
(map – '(3 2 0) '(3 1))
;Value:(0 1)

由於前者中list1中沒有和list2中最後一個元素相對應的元素了,然後者中list2中沒有和list1中最後一個元素相對應的元素。

(map(lambda (x y z) (* x x) (* y y) (* z z))(1 2)(3 4 5)(6 78 9))
;Value:(36 49)

而在這裏例子中爲何最後的返回值不是(36 49 64 81),博主也不知道了,還請知道的網友留個回覆。

for-each

for-each的格式與map一致,可是for-each並不返回一個具體的值,只是用於反作用。(反作用的解釋)咱們一樣經過一個示例來展現。

(definesum 0)
;Value:sum
(for-each(lambda (x) (set! sum (+ sum x)))‘(1 2 3 4))
;Unspecifiedreturn value
sum
;Value:10

如前所述,for-each並無返回值。

過濾

儘管過濾函數並無在R5RS中定義,但MIT-Scheme實現提供了keep-matching-items和delete-matching-item兩個函數。注意item後加和不加s。

(keep-matching-items(1 -2 3 -4 5)even?)
;Value: (-2 -4)

其中even?咱們能夠認爲對應於上前文中sort函數的定序函數,固然,咱們也能夠用lambda來做爲這個參數。

(keep-matching-items(10 39 0 -100 76)(lambda (x) (<= 10 x 100)))
;Value: (10 39 76)

歸檔

一樣在R5RS中沒有定義歸檔函數,但MIT-Scheme提供了reduce等函數。

(reduce + 0 '(1 2 34))                ;⇒ 10
(reduce + 0 '(12))                    ;⇒ 3
(reduce + 0'(1))                      ;⇒ 1
(reduce + 0'())                       ;⇒ 0
(reduce + 0'(foo))                    ;⇒ foo
(reduce list '() '(1 2 34))            ;⇒ (((1 2) 3) 4)
(define (sqrt-sum-sq ls) (sqrt (reduce + 0(map (lambda (x) (* xx)) ls))))

排序

一樣在R5RS中沒有定義排序函數,而在MIT-Scheme中提供了sort(實爲merge-sort實現)和quick-sort函數。這個函數咱們在前面展現過,下面咱們用sort函數,lambda,tan函數和<來寫一個以tan(x)的大小升序排列的函數。

(define(sort-tan ls) (sort ls(lambda (x y) (< (sin x) (siny)))))
;Value:sort-tan
(sort-tan(1 2 3 4 5 6))
;Value:(5 4 6 3 1 2)

apply函數

apply函數將一個過程應用於一個表,也就是將表展開做爲過程的參數。該函數具備任意多個參數,但首末參數必須分別是一個過程和一個表。

(applymax(-1 2 -3))
;Value:2
(apply* 1 2(3 4 5))
;Value:120



感謝訪問,但願對您有所幫助。 歡迎關注或收藏、評論或點贊。


爲使本文獲得斧正和提問,轉載請註明出處:
http://blog.csdn.net/nomasp

相關文章
相關標籤/搜索