1. 程式人生 > >PL真有意思(八):其它程式設計模型

PL真有意思(八):其它程式設計模型

前言

在之前幾篇我們討論的語法、語義、命名、型別和抽象適用於所有語言。然而我們的注意力都主要集中在命令式語言上,現在這篇來看看其它正規化的語言。函式式和邏輯式語言是最主要的非命令式語言。

函式式語言

命名和作用域問題出現在各種模型中,還有型別、表示式和選擇與遞迴等控制流概念等等。所有語言都必須經過掃描、語法分析和語義分析,

函式式程式設計的概念

函式式程式設計將一個程式的輸出定義為其輸入的一個數學函式,在其中沒有內部狀態的概念,因此也沒有副作用。函式式提供了一下特徵,其中許多都是命令式語言中沒有的:

  • 第一級的值和高階函式
  • 廣泛的多型性
  • 表型別和表操作
  • 結構性的函式返回
  • 結構性的物件的建構函式
  • 廢料收集

Scheme

我們以Scheme為例子,來看一下概念

約束

(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在大多數情況下都是用應用序求值。

嚴格求值和惰性求值

如果一個無副作用的函式在其任何一個引數是未定義的情況下也是未定義的,我們就稱它為嚴格。這種函式可以安全的對所有引數求值,所以其結果也將不依賴於求值順序。

惰性求值使我們可以得到正則序求值的優勢,回憶一下我們之前說的,惰性求值對實現無窮資料結構非常有用

高階函式

如果一個函式以函式作為實際引數,或者返回函式作為值,那麼它就是一個高階函式。

比如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和迭代。

併發模型

如果一個程式包含了多餘一個活動的執行上下文。即多餘一個控制執行緒,則稱該程式是併發的。併發的出現至少有三方面的重要原因:

  • 為了反映一些問題的邏輯結構。許多程式,必須同時維護一批在同一時間基本相互獨立的作業的軌跡
  • 利用額外的處理器以提高速度
  • 為了應對相互獨立的多臺物理裝置

併發程式設計基礎

在一個併發程式中,我們將使用術語執行緒來指代那些程式設計師認為與其他執行緒併發的執行的活動實體。在大多數系統中,給定程式的執行緒是在作業系統所提供的一個或多個程序的頂部實現的。

/*

通訊和同步

在任何併發的程式設計模型中,需要處理的兩個最關鍵的問題就是通訊的同步。通訊指執行緒可用於獲得其它執行緒產生的資訊的各種機制。

同步

*/

寫到一般發現很像之前作業系統寫到的程序管理,就不再重複了。放個連結

程序管理

程序排程

總結

這一篇就稍微提了一下除了命令式語言之外的其它正規化,還有像現在語言支援的併發模型。但是之前討論的語法、語義、命名、型別和抽象適用於所有語