如何将以下使用c#HtmlAgility库的代码转换为优雅的样式?
if node <> null then
let nodes = node.SelectNodes("//input[@name='xxx']")
if nodes <> null then
let first = nodes.[0]
if first <> null then
let value = first.Attributes.["value"]
if value <> null then
Some value.Value
else
None
else
None
else
None
else
None
以下代码可能有效吗?但是,它仍然不像C#6的?.
运算符那样简洁。
let toOpt = function null -> None | x -> Some x
node |> toOpt
|> Option.map (fun x -> x.SelectNodes("//input[@name='xxx']"))
|> Option.map (fun x -> x.[0] )
|> Option.map (fun x -> x.Attributes.["value"] )
|> Option.map (fun x -> x.Value )
C#6版本仍然更简洁:
node?.SelectNodes("//input[@name='xxx']")[0]?.Attributes["value"]?.Value
可Option.bind
有帮助吗?
答案 0 :(得分:10)
仅供参考F#4已添加Option.ofObj
在F#中void get_total(FILE*fp){
char c;
int total=0;
int number_of_conversions;
number_of_conversions = fscanf(fp, "%c", &c);
while (isdigit(c) || isspace(c) && c !='\n' && c !=NULL){
if (isspace(c)){
number_of_conversions = fscanf(fp, "%c", &c);
}
else if (isdigit(c)){
total = total + (c- '0');
number_of_conversions = fscanf(fp, "%c", &c);
}
number_of_conversions = fscanf(fp, "%c", &c);
}
printf("%d", total);
是有充分理由避免的。在处理依赖null
的C#库时,我的一般建议是提供一个F#惯用的&#34;适配器&#34;在那个图书馆。
在实践中,这可能是相当多的工作,结果可能不像C#操作符null
那样简洁(不论这个操作符是否是个好主意,除了参数)。
据我所知,F#编译器不支持这样的操作符,但是如果你对它有强烈感觉,你应该在http://fslang.uservoice.com/处提高它。 F#社区是友好的,但我怀疑你必须非常积极地争论,以使社区相信它对F#来说是一个好主意。
同时;一种使其更简洁的方法是创建一个computation expression这样的代码(?.
就是你的代码的样子):
getAttributeValue
答案 1 :(得分:4)
你可以使用Fsharpx中的monad monad
maybe {
let! node = toOpt node
let! nodes = toOpt node.SelectNodes("")
let! first = toOpt nodes.[0]
let! value = toOpt first.Attributes.["value"]
return value.Value
}
如果任何一个为空,则会生成None
,否则会生成Some value.Value
。
注意如果你在整个过程中阅读它,FuleSnabel的解决方案实际上更好,因为它可以让你摆脱toOpt
无处不在,你可以拥有它是
opt {
let! node = node
let! nodes = node.SelectNodes("")
let! first = nodes.[0]
let! value = first.Attributes.["value"]
return value.Value
}
选择这个的唯一理由是,如果你真的只想将你的项目限制在Fsharpx中定义的标准工作流构建器,而不是定义你自己的定制的(你可以从那里复制和粘贴)回答)。