Использование цитаты, вычисленной по другому слову, приводит к ошибке компиляции
Фон
Загрузка фрагмента ниже приводит к сообщению об ошибке Невозможно применить "вызов" к вычисляемому значению во время выполнения:
: subtract-sum ( seq -- quot: ( n -- n ) ) sum '[ _ - ] ;
: subtract-sum-seq ( seq -- x ) dup subtract-sum map ;
Насколько я понимаю, это ожидаемое поведение, поскольку внутренний вызов для вызова в карте требует, чтобы входные и выходные данные обработанной цитаты присутствовали во время компиляции.
проблема
Однако я проверял в слушателе, что я считаю двумя эквивалентными выражениями, и они работали просто отлично.
Пример 1:
# : subtract-sum ( seq -- quot: ( n -- n ) ) sum '[ _ - ] ;
# : subtract-sum-seq ( seq -- seq call ) dup subtract-sum ;
# { 1 2 3 4 } subtract-sum-seq
{ 1 2 3 4 }
[ 10 - ]
# map
{ -9 -8 -7 -6 }
Пример 2:
# : subtract-sum-seq ( seq -- x ) dup '[ _ - ] map ;
# { 1 2 3 4 } subtract-sum-seq
{ -9 -8 -7 -6 }
Вопрос
В чем разница между исходным кодом и рабочими примерами, который вызывает ошибку в первом, а не в двух других? Ясно, что в цитатах что-то не так.
Дополнительная информация
Интересно, что я попытался обернуть свой вызов map внутри слушателя из первого примера в слово, и это привело к той же ошибке, что и исходный код:
# { 1 2 3 4 } subtract-avg-seq map
{ -9 -8 -7 -6 }
# : apply ( -- seq ) { 1 2 3 4 } subtract-avg-seq map ; ! error: Cannot apply "call" to a run-time computed value
0 ответов
В этом примере есть две разные проблемы.
Во-первых, в интерактивном коде слушатель не будет проверять влияние цитат на стек, но он проверяется, когда код компилируется в определении. Это причина того, что ручное расширение слов в Слушателе сработало.
Вторая проблема заключается в том, что вложенные эффекты, объявленные для цитат, игнорируются в большинстве слов. Вы могли бы заменить ( n -- quot: ( n -- n ) )
с ( n -- q )
и это будет работать так же.
В этом случае объявление кавычки в первом слове не относится ко второму слову. Это причина того, что даже если это все теоретически правильно, компилятор не может доказать это; он просто не знает эффектов цитаты.
Решение состоит в том, чтобы объявить эффект цитаты на сайте вызова:
: subtract-sum ( seq -- quot: ( n -- n ) ) sum '[ _ - ] ;
: subtract-sum-seq ( seq -- x ) dup subtract-sum [ call( n -- n ) ] curry map ;
{ 1 2 3 4 } subtract-sum-seq .
! -> { -9 -8 -7 -6 }
https://docs.factorcode.org/content/article-effects.html
https://docs.factorcode.org/content/article-inference-escape.html