F # как язык отлично подходит для написания переводчиков или компиляторов, однако одна вещь продолжает ударять нас, где мы этого не хотим: исключение StackOverflowException.
Хорошо известно, что исключение SO исключено и не может быть восстановлено. Очевидным методом предотвращения такого исключения является подсчет глубины стека по мере продвижения. Накладные расходы, да, но выполнимы и, возможно, не нужны в каждой функции.
С F # этот метод не приносит большой пользы. Мы много используем методы оптимизации хвостовых вызовов в оперативных выражениях интерпретатора. Проблемы, с которыми мы сталкиваемся с SO-исключениями:
- как мы можем сообщить пользователю о них, а не обрушиться на весь текущий AppDomain?
- Если мы идем для подсчета глубины стека, откуда мы узнаем, является ли функция TCO'ed или inlined, поэтому нам не нужно подсчитывать?
- если мы идем на другой подход (например, проверять сам стек при заданных интервалах глубины), существует ли какой-либо (известный) способ сделать это без серьезного затруднения производительности?
Простое увеличение размера стека не поможет, мы хотим дать пользователю ошибку, зависящую от протокола, которая лучше всего улавливается вызывающим приложением. Для этого нам нужно иметь возможность вручную выбросить исключение, что делает его увлекательным. Но как определить правильный момент?
Обновление:
Ханс Пассант правильно предлагает предсказуемость здесь. Тем не менее, программисты, использующие этот DSL, ожидают, что (определенные) вызовы получат TCO'ed, следовательно, они не хотят сильного ограничения стека. Они знают, что делают. Тем не менее, их программы должны быть способны умереть изящно, по крайней мере до такой степени, что любое вызывающее приложение (т.е. Программа С#, использующая наши библиотеки)
не пострадает.