2017-08-14 70 views
4

我在OCaml的版本4.04 UTOP定義一個函數f。忽略OCaml中的函數優雅

utop # let f = function x -> x + 1;; 

val f : int -> int = <fun> 

當我試圖忽略f,我遇到了一個警告。

utop # let a = ignore (f : int -> int); f 2;; 

Characters 15-19:            
Warning 5: this function application is partial, 
maybe some arguments are missing 
val a : int = 3 

警告5被觸發,因爲以下ignore表達具有如下功能接口int -> int

ignore (f 0)if false then (ignore f 0)工作,但他們不是優雅。我不想提供缺少的參數給f。有沒有替代ignore

ignore的動機是不是在這個虛擬例子很清楚,但我確實需要使用它,以避免在我真正的項目的其他警告。

謝謝你的時間。

+1

我聞到一個XY問題(http://xyproblem.info/)。你能解釋一下真實的用例嗎? – Drup

+1

如果你沒有調用這個函數,你爲什麼還要把它放在第一位呢? – Bergi

+0

真正的用例是通過使用ocaml_plugin在運行時編譯一些OCaml代碼。這段代碼可能會或可能不會調用'f'。鑑於我不想將'f'作爲我的插件的庫,最好的方法是將代碼附加到'f'的定義。如果它不調用'f',編譯器會報錯。 –

回答

4

非常粗略地講爲形式e1; e2的表達是通過OCaml的typechecker如下處理:

  • 如果e1具有這樣的功能類型t -> t',警告5被射出。
  • 否則,如果e1沒有一個類型unit,警告10被髮射。

例如,

let f x = 
    prerr_endline "some side effect you may want"; 
    (* but you may not want the returned function sometimes *) 
    fun y -> x + y 

let a = f 1 2; f 1 2;;  (* Warning 10 *) 
let a = f 1; f 1 2;;   (* Warning 5 *) 

ignore e1; e2的類型檢查是作爲e1; e2除了一個點一個爲相同的:它跳過第二檢查:一個警告10不發射即使e1的類型不是unit。爲警告5的第一次檢查仍在進行:

let a = ignore (f 1 2); f 1 2;; (* No warning *) 
let a = ignore (f 1); f 1 2;; (* Warning 5 *) 

所以ignore的目的是清除警告10而不是5的ignore這種特殊的處理是圍繞在OCaml的源代碼typing/typecore.mlis_ignore功能可按定義編碼。

如果你想真正忽略警告5,我認爲2種方法:

let a = let _ = f 1 in f 1 2;; (* No warning *) 

let ignore' _ =() 
let a = ignore' (f 1); f 1 2;; (* No warning *) 

第一種是使用一個通配符匹配的模式。另一種是定義你自己的忽略功能ignore'。因此,這是一個通常的OCaml功能的ignore發出以上不進行警告5參數的特殊類型檢查。

+0

如果我不想提供缺少的參數給f?它在這個虛擬的例子中工作正常,但有時缺少的參數可能難以構建,而'f'可能會引發一些不適當的參數的例外。 –

+0

我明白你的觀點,即如果'ignore'後面跟着一個變量的函數接口,編譯器總是會抱怨。我想知道是否有其他選擇可以忽略。謝謝! –

0

您可以定義工作在箭頭類型自己忽略的功能如下所示:

let ignore_fun (f:'a -> 'b) =() 

這樣,您不再需要一個參數傳遞給˚F並不會下產生警告。

let a = ignore_fun (f : int -> int); f 2;; 
+0

警告27:未使用的變量f。變量f不在ignore_fun中使用,因此會觸發警告27。 –

+0

我可以寫'''let ignore_fun(_:'a - >'b)=()''''代替,但我沒有發現它更清晰 – ghilesZ

1

您可以通過一個let _結構取代ignore呼叫避免警告:

let a = let _ = (f : int -> int) in f 2;; 
0

答案由camlspotter是很好,你應該接受它。 我只是想添加第三個解決方案:總結違規的功能分爲一個元組

let a = ignore (f,()); f 2;; 

或列表

let a = ignore [f]; f 2;; 

或任何需要你的想象。