Это потому, что у вас заканчивается пространство на куче. По умолчанию для кучи программ Clean установлено значение 2M. Вы можете это изменить, конечно. При использовании clm
из командной строки вы можете добавить -h 4M
в свою командную строку или в командную строку самой чистой программы. Если вы используете чистую среду IDE, вы можете изменить размер кучи через «Параметры проекта», «Приложение».
Причина, по которой печатается (
(это то, что я получаю, а не [
), является следующим. Программа «Чистая» будет выводить как можно больше своего объема, а не ждать, пока не будет известна вся информация. Это означает, например, что простая строка как Start = [0..]
будет спамить ваш терминал, а не ждать, пока весь бесконечный список будет в памяти, а затем распечатайте его. В случае с squeen.icl
Clean видит, что результат Start будет кортежем и, следовательно, распечатывает открытую скобу напрямую. Однако при попытке вычислить элементы кортежа (length solutions
и hd solutions
) куча заполняется, что завершает работу программы.
Я не знаю, как он выглядит, когда вы получите полный ворох на Windows, но на Linux (/ Mac), это выглядит следующим образом:
$ clm squeen -o squeen && ./squeen -h 2M
Linking squeen
Heap full.
Execution: 0.13 Garbage collection: 0.03 Total: 0.16
($
Обратите внимание, что кортеж открывающую скобку на последняя строка. Таким образом, при использовании терминала довольно легко определить эту ошибку.
Интересно, что, поскольку length
использует хвостовую рекурсию, первый элемент кортежа можно вычислить даже с небольшой кучей (вы можете попробовать это, заменив второй элемент на []
). Также второй элемент кортежа можно вычислить на небольшой куче (замените первый элемент на 0
).
Дело в том, что длина вычисляется до голова, так как она должна быть напечатана первой. В то время как с обычными length
элементами вызова являются сбор мусора (после итерации по первым 100 элементам они могут быть отброшены, что позволяет использовать меньшую кучу), вызов hd
гарантирует, что первый элемент списка равен не отбрасываются. Если первый элемент не отбрасывается, то ни один из них не может быть третьим, третьим и т. Д. Следовательно, весь список хранится в памяти, в то время как это фактически не требуется. Подавать length
и hd
вызовы решают вопрос:
Start :: ([Int], Int)
Start = (hd solutions, length solutions)
where solutions = Queens 1 [] []
Теперь, после того, как hd
было названо, нет никаких причин, чтобы держать весь список в памяти, поэтому length
может отбросить элементы он итерированные над и кучи не заполняется.
Это ** '(' **, на самом деле. Спасибо. –
@sama Я столкнулся с неточностями в этом ответе. Не то, чтобы анализатор строгости не распознал, просто это 'length' оценивается до 'hd'. Перевертывание двух разрешает это. Я уточняю это в своем обновленном ответе. – Keelan