2016-04-30 3 views
5

Мне нужна реализация функции defaultArg с Lazy в качестве второго параметра. Вот пример использования:Есть ли стандартная реализация F # defaultArg, принимающая ленивый?

defaultArgLazy option (lazy doSomeHeavyWorkThatShouldBeAvoided()) 

Это довольно легко реализовать

let defaultArgLazy o (p:'a Lazy) = 
    match o with 
    | Some v -> v 
    | None -> p.Force() 

Но мне интересно, если есть стандартная реализация, что я пропускаю.

+0

Нет, для этого нет ничего стандартного. – scrwtp

ответ

1

Я не знаю, о чем встроенный, но вот более общий вариант вашей функции:

module Option = 
    let lazyDefault f opt = 
     match opt with 
     | Some x -> x 
     | None -> f() 

let lazyVal = lazy 1 
let opt = None 

opt |> Option.lazyDefault lazyVal.Force // returns 1 

Он принимает любую функцию (unit -> 'a) вместо конкретно Lazy<'a>', так что вы просто пройти через Ленивый-х Force вместо этого, и сохраняйте гарантию того, что оценка выполняется только один раз.

Возможно, Lazy.Force() был добавлен в F # поверх существующего существующего Lazy.Value .NET, чтобы вы могли использовать его более идиоматически с более высокими функциями порядка.

Обратите внимание, что я поменял порядок параметров по сравнению со встроенным defaultArg, чтобы быть более совместимым с функциями в других модулях и более удобным для трубопровода/каррирования.

1

Если ленивое значение используется только в более поздней точке кода, может также возникнуть идея использовать defaultArg и передать ему Lazy<'a> option в качестве первого аргумента. Таким образом, выбор опции или аргумента по умолчанию отделяется от того, когда результат оценивается.

Принимая эту идею, функция

let defaultArgLazy opt lazyDef = 
    (defaultArg (Option.map Lazy.CreateFromValue opt) lazyDef).Value 

будет делать то, что вы хотите - как это делает один за TheQuickBrownFox.

Смежные вопросы