Написание только статических методов эквивалентно программированию без побочных эффектов в C #? - PullRequest
6 голосов
/ 01 августа 2011

У меня есть два вопроса, вытекающих из наблюдаемого поведения статических методов C # (которые я могу неправильно истолковать):

Во-первых: Будет ли рекурсивный статический метод оптимизирован в некотором смысле путем реализации статического метода под прикрытием?

Во-вторых: Было бы эквивалентно функциональному программированию написать целое приложение со статическими методами и без переменных за пределами локальной области видимости? Мне интересно, потому что я до сих пор не обернул голову вокруг этого термина «без побочных эффектов», который я постоянно слышу о функциональном программировании ..

Edit: Позвольте мне упомянуть, я использую и понимаю, почему и когда использовать статические методы в обычной методологии C # OO, и я понимаю, что оптимизация хвостового вызова не будет явно выполняться для рекурсивного статического метода. Тем не менее, я понимаю, что оптимизация хвостового вызова - это попытка остановить создание нового стекового фрейма с каждым проходом, и я несколько раз наблюдал, как выглядит статический метод, выполняющийся в кадре вызывающего метода, хотя Возможно, я неправильно истолковал свое наблюдение.

Ответы [ 4 ]

6 голосов
/ 01 августа 2011

Может ли рекурсивный статический метод быть оптимизирован хвостовым способом в некотором смысле благодаря тому, что статический метод реализован под прикрытием?

Статические методы не имеют ничего общего с оптимизацией хвостовой рекурсии. Все правила в равной степени применимы к экземпляру и статическим методам, но лично я никогда бы не положился JIT оптимизирует мой хвост. Более того, C # компилятор не выдает команду хвостового вызова, но иногда она все равно выполняется . Короче, вы никогда не знаете .

Компилятор F # поддерживает оптимизацию хвостовой рекурсии и, по возможности, компилирует рекурсию в циклы.
Подробнее о поведении C # и F # в этом вопросе .

Было бы эквивалентно функциональному программированию написать целое приложение со статическими методами и без переменных за пределами локальной области видимости?

Это одновременно нет и да .

Технически, ничто не мешает вам вызывать Console.WriteLine из статического метода (который сам является статическим методом!), Который, очевидно, имеет побочных эффектов. Ничто также не мешает вам написать класс (с методами экземпляра), который не изменяет никакого состояния (то есть методы экземпляра не обращаются к полям экземпляра). Однако, с точки зрения дизайна, такие методы не имеют смысла как методы экземпляров, верно?

Если вы Add отправляете элемент в .NET Framework List<T> (который имеет побочные эффекты), вы измените его состояние.
Если вы append элемент в список F # , вы получите другой список , и оригинал не будет изменен.

Обратите внимание, что append действительно - это статический метод для модуля List. Написание методов «преобразования» в отдельных модулях поощряет проектирование без побочных эффектов, поскольку внутреннее хранилище по определению не доступно , даже если язык это позволяет (F # делает, LISP нет). Однако ничто действительно не мешает вам написать нестатический метод без побочных эффектов .

Наконец, если вы хотите использовать понятия функционального языка, используйте один! Гораздо более естественно писать модули F #, которые работают с неизменяемыми структурами данных F #, чем имитировать то же самое в C # со статическими методами или без них.

3 голосов
/ 01 августа 2011

CLR выполняет некоторую оптимизацию хвостового вызова, но только в 64-битных процессах CLR. Смотрите, где это делается: Блог API профилирования CLR Дэвида Бромана: условия JIT для хвостового вызова .

Что касается создания программного обеспечения только со статическими переменными и локальной областью действия, я много сделал, и это на самом деле хорошо. Это просто еще один способ сделать то же самое, что и ОО. Фактически, поскольку нет состояния вне функции / замыкания, его безопаснее и проще тестировать.

Сначала я прочитал всю книгу SICP от корки до корки: http://mitpress.mit.edu/sicp/

Отсутствие побочных эффектов означает, что функцию можно вызывать с одинаковыми аргументами столько раз, сколько вам нужно, и всегда возвращать одно и то же значение. Это просто определяет, что результат функции всегда согласован, поэтому не зависит от какого-либо внешнего состояния. В связи с этим тривиально распараллеливать функцию, кэшировать ее, тестировать, модифицировать, декорировать и т. Д.

Однако система без побочных эффектов, как правило, бесполезна, поэтому у вещей, которые делают IO, всегда будут побочные эффекты. Это позволяет вам аккуратно инкапсулировать все остальное, хотя в этом и заключается смысл.

Объекты - не всегда лучший способ, несмотря на то, что люди говорят. Фактически, если вы когда-либо использовали вариант LISP, вы без сомнения определите, что типичный ОО иногда мешает.

1 голос
/ 29 февраля 2012

На эту тему написана довольно хорошая книга, http://www.amazon.com/Real-World-Functional-Programming-Examples/dp/1933988924.

И в реальном мире использование F #, к сожалению, не подходит из-за командных навыков или из-за существующих кодовых баз, что является еще одной причиной, по которой мне очень нравится эта книга, так как она показывает много способов реализации функций F # в коде, который вы используете днем сегодня. И для меня, по крайней мере, значительное уменьшение количества ошибок в состоянии, отладка которых занимает гораздо больше времени, чем простые логические ошибки, стоит небольшого уменьшения ортодоксальности ООП.

По большей части отсутствие статического состояния и работа в статическом методе только с указанными параметрами устранят побочные эффекты, поскольку вы ограничиваете себя только чистыми функциями. Однако следует обратить внимание на то, что нужно извлекать данные для обработки или сохранять данные в базе данных с помощью такой функции. Однако здесь может помочь сочетание ООП и статических методов, поскольку ваши статические методы делегируют команды объектов более низкого уровня для управления состоянием.

Кроме того, большая помощь в обеспечении чистоты функции заключается в том, чтобы поддерживать объекты неизменяемыми, когда это возможно. Любой действующий объект должен возвращать новый измененный экземпляр, а исходная копия удаляется.

1 голос
/ 01 августа 2011

Относительно второго вопроса: я полагаю, что вы имеете в виду «побочные эффекты» изменчивых структур данных, и, очевидно, это не проблема для (я полагаю) большинства функциональных языков.Например, Haskel в основном (или даже все !?) использует неизменяемые структуры данных.Так что в «статическом» поведении ничего нет.

...