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
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...