Falcon

**Falcon 程式語言**（英語：**The Falcon Programming Language**），又稱 **Falcon P.L.**、**Falconpl** 或 **Falcon**，是一個開源、多範式程式語言，其設計和推廣由 Giancarlo Niccolai 領導。

## 歷史

Haste 於 2002 年編寫一個小型項目，用以實現一小型虛擬機，該項目很快的發展成 Falcon 語言。2008 年，此語言以開源項目的方式成為 Ubuntu 的附加軟體，並且被包含在 Kross。

## 核心

不同於關注於一個編程風格或範式（paradigm），Falcon 在一個簡單的框架（framework）里融合了幾種不同的風格。在實現級別上，Falcon 是「服務概念」驅動，當不作為一個單一的工具被使用時指令碼引擎被看做一個服務指令碼，模組和內嵌的應用。

## Hello Falcon

儘管有各種形式的基本 I/O，一個 "hello world"（全世界朋友你好！）例子使用 _fast print_(快速列印):

```
> "Hello World!"
```

Unicode 支援，下面是一個國際化例子的介紹：

```
// International class; name and street
class 国際(なまえ, Straße)
   // set class name and street address
   नाम = なまえ
   شَارِع = Straße
   // Say who am I!
   function 言え!()
     >@"I am $(self.नाम) from ",self.شَارِع
   end
end
// all the people of the world!
民族 = [国際("高田 Friederich", "臺灣"),
   国際("Smith Σωκράτης", "Cantù"),
   国際("Stanisław Lec", "południow")]
```

```
for garçon in 民族：garçon.言え!()
```

### 資料類型

* Nil - The _nil_ 關鍵字，一個空值.
* Integer - 一個 64 位元整數值.
* Numeric - 一個 IEEE 64 位元浮點值.
* Range - 一組上限，下限和步長.
* MemBuf - Raw 記憶體緩衝，每一個位址是一個無符號的 1,2,3, 或者 4 位元組整數.
* Function - 函式（可呼叫實體）.
* String - 不定長的 UNICODE 字元序列 (但是它們能作為位元組緩衝被使用).
* Array - 不定長的元素序列.
* Dictionary - 不定長有序鍵 / 值對的集合；鍵能是任何 Falcon 元素.
* Object - 來源於類別的實例或者單一的非類物件.
* Class - 能建立實例的類，實體.
* Method - 實例的不變部分，使用函式形式關聯.

## 範式

Falcon 融合六種_主流_編程範式。

* 程序式（procedural）
* 函數式（functional）
* 物件導向（object oriented）
* 面向原型物件（prototype OOP）
* 訊息導向（message oriented）
* 表格化編程（tabular programming）

### 程序式

程序式編程通過典型的函式聲明和呼叫被支援。每一個函式支援隱式變數參數呼叫和占位參數（Positional Parameters）命名參數（Named Parameters）。提供了一套程序式風格的語句（如 for, while, if, switch 語句）。

下面，一個完整的程序式程式，突出一部分在 **Falcon** 里用來減少一些編程任務中原生的 pre-body-post（前置 - 本體 - 後置）處理的困擾的設計理念

```
function sayList( saying )
   for elem in saying
       >> elem
       formiddle: >> " "
       forlast: > "!"
   end
end
```

```
sayList( List("Have", "a", "nice", "day") )
```

### 函數式

Falcon 有個稱為 Sigma-reductor 的求值引擎，它允許程式人員編寫純函數式程式，看起來和用 Lisp 沒什麼不同。混合式編程風格允許在函數式語句序列使用不同的範式（例如 OOP 或者程序化），或者在不同的程序化方式期間中使用函數式求值。

函數式語句序列被描述為標準語言陣列；交叉不同的求值和在 Sigma-reduction 求值方式期間這都意味著語句序列能被程式本身建立，審查和被動態修改。下面的例子在列表迴圈呼叫 _late binding_ 修改一個指定變數的參照。

```
 pnext = [ printl, '"', &value, '"' ]
```

```
 dolist( function(p); seq.value = p; eval(seq); end,
         ["Have", "a", "nice", "day"] )
```

如果他們第一個成員變數是一個自身可呼叫元素，標準陣列作為函式被呼叫，如下面的例子。

```
 [printl "Prompt> "]( "Real data to print" )
```

同一個級別函數式語句序列（如在上面例子）能被作為儲存的呼叫來按照定義處理，並且一次性分配給一個變數，它們在語意上等同於一個函式符號。

函數式範式包含一個 _out of band_ 元素標記。元素能接收一個通過語言運算子和函式被測試的 _oob_ 特徵標記，並且當在函數式語句序列中移動時指明一個特殊含義的值。例如，很多函數式迴圈，如 _floop_ 和 _times_，能重新開始執行迴圈，或者被從包含的函式返回的無論 _1_ 或 _0_ 的 out of band 中斷。_map_ 函式通過一個對映函式轉換一個陣列中的所有值，如果它是一個 _nil_out of band 將忽略返回值（丟棄它）；通過這個方法可以在某處執行對映和過濾。

### 物件導向

通過類，一個繼承模型，靜態類別成員，屬性初始化和實例構造器，Falcon 程式語言提供一個 OOP 範式。在至多一個潛在的父類別是被反射成原生資料的條件下支援多繼承。存取基礎類別成員被支援。

實例的結構是固定和不變的，但是由於 Falcon 函數式特質，函式看上去就是一種特定種類的資料，它能動態設定實例成員為無格式資料或者函式（變成他們的方法）。

Falcon 支援單一物件，可能是 classless 或者父類別衍生，在虛擬機器執行主指令碼之前實例化和被準備。在可能涉及程式模組中一個在其他的物件時，實例消除順序由 Falcon 連結器追蹤以確保單一物件的適當的初始化。

通過函數式語句序列類別實例能被建立，如實例化的一個類在語意上等於呼叫它的符號，因此，對一個第一個元素是一個類的函數式語句序列求值，它有建立一個實例的效果。

Falcon 的 OOP 模型完整支援運算子多載，它允許建立一個針對數學和邏輯的擁有指定的行為運算子的類。

### 面向原型物件

原型 OOP 比 OOP 更簡單，但它去掉類的概念。實例全是 classless，他們的結構能被動態改變。Falcon 語言字典（排列好的鍵 / 值集合）能包含函式，那時字典能被_祝福_，通知語言他們作為 classless 實例被處理，並且使用_點存取符_使他們的值作為屬性或方法被處理。在下面的例子，一個字典變成一個物件：

```
dict = bless([ 'state' => 0, 'incme' = > function(); self.state++; end ])
dict.incme()
> dict.state  // will print '1'
```

簡單地執行繫結的陣列。

```
array = [1,2,3]
array.showMe = function()
   for item in self
       > item
   end
end
```

```
array.showMe()
```

### 訊息導向

當一個訊息被廣播時訊息導向編程允許間接呼叫一個或者更多註冊的監聽器。訊息的內容是任意的並且能包含任何語言元素，包括但不限於哪個建立建立實例的類，函式序列或者表。監聽器不是完整接受訊息和執行他們，就是通過有次序的步驟分享在構建中的一個訊息的通用應答。訊息能被廣播和包含一個即時的應答或者能被儲存在環境用來接收和處理更多的後來者（在 **Falcon** 里被稱作_斷言_）。

訊息導向編程擁有一個在虛擬機器里的直接介面，關於擴充原生模組和嵌入應用能相互作用。例如，一個多執行緒應用可能拋給虛擬機器來自不同的執行緒訊息，為了在指令碼級別上序列化處理和稍後廣播直接來自指令碼的處理解決方案。

### 表格化

表格式編程能看做是一種 OOP 編程的特殊擴充，一個類通過一個表格被描述，他們的列是屬性，每一行是一個實例。不同於一起保持全部實例，允許每個實例影響父表周圍的行，關於表的修改被動態反射到每個實例。

表格提供一個方法來在有限選擇的集合之間選擇行為，或者混合行為並合併它們，提供模糊邏輯引擎。如每一行，實質上的一個 Falcon 陣列，能包含表中資料和邏輯或者私有邏輯（通過陣列繫結），在表格里一個通過全域選擇邏輯選擇的實體能提供專門的處理能力。

## 特性

隨著多範式編程，**Falcon** 為編程人員呈現多種多樣的特色。

### 模板檔案

通過預處理符號**<? .. ?>**或者**<?fal .. ?>**，**Falcon** 允許指令碼成為文字文件的一部分，、。儲存為 ".ftd" 的指令碼被作為一個文字檔案來處理並且在遇到其中一個預處理符號之前簡單輸出。下面的_.ftd_ 例子裡包含其中的指令碼被執行：

```
  You called this script with <? print( args.len() ) ?> parameters.
```

FTD 檔案能通過標準 Falcon 指令碼被整合到各式應用，在動態模板（FTD 檔案）中的是表現邏輯，應用邏輯被儲存在 Falcon 模組。

FTD 檔案能被用來驅動動態網站，一些流行的網頁伺服器（當前的 Apache 2），擁有直接分析和執行 ".fal" 和 ".ftd" 指令碼的模組，提供整合到網頁伺服器引擎的一個 API。用 CGI 指令碼也能使用動態 FTD 頁面。

### 異常

**Falcon** 由 _raise_, _try_ 和 _catch_ 語句支援錯誤處理。raise 語句能丟擲任何 Falcon 元素，包括 Nil，numbers, strings, objects 等等。庫函式和擴充模組將通常引發錯誤類別的實例，或者衍生自他的實例。

catch 語句能擷取任何類型的元素，一個某種類型（如 string（字串）或 interger（整數）），或者某種類別的實例。擷取的類被按層次組織，所以它能像下面的例子一樣支援更多一般性錯誤處理（_TypeError_ 是一個衍生自 _Error_ 類別館）:

```
try
   ... code that can raise ...
catch TypeError in error
   ... if we mixed up types ...
catch Error in error
   ... another generic error ...
catch StringType in error
   ... an explicit raise "something" was issued ...
catch in error
   ... no idea of what has been raised.
end
```

catch 語句中的 _in_ 子句是可選的（這意味著錯誤可以忽略自身）。

_catch_ 語句模仿 _select_ 語句，能被用一個給出的類型或者類轉向。

### 可嵌入執行時

使用可連結執行時庫 _libfalcon_，**Falcon** 被設計成可嵌入和可延伸其他系統的。

### 文件生成器

**Falcon** 裝載著一個整合的文件系統，叫做 _faldoc_，是特別設計來提供可維護的文件的 Falcon 基礎庫（是原生 C++ 代碼或者用 Falcon 編寫的模組）。

### 虛擬檔案系統

所有發生在引擎或者虛擬機器（指令碼執行器）等級的 I/O 操作被委派給一個中央虛擬檔案系統組件（centralized Virtual Filesystem Provider），外部模組或者可嵌入的應用裝置被允許動態註冊。訂閱的虛擬檔案系統抽象 I/O 操作如目錄讀取，建立檔案和打開流，通過 URI 能在指令碼內部定址。這使得他能從任何 VFS（如網路資源或者壓縮加密的檔案）讀取模組或者打開資源，通過第三方模組且或通過嵌入引擎的應用程式可以包含特殊的虛擬位置的支援。

### 並行支援

在更新到 0.8.x 版本，_Threading_ 模組提供指令碼完整多執行緒。執行緒模型是_面向代理（agent oriented）_ ，跨執行緒資料必須通過幾種可行共享機制明確地共享。每一個執行緒執行一個不同的虛擬機器，分離的執行發生在其內部任何操作（如垃圾回收）。這允許有效的並列處理和在指令碼開發者控制之外的 0 競爭。

### 協同處理

**Falcon** 支援准並行協同處理。協同處理是指通過虛擬機器在同一時間片或者在空閒時間裡執行代碼。它們支援一個接近於完整執行緒模組的更輕量級的並行處理，通過不同的協同處理允許程式的全域資料完全可見。除了每個協同處理的合作，（如在排程讀取之前每個協同處理必須檢查資料可用性）。

### 元編譯器

'_Falcon_ 編譯器有一個支援宏展開的元編譯器，在一個標準編譯器中元編譯器由 Falcon 虛擬機器驅動；自元編譯器生成的輸出被傳送到語言的語法剖析器就像他是原始代碼的一部分。使用 **\[ ...\]**登出序列，通過列印他能動態記錄被編譯的程式內容。

```
 \[ printl( "printl( 'Hello world' )" ) \]
```

_macro_ 關鍵字提供一個簡單的轉到編譯時元程式設計的_語法糖果（candy-grammar）_ 介面。

### 原生國際化

用一個字首 'i' 的字串被認為是一個輸出（國際化）字串。在一個模組中通過使用 _directive_ 語句聲明使用的語言，它能指示哪個字串用什麼自然語言編寫，如下面的例子：

```
 directive lang=fr_FR           // uses 5 characters ISO language code
```

```
 > i"Bonjour à tout le monde!"
```

一個命令列工具 _fallc_ 被用來輸出 'i' 字串到 XML 定義檔案，能被作為模板來支援翻譯到不同的語言。

在讀取模組的時候一個已翻譯的字元表被應用到模組。

## 特色

完整地支援模組化編程，**Falcon** 裝載著_特色（Feathers）_ ，標準模組套件。_特色（Feathers）_ 模組當前包括：

* 編譯器 - 反射型編譯器和動態外掛程式引導器。
* 組態剖析器 - 完成設定檔分析支援。
* MXML - 非常快速和簡潔的_迷你_ XML 剖析器（相容 XML 1.0）。
* 正規表示式 - PCRE 7.x 相容正規表示式庫介面。
* 通訊端（Socket） - BSD 通訊端跨平台網路支援。
* ZLib - 簡潔的壓縮程式介面。

## 實現

核心 VM 和官方模組，（包括特色模組和社群提供支援的模組）都是用 C++ 編寫。一些非常底層的模組和引擎元素是用 C 和組譯編寫。

## 可用資源

在 Mac OS X 和 MS-Windows 系統上 Falcon 通過安裝程式釋出，構建和安裝是一個清晰的過程，或者在各種開源系統如 Linux 或 OpenSolaris 上通過自構建原始碼包。

在後者系統上，_Falcon 程式語言_通常支援各種發行版本並保持更新的，其中有：

* Ubuntu
* Fedora
* Gentoo
* Slackware
* Arch Linux

在基於 Solaris 系統的發行版本上通過 Blastwave 專案和 OpenSolaris 系統的（英文） [AuroraUX http://en.wikipedia.org/wiki/AuroraUX] 發行版本 Falcon 程式語言是可用的。

## 參考

## 外部連結

* Falcon 網站（頁面存檔備份，存於網際網路檔案館）
* 文件（頁面存檔備份，存於網際網路檔案館）
* Falcon community wiki（頁面存檔備份，存於網際網路檔案館）
* Falcon community 論壇
* linuxjournal 上的相關文章
* 發表在 Free Software Magazine