2017-07-06 30 views
4

考慮以下幾點:爲什麼一些FAKE方法不能在目標函數中工作?

#r @"FakeLib.dll" 

open Fake 
open Fake.StringHelper 
open Fake.ProcessHelper 

Shell.Exec("mkdir","exampleDirectory") 

Target "DoStuff" (fun() -> 
    trace "Doing Stuff..." 
) 

Target "Clean" (fun() -> 
    trace "Cleaning..." 
) 

Target "Deploy" (fun() -> 
    trace "Deploying..." 
) 

"DoStuff" 
    ==>"Clean" 
    ==>"Deploy" 

RunTargetOrDefault "Deploy" 

上述腳本工作正常,但是當我移動Shell.Exec一個目標內是這樣的:

#r @"FakeLib.dll" 

open Fake 
open Fake.StringHelper 
open Fake.ProcessHelper 

Target "DoStuff" (fun() -> 
    trace "Doing Stuff..." 
    Shell.Exec("mkdir","exampleDirectory") 
) 

Target "Clean" (fun() -> 
    trace "Cleaning..." 
) 

Target "Deploy" (fun() -> 
    trace "Deploying..." 
) 

"DoStuff" 
    ==>"Clean" 
    ==>"Deploy" 

RunTargetOrDefault "Deploy" 

我結束了一個錯誤:

FsiEvaluationException: 

Error: 

     DeployScript.fsx(10,5): error FS0001: This expression was expected to have type 
      unit 
     but here has type 
      int 


Output: [Loading C:\Users\myusername\Desktop\SomeFolder\DeployScript.fsx] 


Input: C:\Users\myusername\Desktop\SomeFolder\DeployScript.fsx 
\Arguments: 
    C:\fsi.exe 

Exception: Yaaf.FSharp.Scripting.FsiEvaluationException: Error while compiling or executing fsharp snippet. ---> System.Exception: Operation failed. The error text has been print the error stream. To return the corresponding FSharpErrorInfo use the EvalInteractionNonThrowing, EvalScriptNonThrowing or EvalExpressionNonThrowing 
    at Microsoft.FSharp.Compiler.Interactive.Shell.FsiEvaluationSession.commitResult[a,b](FSharpChoice`2 res) 
    at Microsoft.FSharp.Compiler.Interactive.Shell.FsiEvaluationSession.EvalScript(String filePath) 
    at [email protected](String arg00) in C:\code\fake\paket-files\matthid\Yaaf.FSharp.Scripting\src\source\Yaaf.FSharp.Scripting\YaafFSharpScripting.fs:line 1303 
    at [email protected](Unit unitVar0) in C:\code\fake\paket-files\matthid\Yaaf.FSharp.Scripting\src\source\Yaaf.FSharp.Scripting\YaafFSharpScripting.fs:line 1277 
    at Yaaf.FSharp.Scripting.Helper.consoleCapture[a](TextWriter out, TextWriter err, FSharpFunc`2 f) in C:\code\fake\paket-files\matthid\Yaaf.FSharp.Scripting\src\source\Yaaf.FSharp.Scripting\YaafFSharpScripting.fs:line 1221 
    at [email protected][a](Boolean preventStdOut, OutStreamHelper out, OutStreamHelper err, FSharpFunc`2 f) in C:\code\fake\paket-files\matthid\Yaaf.FSharp.Scripting\src\source\Yaaf.FSharp.Scripting\YaafFSharpScripting.fs:line 1254 
    at [email protected](String text) in C:\code\fake\paket-files\matthid\Yaaf.FSharp.Scripting\src\source\Yaaf.FSharp.Scripting\YaafFSharpScripting.fs:line 1276 
    --- End of inner exception stack trace --- 
    at [email protected](String text) in C:\code\fake\paket-files\matthid\Yaaf.FSharp.Scripting\src\source\Yaaf.FSharp.Scripting\YaafFSharpScripting.fs:line 1284 
    at [email protected]IFsiSession-EvalScriptWithOutput(String) in C:\code\fake\paket-files\matthid\Yaaf.FSharp.Scripting\src\source\Yaaf.FSharp.Scripting\YaafFSharpScripting.fs:line 1308 
    at Fake.FSIHelper.runScriptUncached(Boolean useCache, String scriptPath, IEnumerable`1 fsiOptions, Boolean printDetails, CacheInfo cacheInfo, TextWriter out, TextWriter err) in C:\code\fake\src\app\FakeLib\FSIHelper.fs:line 471 
DeployScript.fsx(10,5): error FS0001: This expression was expected to have type 

這裏的一點是我試圖只在某個目標下執行shell命令。不要關注mkdir命令,因爲我實際上想要使用schtasks命令。我只是爲了簡單起見而使用了mkdir。也許我在這裏錯過了一個細微差別。我也注意到使用environVarOrFail時的相同行爲。預先感謝所有回覆的人。

回答

7

Shell.Exec返回int,但Target需要返回unit的函數。

試試這個:

let returnUnit() =() 
let return42() = 42 

Target "One" returnUnit // works 
Target "Two" return42 // fails: expected to have type unit, but here has type int 

目標「兩個」編譯失敗,因爲它的第二個參數是返回int的函數,而返回unit預期的功能。

這個錯誤是爲了防止你忘記函數返回值:編譯器有用地告訴你「嘿,你確定你不想用這個int做什麼嗎?那麼爲什麼你在第一個函數中調用函數地點?」

但是,有時候,丟棄返回值是有意義的。例如,在這種特殊情況下,您稱Shell.Exec爲副作用,其返回值並不令您感興趣。這種情況經常出乎意料地發生,所以經常有這樣的特殊功能 - ignore

Target "DoStuff" (fun() -> 
    trace "Doing Stuff..." 
    Shell.Exec("mkdir","exampleDirectory") |> ignore // compiles fine 
) 

該函數獲取任何值,將其拋出並返回一個單位。通過將其應用於Shell.Exec的結果,您告訴編譯器:「是的,我確定我不需要這個值,請ignore它。」


這就是說,我強烈建議使用專門的功能,而不是通用的系統調用。這將使您的腳本更具可讀性,甚至可以幫助您儘早發現偶然的錯誤。例如,要創建目錄,請使用FileUtils.mkdir

Target "DoStuff" (fun() -> 
    trace "Doing Stuff..." 
    FileUtils.mkdir "exampleDirectory" // no need for `ignore`, mkdir already returns `unit` 
) 
+1

非常感謝。我不打算使用mkdir系統調用。我需要它用於schtasks命令。我找不到FAKE中的任何內容來創建,結束和刪除計劃任務。所以,我將使用Shell.Exec來完成這個任務。 –

相關問題