2

是否可以使用管道中缀运算符在返回的对象上调用方法?

例如,我有一个带有方法 (Method1) 的 .Net 类 (Class1)。我目前可以这样编码:

let myclass = new Class1()
let val = myclass.Method1()

我知道我也可以这样编码

let val = new Class1().Method1()

但是我希望能够将它流水线化(我正在使用 ? 下面我不知道该怎么做):

new Class1()
|> ?.Method1()

此外,假设我有一个返回对象的方法,并且我只想在该方法没有返回 null 时引用它(否则保释?)

new Class1()
|> ?.Method1()
|> ?? ?.Method2()

或者为了更清楚,这里有一些 C# 代码:

    public void foo()
    {
        var myclass = new Class1();
        Class2 class2 = myclass.Method1();
        if (class2 == null)
        {
            return;
        }
        class2.Method2();
    }
4

2 回答 2

3

您可以相当容易地定义类似于您的(??)运算符的内容(但运算符不能以问号开头):

let (~??) f x =
  if (x <> null) then
    f x

不幸的是,您的流水线代码需要更加冗长(另外请注意,您可以删除new调用构造函数的关键字):

Class1()
|> fun x -> x.Method1()

把它们放在一起:

Class1()
|> fun x -> x.Method1()
|> ~?? (fun x -> x.Method2())
于 2009-09-17T19:09:24.900 回答
2

使用自定义运算符作为“kvb”建议绝对是一种选择。null在这种情况下,您可能会发现另一种有趣的方法是定义您自己的“计算表达式”,它会在您指定的每个点自动执行值检查。使用它的代码如下所示:

open System.Windows.Forms

// this function returns (0) null, or (1) btn whose parent is 
// null or (2) button whose parent is not null
let test = function
  | 1 -> new Button(Text = "Button")
  | 2 -> new Button(Text = "Button", Parent = new Button(Text = "Parent"))
  | _ -> null

let res =  
  safe { let! btn = test(2) // specify number here for testing
         // if btn = null, this part of the computation will not execute
         // and the computation expression immediately returns null
         printfn "Text = %s" btn.Text
         let! parent = btn.Parent // safe access to parent
         printfn "Parent = %s" parent.Text // will never be null!
         return parent }

如您所见,当您想使用可能为“null”的值时,您可以let!在计算表达式中使用。计算表达式可以定义为null如果值是则立即返回null,否则运行其余的计算。这是代码:

type SafeNullBuilder() =
  member x.Return(v) = v
  member x.Bind(v, f) = 
    if v = null then null else f(v)

let safe = new SafeNullBuilder()    

顺便说一句:如果您想了解更多信息,它与 Haskell 中的 'Maybe' monad 非常相似(或使用 F# 选项类型进行计算)。

于 2009-09-20T00:24:06.110 回答