scala中如何編寫自定義的流程式控制制結構

来源:http://www.cnblogs.com/honeybee/archive/2016/03/21/5302513.html
-Advertisement-
Play Games

scala是一種函數式編程風格的語言,除了常見的if......else ,for ,while等傳統的流程式控制制結構,也可以自定義流程式控制制的控制結構。 再瞭解scala如何實現編寫新的流程結構,我們瞭解一下頭等函數的概念; scala的函數是頭等函數(first-class function).你不


scala是一種函數式編程風格的語言,除了常見的if......else  ,for ,while等傳統的流程式控制制結構,也可以自定義流程式控制制的控制結構。

再瞭解scala如何實現編寫新的流程結構,我們瞭解一下頭等函數的概念;

scala的函數是頭等函數(first-class function).你不僅可以定義和調用函數。還可以把他們寫成匿名的字面量(Iiteral),並把他們作為值(value)傳遞。

在擁有頭等函數的語言中,即使語言的語法是固定的,你也可以有效地製作新的控制流程結構,可以使用創建帶函數參數的方法來做到這點;另一種方法是

使用用花括弧代替小括弧的機制。

(一)使用創建帶函數參數的方法來編寫新的控制結構

下麵是"雙倍"控制結構的實現,能夠重覆一個操作兩次並返回結果:

def twice(op: Double => Double,x: Double) = op(op(x))

#調用方法
twice(_ + 1,5)

twice函數解析:該函數有2兩個參數,
第一個參數是function,作用是把一個double轉化成另一個double。
第二個參數double類型的數字。
op(x)的意思是調用op對象的apply() 方法,由於op是函數值對象,所以op(x)的意思是,將x應用為op函數的參數。

所以 twice(_ + 1,5) 的返回值是 7.

 

當你在代碼中發現,有個重覆的控制模式時,就可以考慮把這些重覆的控制模式實現成一個新的控制結構。

文件操作是的流程是:打開一個資源,對它進行操作,關閉資源。這是一個經常使用的代碼模式。我們可以新建

一個控制結構來實現這個功能。

    /**
     * withPrintWriter 方法有兩個參數:
     * 第一個參數的值:file對象。
     * 第一個參數的值:function類型的對象,其中function的參數是PrintWriter,返回值是Unit。
     * 
     */
  def withPrintWriter(file: File,op: PrintWriter => Unit){
    val writer = new PrintWriter(file)
    try{
      op(writer)
    }finally{
      writer.close()
      println("closed the print writer.")
    }
  }
  //調用withPrintWriter方法
withPrintWriter(new File("D:/loader.log"), writer => {println("write a time str to file.");writer.print(new java.util.Date)})

withPrintWriter方法調用過程分析,

withPrintWriter(new File("D:/loader.log"), writer => {println("write a time str to file.");writer.print(new java.util.Date)})
第一個參數的值:file對象。
第一個參數的值:function類型的對象,該function的功能是將一個時間戳寫入到這個文件中,併在寫之前列印一條提示日誌。
使用withPrintWriter的好處是:withPrintWriter並非客戶代碼,可以確保文件在結尾被關閉;
因此客戶忘記關閉文件是不可能的。這個技巧被稱為借貸模式(loan parttern)。
拿withPrintWriter來講:withPrintWriter打開了資源並"貸出"給函數, withPrintWriter把printWriter借給
函數op;當函數op完成時,它發出信號說明它不再需要 "借"的資源PrintWriter,於是資源在finally塊中被關閉,

以確信其確實被關閉,而忽略函數是正常結束返回還是拋出了異常。

(二)使用用花括弧代替小括弧的機制實現

為了讓客戶代碼看上去更像內建控制結構的另一種方式是使用花括弧代替小括弧包圍參數列表。
scala的任何方法調用,如果你確實只傳入一個參數,就可以選擇使用花括弧代替小括弧包圍參數。

例如如下代碼:

      println("hello,world") ////如果有一個參數,可以用花括弧代替小括弧包圍參數。
      println{"hello,world"}

    val g = "Hello,world!"
    g.substring(7,9)
//    g.substring{7,9}  //如果有兩個參數,就不能用花括弧代替小括弧包圍參數,會報出編譯錯誤

 為了使用{}替換小括弧,使用柯里化重新定義前一函數withPrintWriter,源碼如下:

  /**
   * 使用柯里化重新定義函數。
   * scala在傳入一個參數時,可以用花括弧代替小括弧的機制:
   * 這個機制的目的是讓客戶端程式能寫出包圍在花括弧內的函數字面量;這可以讓方法調用感覺更像控制抽象。
   */
  def withPrintWriter2(file: File)(op: PrintWriter => Unit) = {
    val writer = new PrintWriter(file)
    try{
      op(writer)
    }finally{
      writer.close()
    }
  }
  
//調用該函數。
//調用柯里化的withPrintWriter2方法,第一函數參數以小括弧包圍參數,第二個一花括弧包圍參數(參數是函數字面量)。
  //這種方法調用看起來是不是比較賞心悅目啊!  
  withPrintWriter2(new File("D:/kafka_loader.log")){
      writer => writer.print(new java.util.Date)
  }
  //當然也可以都用小括弧,或者都用大括弧,也是沒有問題的?看個人喜好了,但是代碼就有點怪異!
  withPrintWriter2(new File("D:/kafka_loader.log"))(
      writer => writer.print(new java.util.Date)
  )
  withPrintWriter2{new File("D:/kafka_loader.log")}{
      writer => writer.print(new java.util.Date)
  }
  
  // 簡化一下調用方法
  val file = new File("D:/kafka_loader.log")
  val func =  (writer: PrintWriter) => writer.print(new java.util.Date)
  withPrintWriter2(file){func} //都是合法的哦,這種更像控制抽象。
  withPrintWriter2(file)(func) //都是合法的哦
  withPrintWriter2{file}{func} //都是合法的哦
  withPrintWriter2{file}(func) //都是合法的哦

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • //通用單選按鈕驗證 使用例子: extAttr="validateAttr=type=radio;" function f_check_radio(obj){ //獲取相同的name的Radio組 var radioNames = $names(obj.name); var len = radio
  • 原文地址:http://www.jb51.net/article/38102.htm ps:好久沒更新python代碼了,這次用到了字元串,轉來看看 Python 截取字元串使用 變數[頭下標:尾下標],就可以截取相應的字元串,其中下標是從0開始算起,可以是正數或負數,下標可以為空表示取到頭或尾。
  • 該類里包含了Java中常用的字元串處理方法,如日期處理、金額轉換... import java.math.BigDecimal;import java.sql.Timestamp;import java.text.SimpleDateFormat;import java.util.Calendar;
  • 今天遇到GD的resizeimage 函數處理jpg尾碼文件的縮略圖的時候 提示該圖片不是合法的jpg圖片並報錯 國內網上查了很多資料也沒找到有效的解決辦法,原來只要把 GD的jpeg文件支持打開即可解決 在開頭寫上上邊這行代碼 或者 在php.ini文件里把這個配置打開即可
  • 我做的是登錄界面。用了JButton(按鈕),JComboBox(組合框),JOptionPane(提示面板),JPasswordField(密碼框),JTextField(文本框),用監聽器實現了事件相應。當輸入帳號和密碼都是123時候,提示登錄成功,否則登錄失敗! 還添加了java中的顏色和字體
  • scala如果你想實現像if ,while等類似的控制結構,根本沒有值要傳入花括弧{}直接的代碼里。要怎麼實現。 比如說,我們要實現一個斷言的控制結構,myAssert(), myAssert函數參考自帶參數和一個標示變數,如果標示位為false,則什麼都不做,如果為true則進行正常判斷。 下麵是
  • 用autohotkey腳本,調整常用按鍵,另外定義常用代碼塊為巨集。來實現快速輸入powershell腳本。
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...