От новичка до гуру: Курсы программирования на CyberDuff

Является ли это ошибкой цитирования 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 # или нет?


Ответы:


1

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

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

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

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


EDIT Изначально я думал, что проблема может быть такой, как показано ниже, но теперь я не уверен (см. комментарии).

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

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

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

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

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

30.05.2010
  • Спасибо за ответ, Томаш! Я не согласен с вами, что когда я пишу версию [<ReflectedDefinition>], метаданные должны выглядеть как <@ (fun() -> %x + "abc") () @>. Внутри цитаты имя x должно быть привязано к общедоступному значению .NET, а не к фрагменту цитаты! Если бы это вело себя так, как вы говорите, код вроде этого: [<ReflectedDefinition>] let rec f () = (fun() -> f () + "abc") () тоже должен давать такое же ожидание, но это не так. 30.05.2010
  • @ControlFlow: я думаю, что ваша точка зрения имеет смысл. Возможно, это связано с рекурсивными значениями, которые в F# обычно довольно сложны. 30.05.2010
  • Я тоже так думаю, обработка рекурсивных значений - нетривиальная задача для энергичных языков, таких как F # ... Возможно, компилятору следует просто ограничить использование [‹ReflectedDefinition›] подобным образом. 30.05.2010
  • Новые материалы

    Представляем Narwhal Technologies (Nrwl)
    6 декабря 2016 г. Маунтин-Вью, Калифорния С тех пор, как Виктор Савкин и я (Джефф Кросс) присоединились к команде Angular в Google на заре Angular 1, Angular продемонстрировал феноменальный..

    Путь AWS  — «Изучение машинного обучения — 10 начинающих ИИ и машинного обучения на AWS».
    Универсальный ресурсный центр для изучения искусственного интеллекта и машинного обучения. НОЛЬ или ГЕРОЙ, начните свое путешествие здесь. Получите решения и пройдите обучение у экспертов AWS...

    5 простых концепций Python, ставших сложными
    #заранее извините 1) Переменные x = 4 y = 5 Переменная в Python — это символическое представление объекта. После присвоения некоторого объекта переменной Python мы приобретаем..

    «Освоение вероятности: изучение совместной, предельной, условной вероятности и теоремы Байеса —…
    Виды вероятности: Совместная вероятность Предельная вероятность Условная вероятность Диаграмма Венна в вероятностях: В “Set Theory” мы создаем диаграмму Венна...

    Основы Spring: Bean-компоненты, контейнер и внедрение зависимостей
    Как лего может помочь нашему пониманию Когда мы начинаем использовать Spring, нам бросают много терминов, и может быть трудно понять, что они все означают. Итак, мы разберем основы и будем..

    Отслеживание состояния с течением времени с дифференцированием снимков
    Время от времени что-то происходит и революционизирует часть моего рабочего процесса разработки. Что-то более забавное вместо типичного утомительного и утомительного процесса разработки. В..

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