Примеры, приведенные ниже, дают типичные результаты.
Один медленный пример в прогоне длиной 20.
In[18]:= getTimes[whileLength, 20]
Out[18]= {0.031, 0.032, 0.031, 0.031, 0.031, 0.032, 0.031, 0.031, \
0.031, 0.047, 0.032, 0.031, 0.031, 3.547, 0.047, 0.031, 0.031, 0.032, \
0.031, 0.031}
Попутно отмечу, что время примерно в 10 раз быстрее, чем в исходном посте.За исключением медленных случаев, которые сопоставимы.Не уверен, что объясняет эту разницу в соотношениях.
Нет медленных примеров.
In[17]:= getTimes[nestLength, 20]
Out[17]= {0.047, 0.047, 0.062, 0.047, 0.047, 0.062, 0.047, 0.047, \
0.047, 0.063, 0.046, 0.047, 0.047, 0.063, 0.047, 0.046, 0.047, 0.063, \
0.047, 0.047}
Один медленный пример в пробеге длиной 100.
In[19]:= getTimes[whileLength, 100]
Out[19]= {0.031, 0.031, 0.031, 0.032, 0.031, 3.594, 0.047, 0.031, \
0.031, 0.031, 0.032, 0.031, 0.031, 0.031, 0.032, 0.031, 0.047, 0.031, \
0.031, 0.031, 0.032, 0.031, 0.031, 0.031, 0.032, 0.047, 0.031, 0.031, \
0.031, 0.032, 0.031, 0.031, 0.031, 0.032, 0.031, 0.031, 0.047, 0.031, \
0.031, 0.032, 0.031, 0.031, 0.031, 0.032, 0.031, 0.031, 0.047, 0.031, \
0.032, 0.031, 0.031, 0.031, 0.032, 0.031, 0.031, 0.047, 0.031, 0.031, \
0.032, 0.031, 0.031, 0.031, 0.032, 0.031, 0.047, 0.031, 0.031, 0.032, \
0.031, 0.031, 0.031, 0.032, 0.031, 0.031, 0.031, 0.032, 0.046, 0.032, \
0.031, 0.031, 0.031, 0.032, 0.031, 0.031, 0.047, 0.031, 0.032, 0.031, \
0.031, 0.031, 0.032, 0.031, 0.047, 0.031, 0.031, 0.031, 0.032, 0.031, \
0.031, 0.031}
Mathematica реализует,несовершенно то, что называется «бесконечной оценкой».То есть выражение переоценивается до тех пор, пока оно не перестанет меняться.Чтобы сделать это достаточно быстро, существуют различные оптимизации, которые пытаются замкнуть процесс, когда это возможно.
В некоторых случаях это может быть сложно различить (из-за эффекта, похожего на хеш-коллизии), а выражения могут быть излишнеперепроверены.Глубоко вложенные выражения имеют тенденцию быть худшим случаем для этого.У нас есть дополнительный код, который часто решает эти проблемы даже в случаях коллизий.
В этом случае виновником является именно этот код, который пытается быстро определить, требует ли выражение переоценки.Это странно, но, возможно, подсказка (кому-то), что это происходит не чаще одного раза в цикле «В то время как».Так что в плохих случаях что-то происходит, что предотвращает повторение, в то время как в то время как.
Одно время я был знаком с кодом обнаружения переоценки, написав его фрагмент.Но он был переписан для версии 8. Так что даже после того, как я увидел это неоптимальное поведение в отладчике, для меня это загадка.Все, что я могу сейчас сказать, это то, что я подал отчет об ошибке.
Как заметил Леонид Шифрин, символы с атрибутом HoldAllComplete неуязвимы для этой проблемы.Поэтому использование этого атрибута может быть полезным для этого типа кода.
Daniel Lichtblau Wolfram Research