Действительно ли это - ошибка цитат F#?

[<ReflectedDefinition>]
let rec x = (fun() -> x + "abc") ()

Пример кода с рекурсивным значением выше продуктов следующая ошибка компилятора F#:

ошибка FS0432: [<ReflectedDefinition>] условия не может содержать использование оператора соединения встык префикса '%'

Я не вижу использования оператора разрезания в коде выше, похож на ошибку... :)

Похож это - проблема с цитатой через ReflectedDefinitionAttribute только, нормальная цитата работает хорошо:

let quotation =
    <@ let rec x = (fun() -> x + "abc") () in x @>

приводит к ожидаемому результату со скрытым Lazy.create и Lazy.force использования:

val quotation : Quotations.Expr<string> =
   LetRecursive
   ([(x, Lambda (unitVar,
        Application
        (Lambda (unitVar0,
            Call (None,
            String op_Addition[String,String,String](String, String),
            [Call (None,
                String Force[String](Lazy`1[System.String]), // `
                [x]), Value ("abc")])),
        Value (<null>)))),
   (x, Call (None, Lazy`1[String] Create[String](FSharpFunc`2[Unit,String]), [x])),
   (x, Call (None, String Force[String](Lazy`1[String]), [x]))], x) // `

Таким образом, вопрос: действительно ли это - ошибка компилятора F# или нет?

5
задан Tomas Petricek 30 May 2010 в 15:40
поделиться

1 ответ

Я бы подумал, что это может быть вызвано обработкой рекурсивных значений в F #. В качестве обходного пути вы можете превратить рекурсивную ссылку в параметр:

[<ReflectedDefinition>] 
let foo x = (fun() -> x + "abc") ()

// To construct the recursive value, you'd write:
let rec x = foo x

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


РЕДАКТИРОВАТЬ Первоначально я думал, что проблема может заключаться в следующем, но сейчас я не уверен (см. Комментарии).

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

Цитата, которая должна быть сохранена в метаданных сборки, будет выглядеть так:

let rec x = <@ (fun() -> %x + "abc") () @>

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

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

5
ответ дан 14 December 2019 в 19:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: