Допустим есть ф-ция long-calculation, которая внутри себя содержит некую свободную переменную a. Если прогер знает, что эта а не будет изменяться во время исполнения, то ф-цию он не будет использовать (вызывать) в дальнейщем коде, а запишет все в переменную result, и будет использовать ее. Компилятор, по-идее, должен сделать то же самое. Но как он узнает, будет ли она изменяться? Допустим, если не предусмотрено динамическое изменение, во время исполнения, он может просто пропарсить код. В других случаях, поможет явная декларация.
Итого: если код не сможет оптимизировать прогер, этого не сможет сделать и компилятор. Выигрыш в писанине для прогера нулевой: либо Result = call long-calculation, либо type: clear_func fu: long-calculation
Идем далее. Что если прогер все же захочет оптимизировать код в грязной ф-ции? Он просто завернет муттабельную переменную в ф-цию, и присвоит переменной result не результат вычисления long-calculation, а ф-цию, возвращающую вычисления с этой переменной, т.е. он вычислит long-calculation не до конца, а сколько возможно, без учета изменения a. Как вариант, он может создать переменную b, которая будет ссылаться на символ (не значение) муттабельной a. Соответственно, ф-ция long-calculation будет пользоваться чистой b, а не грязной a, поэтому можно соптимизировать. Правда, ссылка на символ не во всех ЯП возможна, но это уже другой вопрос, а в целом, такая техника даже более прозрачна, чем фп-стиль. Компилятор, естественно, сделет примерно то же самое (при наличии соответствующего забубенного синтаксиса деклараций типов и пр.)
Тут напрашивается резонный вопрос: а зачем нужна компиляция, если прогер настолько легко может соптимизировать свой код руками?
С другой стороны, компиляция накладывает на программиста массу ограничений, в том числе, в плане оптимизаций, как ни странно.
Кроме того, следует учесть, что компилятор не обладает умом, и не может определить, что следует оптимизировать, а на что забить, он будет усираться, и оптимизировать все подряд. Это условно, подпадает под определение «преждевременная оптимизация», и не может не сказаться на жирноте компилтайма (что обычно и наблюдается в жабе и хачикиле).
Резюмируюя. Компилятор ограничивает выразительные возможности, гибкость, и (парадоксально) возможности оптимизации ЯП.