在以前幾篇咱們討論的語法、語義、命名、類型和抽象適用於全部語言。然而咱們的注意力都主要集中在命令式語言上,如今這篇來看看其它範式的語言。函數式和邏輯式語言是最主要的非命令式語言。html
命名和做用域問題出如今各類模型中,還有類型、表達式和選擇與遞歸等控制流概念等等。全部語言都必須通過掃描、語法分析和語義分析,程序員
函數式程序設計將一個程序的輸出定義爲其輸入的一個數學函數,在其中沒有內部狀態的概念,所以也沒有反作用。函數式提供了一下特徵,其中許多都是命令式語言中沒有的:安全
咱們以Scheme爲例子,來看一下概念markdown
(let ((a 3)
(b 4)
(square (lambda (x) (* x x)))
(plus +))
(sqrt (plus (square a) (square b))))
複製代碼
特殊型let有兩個或者多個參數,其中第一個參數是一些二元組的表,每一個二元組的表,每一個二元組中的第一個元素是名字,第二元素就是這個名字在let的第二個參數中表明的值。其他參數將按順序求值,對於整個結構的求值將是最終參數的值數據結構
(cond ((< 3 2) 1) ((< 4 3) 2) (else 3)) 複製代碼
cond的參數是一些二元組,它們將被從頭至尾按順序考慮。若是第一個二元組的第一個元素求值獲得#t,那麼整個表達式的值就是這個二元組的第二個元素的值併發
在以前的幾篇已經提到了兩種求職方式:應用序求值和正則序求值。和大多數命令式語言同樣,Scheme在大多數狀況下都是用應用序求值。函數
若是一個無反作用的函數在其任何一個參數是未定義的狀況下也是未定義的,咱們就稱它爲嚴格。這種函數能夠安全的對全部參數求值,因此其結果也將不依賴於求值順序。oop
惰性求值使咱們能夠獲得正則序求值的優點,回憶一下咱們以前說的,惰性求值對實現無窮數據結構很是有用spa
若是一個函數以函數做爲實際參數,或者返回函數做爲值,那麼它就是一個高階函數。操作系統
好比Scheme的map函數
(map * '(2 4 6) '(3 5 7)) => (6 20 42)
複製代碼
map將對這些表中的一組元素調用相應的函數
高階函數主要的做用就是從現有的函數出發構造新函數
(define total (lambda (l) (fold + 0 1))) (total '(1 2 3 4 5)) (define total-all (lambda (l) (map tatal l))) (total-all '((1 2 3 4 5) (2 4 6 8 10) (3 6 9 12 15))) 複製代碼
Curry化
柯里化是一個常見的操做,是用一個單參數函數取代一個多參數的函數,這個單參數函數返回一個函數
(define curried-plus (lambda (a) (lambda (b) (+ a b)))) ((curried-plus 3) 4) (define plus-3 (curried-plus 3)) (plus-3 4) 複製代碼
除了其它用途以外,這種curry操做還使咱們可以給高階函數傳遞一個部分求值函數
(map (curried-plus 3) '(1 2 3)) => (4 5 6)
複製代碼
無反作用的程序設計是一種很是誘人的想法,從前面的幾篇能夠看出,反作用可能使程序難以閱讀和編譯。
不過,存在着許多經常使用的程序設計慣用形式,最正宗的反作用在其中扮演着核心角色。
咱們關注計算的函數式模型。命令式程序的計算主要是經過迭代和反作用,而函數式程序的計算主要是經過將參數代換到函數中。
函數式語言的相應模型是lambda演算,許多函數式語言傾向於在lambda演算的基礎上擴充一些特徵,包括賦值、I/O和迭代。
若是一個程序包含了多餘一個活動的執行上下文。即多餘一個控制線程,則稱該程序是併發的。併發的出現至少有三方面的重要緣由:
在一個併發程序中,咱們將使用術語線程來指代那些程序員認爲與其餘線程併發的運行的活動實體。在大多數系統中,給定程序的線程是在操做系統所提供的一個或多個進程的頂部實現的。
/*
在任何併發的程序設計模型中,須要處理的兩個最關鍵的問題就是通訊的同步。通訊指線程可用於得到其它線程產生的信息的各類機制。
同步
*/
寫到通常發現很像以前操做系統寫到的進程管理,就再也不重複了。放個連接
這一篇就稍微提了一下除了命令式語言以外的其它範式,還有像如今語言支持的併發模型。可是以前討論的語法、語義、命名、類型和抽象適用於全部語言