<p><b>「讀取-求值-輸出」循環</b>（英語：<span lang="en"><b>Read-Eval-Print Loop</b></span>，簡稱<b>REPL</b>），也被稱做<b>交互式頂層構件</b>（英語：<span lang="en"><b>interactive toplevel</b></span>），是一個簡單的，交互式的編程環境。這個詞常常用於指代一個Lisp的交互式開發環境，也能指代命令行的模式。
</p>


<h2><span id=".E6.A6.82.E8.BF.B0"></span><span id="概述">概述</span></h2>
<p><i>「讀入-求值-輸出」循環</i> 的名字來自於以下幾個Lisp用來實現這種機制的內置函數：
</p>
<ul><li>讀入函數接收一個來自於用戶的表達式，將其解析成資料結構並存入記憶體。例如，用戶可能會輸入一個s-表達式　<code>(+ 1 2 3)</code>，這句話會被解析成一個包含四個元素的鍊表。</li>
<li>求值函數　負責處理內部的資料結構並對其求值。在Lisp中，求一個以函數名開頭的ｓ－表達式意味著對接下來的參數調用那個函數。所以函數"<code>+</code>"被在參數<code>1 2 3</code>上調用，產生結果<code>6</code>。</li>
<li>輸出函數接受求值結果，並將其呈現給用戶。儘管當前的結果「<code>6</code>」並不具有複雜的格式，但如果是一個較為複雜的表達式，那麼它將會被精心處理，以便於更方便地被理解。</li></ul><p>REPL使得探索性的編程和調試更加便捷，因為「讀取-求值-輸出」循環通常會比經典的「編輯-編譯-運行-調試」模式要更快。
</p>
<h2><span id=".E4.BC.98.E7.82.B9"></span><span id="优点">優點</span></h2>
<p>REPL對於學習一門新的程式語言具有很大的幫助，因為它能立刻對初學者做出回應。許多工具集和程式語言使用REPL研究算法、進行調試，比如MATLAB，ROOT（頁面存檔備份，存於網際網路檔案館），SciPy和IPython。Python的doctest模塊能夠通過捕捉自身REPL命令行的輸出使測試代碼更容易地進行。
</p><p>由於 <code>print</code> 函數輸出的數據格式（字符串）與用戶輸入的數據格式（字符串）相同，大多數輸出的結果也可以被帶回到 <code>read</code> 函數作為輸入。然而，有的時候輸出的結果只能代表求值結果而不是求值結果本身，比如一個socket句柄或一些類的實例。比如在Python中使用 <code> &lt;__模块名__.类名 实例名&gt; </code> 這種形式來代表一個實例本身，在Common Lisp當中就使用 <code> #&lt;whatever&gt; </code>的形式。而在CLIM，SLIME以及Symbolics Lisp Machine的REPL卻有辦法讀取很難被完全字符串化的這些對象。他們記錄被輸出過的對象，之後當代碼被讀取時，這些對象能夠被解析並重新被使用。
</p>
<h2><span id=".E5.AE.9E.E7.8E.B0"></span><span id="实现">實現</span></h2>
<p>為了實現一個 Lisp REPL，只需要實現這三個函數和一個不停輪詢的函數即可（當然，求值函數的實現是最為複雜的，因為它在內部要實現像 <code>car</code> 與 <code>+</code> 的原始函數以及像<code>if</code> 一樣的特殊操作符）。這些工作完成了之後，一個基本的REPL就可以用如下的簡單形式表達：<code>(loop (print (eval (read))))</code>。
</p><p>一種實現<code>eval</code>的方式就是實現一個遞歸處理抽象語法樹（該語法樹被 <code>read</code> 函數創建）的函數。另一種可行的方法是將這個抽象語法樹編譯為機器碼並執行。
</p>
<h2><span id=".E4.B8.BB.E8.A6.81.E7.9A.84REPL.E7.BC.96.E7.A8.8B.E8.AF.AD.E8.A8.80.E7.8E.AF.E5.A2.83"></span><span id="主要的REPL编程语言环境">主要的REPL程式語言環境</span></h2>
<p>APL、BASIC、Clojure、F#、Haskell、J、Julia、Perl、PHP、Prolog、Python、R、Ruby、Scala、Smalltalk、Standard ML、Swift、Tcl、Javascript、Java(版本jdk-9起)
</p>
<h2><span id=".E5.A4.96.E9.83.A8.E9.93.BE.E6.8E.A5"></span><span id="外部链接">外部連結</span></h2>
**「讀取 - 求值 - 輸出」循環**（英語：**Read-Eval-Print Loop**，簡稱 **REPL**），也被稱做**交互式頂層構件**（英語：**interactive toplevel**），是一個簡單的，交互式的編程環境。這個詞常常用於指代一個 Lisp 的交互式開發環境，也能指代命令行的模式。

## 概述

 _「讀入 - 求值 - 輸出」循環_ 的名字來自於以下幾個 Lisp 用來實現這種機制的內置函數：

* 讀入函數接收一個來自於用戶的表達式，將其解析成資料結構並存入記憶體。例如，用戶可能會輸入一個 s - 表達式 `(+ 1 2 3)`，這句話會被解析成一個包含四個元素的鍊表。
* 求值函數　負責處理內部的資料結構並對其求值。在 Lisp 中，求一個以函數名開頭的ｓ－表達式意味著對接下來的參數調用那個函數。所以函數 "`+`" 被在參數 `1 2 3` 上調用，產生結果 `6`。
* 輸出函數接受求值結果，並將其呈現給用戶。儘管當前的結果「`6`」並不具有複雜的格式，但如果是一個較為複雜的表達式，那麼它將會被精心處理，以便於更方便地被理解。

REPL 使得探索性的編程和調試更加便捷，因為「讀取 - 求值 - 輸出」循環通常會比經典的「編輯 - 編譯 - 運行 - 調試」模式要更快。

## 優點

REPL 對於學習一門新的程式語言具有很大的幫助，因為它能立刻對初學者做出回應。許多工具集和程式語言使用 REPL 研究算法、進行調試，比如 MATLAB，ROOT（頁面存檔備份，存於網際網路檔案館），SciPy 和 IPython。Python 的 doctest 模塊能夠通過捕捉自身 REPL 命令行的輸出使測試代碼更容易地進行。

由於 `print` 函數輸出的數據格式（字符串）與用戶輸入的數據格式（字符串）相同，大多數輸出的結果也可以被帶回到 `read` 函數作為輸入。然而，有的時候輸出的結果只能代表求值結果而不是求值結果本身，比如一個 socket 句柄或一些類的實例。比如在 Python 中使用 `<__模块名__.类名 实例名>` 這種形式來代表一個實例本身，在 Common Lisp 當中就使用 `#<whatever>` 的形式。而在 CLIM，SLIME 以及 Symbolics Lisp Machine 的 REPL 卻有辦法讀取很難被完全字符串化的這些對象。他們記錄被輸出過的對象，之後當代碼被讀取時，這些對象能夠被解析並重新被使用。

## 實現

為了實現一個 Lisp REPL，只需要實現這三個函數和一個不停輪詢的函數即可（當然，求值函數的實現是最為複雜的，因為它在內部要實現像 `car` 與 `+` 的原始函數以及像 `if` 一樣的特殊操作符）。這些工作完成了之後，一個基本的 REPL 就可以用如下的簡單形式表達：`(loop (print (eval (read))))`。

一種實現 `eval` 的方式就是實現一個遞歸處理抽象語法樹（該語法樹被 `read` 函數創建）的函數。另一種可行的方法是將這個抽象語法樹編譯為機器碼並執行。

## 主要的 REPL 程式語言環境

APL、BASIC、Clojure、F#、Haskell、J、Julia、Perl、PHP、Prolog、Python、R、Ruby、Scala、Smalltalk、Standard ML、Swift、Tcl、Javascript、Java (版本 jdk-9 起)

## 外部連結
"读取-求值-输出"循环