2017-05-24 41 views
2

鑑於這種F#庫代碼在F#中是否有空括號用於表示沒有參數?

從主

open FileMaint 
let log_file = FileMaint.fm.generate_log_file 

從庫

module FileMaint 
. 
. 
. 
[<AutoOpen>] 
(* return_unique_file_name just returns as close to a unique file name piece based on clock time. *) 
module fm = 


(* Checks for presense of a file name. *) 
    let is_file_present file_name = 
     let rc = 
      if File.Exists file_name then 
       true 
      else 
       false 
     rc 

    (* Initialize a log file. *) 
    let generate_log_file = 
     let log_file_name = 
      if File.Exists(base_log_file) then 
       test_and_reset_unique_file_name local_dir base_log_file 
      else 
       base_log_file 

     use fH = new StreamWriter(log_file_name, true) 
     fH.WriteLine(generate_time_stamp + ": " + log_file_name + " initialized.") 

從我的 「主」,我可以進入通話is_file_present,但我不能踏入,也不會generate_log_file執行。

但是,在generate_log_file庫函數(如generate_log_file())上定義括號之後,然後調用它,函數就會執行(並且我可以進入該函數)。

因此,看起來空括號表示函數沒有參數時的佔位符。那是對的嗎?

+0

可能還想包括您的主代碼(或至少相關位) – Will

+0

@我會添加一些額外的上下文。 – octopusgrabbus

+0

'()'只是單位。在F#中,每個函數都必須有一個參數,並且每個函數都必須返回一些內容。如果你沒有將任何變量傳遞給函數,用()表示。如果返回值有副作用(例如打印到屏幕或寫入文件),它也會返回()。 – s952163

回答

6

空的括號是類型unit。此值與任何其他值一樣,與數字或字符串主要不同。

let a = 5 
let b = "abc" 
let c =() 

> val a: int = 5 
> val b: string = "abc" 
> val c: unit =() 

這種類型unit是特殊的,它只有一個值,沒有別人。但在其他方面,它就像任何其他類型一樣。你可以使用它的功能參數,例如:

let f (u: unit) = ... 

但由於它永遠只能有一個值,可以使用值本身作爲參數的模式:

let f() = ... 

你可以做到這一點其他類型還有:

let g 42 = ... 
let h "abc" = ... 

,這將編譯,但它會給你一個警告,也有int其他值除42,你還沒有定義什麼日電子功能應該爲他們做。但是unit除了()之外沒有其他值,所以沒有警告。你甚至可以使一個同等類型的自己:

type T = A 
let f A = 42 // no warning here, because A is the only possible value of type T 

現在,又回到了你的例子:在你的原代碼,generate_log_file不是一個函數,而是一個值。它是在初始化期間計算的,當你認爲你正在「調用」它時,你只是參考了這個預先計算的值。沒有呼叫正在進行,因爲沒有任何呼叫。

而它是一個值而不是一個函數的原因是它沒有任何參數。是的,這是一個簡單的規則:如果你有參數,你是一個功能;如果沒有,你是一個價值。所以一旦你給它一個參數,它成爲一個功能,那就是爲什麼你可以在步驟。

2

由於它代表的generate_log_file值時模塊fm被初始化,裝配在啓動過程中最有可能被初始化的值。如果您在戰略上插入Debugger.Break,這是可調試的。

通過將代碼更改爲let generate_log_file() ...generate_log_file現在是一個函數,您可以使用單位值()調用它,使其更易於調試。

在F#中,您始終使用單個值調用函數,()是類型unit的唯一值。

PS。

let generate_log_file() ...使用參數的模式匹配來避免需要鍵入let generate_log_file (_ : unit) ...。以下是合法的,儘管有些無用let generate_log_file 0 ...