Можно ли использовать оператор конвейера для вызова метода возвращаемого объекта? - PullRequest
1 голос
/ 17 сентября 2009

Можно ли вызвать метод для возвращенного объекта с помощью инфиксного оператора конвейера?

Например, у меня есть класс .Net (Class1) с методом (Method1). В настоящее время я могу кодировать это так:

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

Я знаю, что я мог бы также закодировать это как таковое

let val = new Class1().Method1()

Однако я бы хотел иметь возможность транслировать его (я использую? Ниже, где я не знаю, что делать):

new Class1()
|> ?.Method1()

Кроме того, скажем, у меня был метод, который возвращает объект, и я хочу ссылаться на него только в том случае, если этот метод не возвратил ноль (в противном случае залог?)

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

Или, чтобы было понятнее, вот код C #:

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

Ответы [ 2 ]

2 голосов
/ 17 сентября 2009

Вы можете довольно просто определить что-то похожее на ваш оператор (??) (но операторы не могут начинаться со знака вопроса):

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

К сожалению, ваш конвейерный код должен быть немного более подробным (также обратите внимание, что вы можете удалить ключевое слово new для вызова конструкторов):

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

Собираем все вместе:

Class1()
|> fun x -> x.Method1()
|> ~?? (fun x -> x.Method2())
1 голос
/ 20 сентября 2009

Использование пользовательского оператора, как предполагает '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 }

Как вы можете видеть, когда вы хотите использовать значение, которое потенциально может быть 'нулевым', вы используете 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()    

Кстати: если вы хотите узнать больше об этом, это очень похоже на монаду «Maybe» в Haskell (или вычисления, работающие с опцией типа F #).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...