有沒有辦法從Expr
提取參數?F# - 從Expr提取選項
一個例子:
let hasStringOption (e:Expr<string option>) =
let myOption : string option = ..some code to get the string option from e
我該如何獲得Expr
內string option
並將其分配給myOption
?
有沒有辦法從Expr
提取參數?F# - 從Expr提取選項
一個例子:
let hasStringOption (e:Expr<string option>) =
let myOption : string option = ..some code to get the string option from e
我該如何獲得Expr
內string option
並將其分配給myOption
?
在你的榜樣,string option
代表表達返回類型,所以表達式本身可以是任意複雜的,需要某種像PowerPack中的評價策略作爲@wmeyer顯示。
但是,如果你確實有一個string option
表達您可以使用標準庫報價活動模式和反射來實現自己的評估策略(這裏顯示的通用選項):
module P = Microsoft.FSharp.Quotations.Patterns
let extract (expr:Expr<'a option>) =
match expr with
| P.NewUnionCase (uci, args) ->
if uci.Name = "Some" then
match args.Head with
| P.Value(value, ty) -> Some(value :?> 'a)
else
None:('a option)
let example1 = extract <@ None:int option @>
let example2 = extract <@ Some("hello world") @>
而事實上,這樣的方法可能是您自己的一種策略,用於使用反射和活動模式遞歸評估任意表達式,而不是PowerPack緩慢而有限的中間LINQ策略。
感謝您的整齊的功能:) - 但是..爲什麼你使用'None :('選項)'?什麼是:所有關於? – ebb 2011-05-18 09:05:52
嗨@ebb,不客氣。 ':('選項)'None :('選項)的一部分'只是一個類型註釋,我最初用它來幫助編譯器推斷'extract'的返回類型。但是由於Some(value:?>'a)'分支就足夠線索了(我首先寫了None分支),結果是沒有必要的。另一方面,爲了幫助編譯器推斷'example1'的最終類型,':int option' *是必需的。但它也可以通過在example1上放置類型註釋來完成:'let example1:int option = extract <@ None @>' – 2011-05-18 12:18:49
可悲(或不),你無法評估F#報價。 F#PowerPack具有編譯LINQ表達式(可以評估)的引用的有限能力。
我已經實現了一個自定義的基於反射的報價評估器,它現在是2.0.0版本以前的Unquote的一部分,http://code.google.com/p/unquote/。我認爲它比PowerPack的評估程序快50倍,並且它還支持更多的表達式。 – 2011-07-13 02:07:31
有了引用,你可以做FSharp.PowerPack.Linq.dll
:
open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Linq.QuotationEvaluation
let hasStringOption (e:Expr<string option>) =
let myOption : string option = e.Eval()
myOption.IsSome
printfn "%A" (hasStringOption <@ Some "hello" @>)
printfn "%A" (hasStringOption <@ None @>)
然而,據報道,這是相當緩慢的,並使用LINQ表達式作爲一箇中間步驟。
它取決於,如果你有<@ Some(f x)@>,你想評估函數調用嗎?如果是這樣,請使用wmeyer提及的Eval;否則,斯蒂芬的解決方案就是要走的路。 – Laurent 2011-05-17 15:05:36