热门问题
时间线
聊天
视角

讀取-求值-輸出迴圈

来自维基百科,自由的百科全书

Remove ads

「讀取-求值-輸出」迴圈(英語:Read-Eval-Print Loop,簡稱REPL),也被稱做互動式頂層構件(英語:interactive toplevel),是一個簡單的,互動式的編程環境。這個詞常常用於指代一個Lisp的互動式開發環境,也能指代命令列的模式。

概述

「讀入-求值-輸出」迴圈 的名字來自於以下幾個Lisp用來實作這種機制的內建函式:

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

REPL使得探索性的編程和除錯更加便捷,因為「讀取-求值-輸出」迴圈通常會比經典的「編輯-編譯-執行-除錯」模式要更快。

優點

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

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

Remove ads

實作

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

一種實作eval的方式就是實作一個遞迴處理抽象語法樹(該語法樹被 read 函式建立)的函式。另一種可行的方法是將這個抽象語法樹編譯為機器碼並執行。

主要的REPL程式語言環境

APLBASICClojureF#HaskellJJuliaPerlPHPPrologPythonRRubyScalaSmalltalkStandard MLSwiftTclJavascriptJava(自JDK 9起)

外部連結

Loading related searches...

Wikiwand - on

Seamless Wikipedia browsing. On steroids.

Remove ads