REBOL

REBOL（發音reb-ol 'reb-ol，英文Relative Expression Based Object Language的縮寫），自R3發行版改稱為Rebol，是跨平台的數據交換語言和多范型的動態程式語言。由AmigaOS的系統架構師Carl Sassenrath設計，用於網路通信和分布式計算。

## 簡介

REBOL介入了方言化的概念：用於代碼和數據的小型的、優化的領域特定語言，據設計者Carl Sassenrath所說這是這個語言最顯著的性質：「儘管它可以用於編程、寫函數和進行處理，它最大的長處是輕易的建立領域特定語言或方言的能力。」

知名於JavaScript開發上貢獻的道格拉斯·克羅克福特，曾經描述Rebol為是對JSON有影響者之一：「更加現代的語言，但具有一些非常類似於Lisp的想法，它全部建造在數據表示之上，然後再被作為程序執行。」

最初，這個語言和它的官方實現，是REBOL技術公司開發的專有和封閉原始碼的軟體。經過跟Lawrence Rosen的討論，Rebol版本R3解釋器於2012年12月12日在Apache 2.0許可證下發行。老版本能以二進位形式獲得到，沒有發行它們的原始碼的規劃。

Rebol已經被用於編程網際網路應用（客戶端和伺服器端二者）、資料庫應用、實用工具和多媒體應用。

## 實例

Rebol的設計原理之一就是「以簡單方式做簡單的事情」。使用下面的「可視界面方言」例子來描述一個具有圖形使用者界面的簡單的Hello world程序：

```smalltalk
view layout [text "Hello world!" button "Quit" [quit]]
```

使用R3-GUI的類似的例子：

```smalltalk
view [text "Hello world!" button "Quit" on-action [quit]]
```

<image>

## 方言

Rebol的領域特定語言叫做「方言」，是為特定用途優化的微型語言。方言可以用來定義業務規則、圖形使用者界面或在程序安裝期間的螢幕序列。使用者可以定義他們自己的方言，重用任何現存的Rebol單詞並給予它在方言中的特殊含義。方言是有處理Robol塊的函數以特殊方式解釋的。

Rebol的方言能力的例子可以從單詞`return`看出來。在「數據交換方言」中`return`就是個沒有任何特殊含義的單詞。在「執行方言」中, `return`是個全局變量，指稱傳遞迴一個函數結果值的一個原生函數。在「可視界面方言」（VID）中`return`是一個關鍵字，導致布局引擎去模擬一個回車返回，移動「呈現筆」下至下一行的開始處。

具有圖形能力的Rebol解釋器必須理解和解釋很多方言。下表按重要性依次列出最主要的方言。

方言名字｜解釋於｜用途

數據交換方言｜`load`函數｜表示數據和元數據；Rebol方言的共用平台

執行方言｜`do`函數｜編程

解析方言｜`parse`函數｜模式匹配

函數規定方言｜`make`函數｜函數定義；函數式編程

對象規定方言｜`make`函數｜對象定義/繼承；基於原型編程

可視界面方言或RebGUI｜`layout`函數或`display`函數｜指定圖形使用者界面

繪圖方言｜`view`函數｜定義圖形元素（直線、多邊形等）

腳本規定方言｜`do`函數｜腳本定義

安全政策方言｜`secure`函數｜指定安全政策

## 語法

Rebol的語法 (程式語言)是自由形式的，不要求特殊定位。但是，通常使用縮進來更好將文本結構傳達給人類讀者。

不同方言的語法屬性可以不同。對於所有Rebol方言的公共平台是「數據交換方言」；其他方言通常從它派生。除了是所有方言的公共平台之外，「數據交換方言」直接用來表示數據和元數據、遷移（populate）數據結構，在網際網路上發送數據，並把它們保存在數據存儲中。

對比於程式語言比如C，「數據交換方言」不構成自聲明、語句、表達式 (電腦科學)或關鍵字。有效的「數據交換方言」文本流是樹數據結構，構成自塊（根塊是隱含的，子塊由方括號界定符），圓塊（圓括號界定）、字串（雙引號或適用多行字串的花括號來界定；脫字符表示法用於不可列印字符）、URL、e-mail地址、文件、路徑或其他複合值。不同於ALGOL的塊，Rebol的塊是複合（composite）值，類似於Lisp中引用起來的表達式。代碼以Rebol塊的形式寫成的事實，使語言具有同像性。

塊還有圓塊可以包含由空白分隔的其他複合值（一個塊可以包含子塊、圓塊、字串等等)或標量值比如：`word`（單詞）、`set-word`（後綴著冒號的單詞）、`get-word`（前綴著冒號的單詞）、`lit-word`（前綴著撇號的單詞），數字、錢款、字符等。注意在單詞中允許特殊字符，所以`a+b`是一個單詞，不同於`a + b`，它是空格分隔的三個單詞。

注釋可以出現在分號之後直到行結束。多行注釋或不被詞法分析器忽略的注釋，可以使用平常的數據類型比如多行字串來書寫。

## 語義

塊包含領域特定語言，它可以作為實際參數提交給特定的「求值器」函數。

### do

最常用的求值器是`do`函數。它被預設的用來解釋給解釋器控制台的文本輸入。

由`do`函數解釋的「執行方言」，是一個面向表達式程式語言的「數據交換方言」的子語言。語言的主要語義單元是表達式 (電腦科學)。對比於派生自ALGOL的指令式程式語言，「執行方言」既沒有關鍵字也沒有語句。

單詞被用作大小寫不敏感變量。像在所有動態類型語言中那樣，變量沒有關聯的類型，類型是關聯於值的。在`do`函數遇到一個單詞的時候，返回對這個單詞的求值結果。`set-word`單詞可以用於賦值。儘管沒有語句，賦值和有副作用的函數在一起，可以用於指令式編程。

根塊的子塊自行用`do`求值。塊作為解釋器實際參數這個性質被用來處理數據塊，通過把塊作為實際參數提交給控制函數如`if`、`either`、`loop`等用於結構化編程，在把塊傳遞給特定解釋器函數時用於方言。

值得注意的特殊問題是賦值給變量的複合值是不複製的。要製作一個複本，這個值必須傳遞給`copy`函數。

`do`函數通常服從前綴表示法求值，這裡函數處理跟隨在其後的實際參數。但是，也存在使用中綴算符的中綴求值。中綴求職優先於前綴求值。例如：

```
[[绝对值|abs]] -2 + 3
```

返回`1`，因為中綴加法優先於計算絕對值。在求值中綴表達式的時候，求值的次序是從左至右，沒有算符優先於其他算符。例如

```smalltalk
2 + 3 * 4
```

返回`20`，對於乘法優先於加法的求值這將產生14。所有演算法都有前綴版本。`Do`在將實際參數傳遞給函數之前通常對實際參數進行求值。所以，下列表達式：

```text
print read http://zh.wikipedia.org/wiki/Rebol
```

首先讀取維基百科的Rebol頁面，接著把結果傳遞給`print`函數。圓括號可以用來改變求值的次序。使用前綴表示法，可以避免使用圓括號。

這種簡單的優先級規則有如下優勢：

- 不需要在寫表示式的時候查看優先級表格。
- 不需要在定義新算符的時候重寫優先級表格。
- 表達式可以輕易的從中綴轉寫成前綴表示法或反之。

還有一個劣勢：

- 習慣了常規優先級規則的使用者容易出錯。

### parse

`parse`函數適合用於規定、驗證、變換和解釋方言。它通過在運行時間匹配「解析表達式」來完成工作。

「解析表達式」是使用「解析方言」來書寫的，它類似於「執行方言」，是「數據交換方言」的面向表達式的子語言。不同於「執行方言」，「解析方言」使用關鍵字來代表算符和大多數重要的非終結符，中綴分析算符沒有前綴等價者並使用優先級規則（序列優先於選擇）。

動作也可以被包含而在解析處理期間進行，並且`parse`函數可以被用來處理塊或字串。在「字串解析」層級，`parse`必須處理「低層」解析，需要考慮到字符和界定符。「塊解析」是更高層級，處理在Rebol值的級別上的掃描。

解析方言屬於由自頂向下解析語言或解析表達文法（PEG）為代表的文法家族。主要的類似性是所有家族成員都有序列和選擇算符的出現。解析方言的語法和在解析方言和PEG之間的類似性可以用分析算術表達式的PEG示例的如下轉寫來展示：

```smalltalk
Digit: charset [#"0" - #"9"]
Value: [some Digit | "(" Expr ")"]
Product: [Value any [["*"| "/"] Value]]
Sum: [Product any [["+"| "-"] Product]]
Expr: Sum
parse/all "12+13" Expr
```

## 外部連結

- Computers/Programming/Languages/REBOL
- A REBOL tutorial
- Rebol 3 Tutorial

## 基本資料

- 日語原文：Rebol
- 編程范型：面向語言、數據交換、同像性、指令式、函數式、基於原型
- 發行時間：1997年
- 設計者：Carl Sassenrath
- 開發者：REBOL技術
- 類型系統：動態、強類型
- 許可證：2.7.8為免費重新發布軟體、R3為Apache 2.0許可證
- 文件擴展名：.r, .reb
- 受影響於：Self, Forth, Lisp, Logo
- 施影響於：JSON, Red (程式語言)
- 作業系統：跨平台
- wikibooks：Rebol Programming