Время компиляции и время выполнения шаблонов Hamlet

Для механизма шаблонов Гамлета я понимаю, что шаблон анализируется во время компиляции, в результате чего получается исходный код, содержащий вызовы комбинаторов blaze-html (и, возможно, других выражений из-за интерполяции). Таким образом, точки (поддеревья), где происходит интерполяция, известны во время компиляции.

Во время выполнения нам нужно вычислить интерполированное значение (конечно) и "вставить его" в дерево, то есть применить комбинаторы html. Все они? На самом деле некоторые из этих приложений могут быть оценены во время компиляции (те, у которых нет интерполяции под ними). Это происходит?

3 ответа

Решение

Прошло много времени с тех пор, как я работал над кодом, так что не воспринимайте это как авторский (как упоминал Даниэль, -ddump-simpl хороший звонок здесь). Но я не верю, что мы используем комбинаторы blaze-html, просто тип данных. Сам Гамлет объединяет строки в максимально возможной степени во время компиляции, чтобы избежать этих затрат во время выполнения. Я знаю, что когда я последний раз тестировал (что было сделано много лет назад), оптимизация окупилась довольно хорошо.

Вероятно, нет: то, что вы просите, звучит очень похоже на частичную оценку (не путать с частичным применением), которая является чем-то вроде минного поля производительности компилятора, поэтому ее часто избегают. Но вы можете проверить сами; использование -ddump-simpl с вашим предпочтительным уровнем оптимизации, чтобы увидеть ядро, которое генерирует GHC.

Как говорит Майкл: "Гамлет сам объединяет строки в максимально возможной степени во время компиляции, чтобы избежать таких затрат во время выполнения".

Для примера из книги,

main = putStrLn $ renderHtml [shamlet|
<p>Hello, my name is #{name person} and I am #{show $ age person}.
<p>
    Let's do some funny stuff with my name: #
    <b>#{sort $ map toLower (name person)}
<p>Oh, and in 5 years I'll be #{show ((+) 5 (age person))} years old.
|]
  where
    person = Person "Michael" 26

-ddump-simpl содержит это:

               (>>
                  @ Text.Blaze.Internal.MarkupM
                  Text.Blaze.Internal.$fMonadMarkupM
                  @ ()
                  @ ()
                  (id
                     @ (Text.Blaze.Internal.MarkupM ())
                     (. @ Data.Text.Internal.Text
                        @ Text.Blaze.Internal.Markup
                        @ String
                        Text.Blaze.Internal.preEscapedText
                        Data.Text.pack
                        (GHC.CString.unpackCString#
                           ".</p>\n\
                           \<p>Let's do some funny stuff with my name: <b>"#)))

Действительно, это не синтаксическое дерево HTML (последняя строка - строка содержит закрывающий тег и следующий открывающий тег).

Эта функция Гамлета должна рекламироваться больше!

Другие вопросы по тегам