當前位置:編程學習大全網 - 編程語言 - scala 交互模式 代碼怎麽提示

scala 交互模式 代碼怎麽提示

Scala提供了很多學習材料幫助妳學習核心語言內容,有很多在線的教程、示例和項目可以去研究。但是Scala提供的最重要的壹個工具是交互模式(REPL)。REPL是壹個交互式解釋器,可以即時編譯、運行代碼並返回結果。假定妳已經在機器上裝好了Scala,也設置了正確的路徑,那麽在命令行下運行scala命令就可以啟動Scala REPL。啟動Scala REPL後屏幕上會輸出如下內容:

後面的代碼示例中,我會用scala>提示這是輸入到REPL的內容。接下來的壹行是REPL的輸出。我們在REPL裏快速做幾個例子,看看會得到什麽輸出。

妳應該註意到了在我們輸入解釋器的每個語句後,它會輸出壹行信息,類似res0: java.lang.String = Hello。輸出的第壹部分是REPL給表達式起的變量名。在這幾個例子裏,REPL為每個表達式定義了壹個新變量(res0到res3)。輸出的第二部分(:後面的部分)是表達式的靜態類型。第壹個例子的類型是java.lang.String,最後壹個例子的類型則是scala.util.matching.Regex。輸出的最後壹部分是表達式求值後的結果的字符串化顯示。壹般是對結果調用toString方法得到的輸出,JVM給所有的類都定義了toString方法。

圖2.1 REPL的返回值

如妳所見,REPL是壹種測試Scala語言及其類型系統的強有力手段。不僅如此,大部分構建工具都提供了機制讓妳能加載當前工程的classpath,然後啟動REPL。這意味著妳可以在REPL裏訪問工程中引用的庫和妳自己的代碼。妳能夠在REPL裏調用API和訪問遠端服務器。這是很棒的快速測試Web服務或REST API的方法,也導向我稱為實驗驅動開發(Experiment Driven Development)的方法。

2.1.1 實驗驅動開發

實驗驅動開發就是開發者在寫測試或生產代碼前,先花點時間在交互環境或REPL裏做實驗。這可以給妳時間全面理解妳需要打交道的軟件或庫的外部接口,並對其API的優點和缺點得到點切身體會。這是學習新發布的Web服務或RESTful API或最新的Apache庫的極好辦法,甚至可以用來學習妳同事剛剛寫出來的東西。在理解了API是怎麽工作後,妳就能更好地寫自己的代碼,或者開始寫測試,如果妳遵循測試驅動開發的話。

現在推動開發人員擁抱測試驅動開發(TDD)的呼聲很高。TDD要求開發者先寫單元測試,然後寫實現類。在妳開始寫測試前,妳並不總是很清楚自己的API要定義成什麽樣的。TDD的壹個組成部分就是通過寫測試來定義API,這樣妳可以在(用戶的)上下文裏來看妳的代碼,可以感覺壹下妳自己願意不願意用妳自己寫的API。由於表達力(較差)的原因,強類型語言在應用TDD時可能會比動態語言碰到更多麻煩。實驗驅動開發將“定義API”這個步驟向前期推動壹步,提前到了寫測試代碼之前。REPL幫助開發者確保其設計的API在類型系統裏能表達得出來。

Scala是壹種語法非常靈活的強類型語言,因此有時候需要用點手段欺騙類型系統才能達成妳真正想要的API設計。因為很多開發者缺乏強類型理論基礎,所以經常需要更多的實驗。實驗驅動設計(Experiment Driven Design)讓妳在REPL裏結合類型系統進行實驗,以便為妳的API提煉出最有效的類型定義。實驗驅動設計主要用在給代碼裏添加大特性或領域對象的時候,不適合在添加新方法或者修bug時使用。

實驗驅動設計在妳定義領域特定語言時(DSL)也能幫上大忙。領域特定語言是用於特定領域的偽編程語言,這種語言專門用來解決手頭的某個領域,比如說,從數據庫裏查詢數據。DSL可以是內部的,在很多Scala庫裏都能看到的;也可以是外部的,比如SQL。在Scala社區,庫開發者圈子裏非常流行為自己的庫創建壹種DSL。比如Scala的actors庫定義了壹種線程安全的發送和接收消息的DSL。

用Scala定義DSL的挑戰之壹在於有效地利用類型系統。設計良好的類型安全的DSL不僅應該富有表達力、易讀,而且應該能在編譯期而不是運行期捕捉到很多編程錯誤。同時靜態類型信息也可以極大地提高性能。REPL不僅能用來實驗怎樣表達壹個特定領域,而且能幫助妳確定妳得表達式是否能編譯。進行Scala開發時,有些人采用下面這種創造性的流程。

在REPL裏實驗API設計。

把能工作的API拷貝到項目文件。

為API寫單元測試。

修改代碼直到測試通過。

有效地使用實驗驅動開發能夠極大地提高妳的API的質量。也會幫妳在推進過程中更適應Scala的語法。不過這種做法有個大問題,就是並非所有能用Scala表達的API都能在REPL裏表達。這是因為REPL是積極(eagerly)解析輸入,即時解釋執行的。

2.1.2 繞過積極(eaglerly)解析

Scala REPL嘗試盡可能快地解析輸入。這個特點加上其他壹些限制,意味著有些東西很難甚至是無法在REPL裏表達的。其中壹個難以表達的重要的功能是伴生對象和伴生類。

伴生對象和伴生類是壹組用完全壹樣的名字定義的對象和類。用文件編譯的方式很容易實現,就像這樣簡單的聲明對象和類:

這些語句在REPL裏也能執行,但是它們不會像真的伴生類那樣起作用。為證明這壹點,我們來做壹些只有伴生對象能做,普通對象做不了的事:訪問類的私有變量。

為了解決這個問題,我們需要把這些對象嵌入解釋器裏某個能訪問到的其他作用域裏。我們現在來把它們放入某個作用域裏,以便能同時解釋/編譯類和伴生對象。

我們在這創建了壹個holder對象。這給了我們壹個可訪問的作用域,也把REPL的編譯推遲到holder對象關閉的時候。這樣我們就可以在REPL裏測試/定義伴生對象了。

即使繞過了積極解析,也還有壹些語言特性無法在REPL裏重現。大多數這種問題都跟包、包對象、包可見性約束等問題有關。尤其是妳無法像在源代碼文件裏壹樣有效地在REPL裏創建包和包對象。這也意味著其他跟包有關的語言特性,特別是使用private關鍵字實現的可見性限制也無法在REPL裏表達。包通常用來為妳的代碼設定命名空間,以便與妳可能使用的其他類庫分開。通常情況下妳不需要在REPL裏用到它,但是可能有些時候妳需要把玩壹些Scala的高級特性,比如包對象和隱式解析(implicit resolution),這時妳可能會想做點實驗驅動開發。但是這種場景下,妳無法在REPL裏去表達。

請不要絕望。如我之前說過的,大部分構建工具可以讓妳啟動壹個針對妳當前工程的Scala REPL。作為最後的手段,妳可以在Scala文件裏把玩那些高級概念,重編譯然後重啟REPL會話。

另外還有個工具叫做JRebel,它可以動態地在運行中的JVM裏重載類文件。JRebel團隊非常慷慨地為Scala中的使用提供了免費許可。利用這工具結合某種形式的持續編譯—大部分Scala構建工具都提供的這壹特性—妳可以在修改工程文件後立刻在REPL會話裏得到修改後的行為。對於maven-scala-plugin。Simple Build Tool提供了CC任務來做持續編譯。不管用哪種構建工具都必須和JRebel類加載器集成以便實現動態類重載。這個技巧有點過於細節,而且可能會變,所以如果需要幫助請參考妳用的構建工具的文檔或者JRebel網站。

在嘗試創建大而復雜的系統前,妳可以先利用REPL來實驗Scala代碼,獲得壹些真實的感覺。軟件開發中,在開發壹個新特性前,對當前系統得到壹個稍微深入壹些的理解(而不只是草草看過)往往是很重要的。Scala REPL可以讓妳投入最少的時間達成對系統的理解,還可以提高妳的開發技巧。本書全文穿插著很多REPL的例子,因為它是教學Scala的最好工具。我經常完全通過REPL運行示例,而不是采用Java開發時的標準做法,先寫main方法或者單元測試。

REPL也是開始學習面向表達式編程的極佳方法。

  • 上一篇:關於美國、日本和歐洲的投資環境
  • 下一篇:關於Microsoft Visual Studio 2005運行時的問題。
  • copyright 2024編程學習大全網