Когда отдавать предпочтение нетипизированным над напечатанными цитатами в F#?

F# имеет как типизированные, так и нетипизированные цитаты кода, и мне интересно, каковы случаи использования, когда один выбирает один над другим?

Является ли различие только удобством, а нетипизированные и типизированные цитаты могут быть преобразованы в каждое во всех случаях или являются типизированными цитатами, например, подмножеством возможных с нетипизированными цитатами?

Есть ли примеры, которые работают только с типизированными, но не с нетипизированными цитатами - или наоборот?

2 ответа

Решение

В общем, я бы рекомендовал использовать печатные цитаты, когда вы можете. Как обычно, типы позволят вам статически применять некоторые условия корректности, которые в противном случае могли бы вызвать сбои во время выполнения. Рассматривать:

let one = <@@ "one" @@>
// exception at runtime
let two = <@@ 1 + %%one @@>

в отличие от

let one = <@ "one" @>
// compile time error: the type 'string' does not match the type 'int'
let two = <@ 1 + %one @>

Кроме того, иногда нетипизированные цитаты требуют дополнительных аннотаций типов в тех случаях, когда типизированные цитаты этого не делают:

// ok
let l = <@ [1] @>
let l2 = <@ List.map id %l @>

// fails at runtime (obj list assumed instead of int list)
let l = <@@ [1] @@>
let l2 = <@@ List.map id %%l @@>

// ok
let l = <@@ [1] @@>
let l2 = <@@ List.map (id:int->int) %%l @@>

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

Также обратите внимание, что при необходимости чрезвычайно легко конвертировать между типизированными и нетипизированными цитатами (Expr<_> в Expr перейти от типизированного к нетипизированному; использование Expr.Cast пойти другим путем).

Обычно потребители библиотек обработки цитат будут использовать типизированные цитаты. Принимая во внимание, что авторам обработки цитат необходимо работать с нетипизированными цитатами.

То есть вы не будете часто напрямую создавать нетипизированные цитаты, используя (<@@ @@>) оператор. Но для рекурсивной обработки цитаты с использованием различных активных шаблонов базовой библиотеки F#, таких как модуль Quotations.Patterns, вы работаете с цитатами в их нетипизированной форме.

Обратите внимание, что Expr<'T> продолжается Expr и на самом деле не добавляет много информации к нему. То есть типизированные цитаты на самом деле просто иллюзия, все захваченные метаданные находятся в Expr объект и доступен только во время выполнения.

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