У меня есть функция 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 в области видимости модуля, а также переместить локальную функцию в область видимости модуля.
Мой вопрос: есть ли лучший способ определить набор функций, которые используют общий объект, например поток или StringBuilder, не передавая его каждой из функций?

2
Hanik 22 Сен 2018 в 22:25

1 ответ

Лучший ответ

В вашей ситуации я бы, вероятно, определил в модуле набор функций, которые принимают явный параметр 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 \ n" к Экземпляр StringBuilder, созданный вами в начале compile. (Конечно, каждый раз, когда вы вызываете функцию, будет другой экземпляр). Но у вас также есть общедоступные версии emitn, emitfn и т. Д., Что упрощает модульное тестирование FAR.

2
rmunn 22 Сен 2018 в 19:43