f # - использовать общий объект, не передавая его везде - PullRequest
0 голосов
/ 22 сентября 2018

У меня есть функция compile, которая принимает AST и создает строку с инструкциями по сборке.Внутри я создаю объект StringBuilder.Также внутри compile есть много локальных функций, таких как emitIf, emitLet и т. Д. Причина определения локальных функций заключается в том, что объект StringBuilder не нужно передавать в функции emit в качестве дополнительного параметра.,Но я чувствую, что это решение несколько неловко.

module Compile
let compile ast =
    let sb = new StringBuilder()
    let emitn s = sb.AppendLine s |> ignore
    let emitfn f = Printf.kprintf emitn f
    let emitLoadNumber (n:int) = 
        emitfn "  mov $%d, %%rax" n

    let rec emitExpr env si =
    //...
    and emitIf isTail env si cond th el =
    //...

В качестве другого решения я мог бы создать StringBuilder в области видимости модуля, а также переместить локальную функцию в область видимости модуля.
У меня вопрос: есть ли лучший способ определить набор функций, которые используют общий объект, такой как stream или StringBuilder, без передачи его каждой из функций?

1 Ответ

0 голосов
/ 22 сентября 2018

В вашей ситуации я бы, вероятно, определил группу функций в модуле, которые принимают явный параметр StringBuilder, а затем использовал бы частичное приложение, чтобы определить группу локальных функций, которые закрываются над одним конкретным экземпляром StringBuilder.Например,

module Compile

let emitn sb s = sb.AppendLine s |> ignore
let emitfn sb f = Printf.kprintf (emitn sb) f
let emitLoadNumber sb (n:int) =
    emitfn sb "  mov $%d, %%rax" n

let compile ast =
    let sb = new StringBuilder()
    let emitn = emitn sb
    let emitfn = emitfn sb
    let emitLoadNumber = emitLoadNumber sb

    let rec emitExpr env si =
    //...
    and emitIf isTail env si cond th el =
    //...

Теперь внутри функции compile и ее подфункций (emitExpr, emitIf и т. Д.) Вы можете использовать emitn "foo", и она добавит строку "foo \ nmsgstr "экземпляру StringBuilder, который вы создали в начале compile.(Конечно, каждый раз, когда вы вызываете функцию, это будет другой экземпляр).Но у вас также есть общедоступные версии emitn, emitfn и т. Д., Что облегчает модульное тестирование FAR.

...