Чистые функции в С#

Я знаю, что С# получает много поддержки параллельного программирования, но AFAIK по-прежнему нет конструкций для проверки побочных эффектов, правильно?

Я предполагаю теперь более сложным, что С# уже выложен. Но планируете ли вы это сделать? Или F # единственный язык .NET, который имеет конструкции для проверки побочных эффектов?

Ответ 1

С# язык не есть, но .NET может быть.

Библиотека Контрактов + инструменты статического анализа, внедряемые в .NET 4, могут представить их:

Microsoft использует [Immutable] и [Pure] внутри рамки .NET 3.5 прямо сейчас.

Например, см. [Microsoft.Contracts.Immutable] и [Microsoft.Contracts.Pure] внутри .NET 3.5 в System.Core.dll. К сожалению, они внутренние. Однако Microsoft.Contracts. * В основном рождается из исследования SpeС#, а SpeС# была сложена в API контрактов, который будет частью .NET 4.0.

Мы посмотрим, что из этого получится. Я не проверял, не содержат ли в предварительных версиях .NET 4.0 битов любые API, такие как [Pure] или [Immutable] в API контрактов. Если они это сделают, я бы предположил, что инструмент статического анализа будет тем, чтобы обеспечить соблюдение правила, а не компилятора.

edit Я только что загрузил Microsoft.Contracts.dll из последняя предварительная релиза MS-контрактов на этой неделе. Хорошие новости: в библиотеке существуют атрибуты [Pure] и [Mutability (Mutability.Immutable)], которые предполагают, что они будут в .NET 4.0. Woohoo!

edit 2 Теперь, когда .NET 4 был выпущен, я просмотрел эти типы. [Pure] все еще присутствует в System.Diagnostics.Contracts namespace. Он не предназначен для общего использования, а скорее для использования с проверкой до и после кондиционирования. Это не принудительный компилятор, и инструмент проверки контракта Code Contract не обеспечивает чистоту. [Mutability] ушел. Интересно, что, когда Microsoft использовала атрибуты Mutability и Pure в .NET 3.5 (во внутреннем классе BigInteger в System.Core.dll),.NET 4 переместил BigInteger в System.Numerics и лишил [Pure] и [Mutability] атрибуты этого типа. В нижней строке: показано, что .NET 4 ничего не делает для проверки побочных эффектов.

edit 3 С недавним (в конце 2011 года) просмотренным Microsoft Rosyln компилятором как сервисным сервисом, который, как полагают, запланирован для RTM в Visual Studio 2015, выглядят так, как будто они будут способный поддерживать такие вещи; вы можете написать расширения компилятору, чтобы проверить чистоту и неизменность, а также выдавать предупреждения компилятора, если что-то, украшенное этими атрибутами, не соответствует правилам. Несмотря на это, мы смотрим на несколько лет, чтобы поддержать это.

edit 4 Теперь, когда Rosyln существует с лета 2015 года, способность создавать расширение компилятора для чистой/неизменяемости действительно существует. Тем не менее, это ничего не делает для существующего кода рамки, а также для стороннего библиотечного кода. Но на горизонте есть предложение С# 7 для неизменяемых типов. Это будет принудительно применено компилятором и представит новое ключевое слово неизменяемое для С# и атрибут [Неизменяемый] в .NET framework. Использование:

// Edit #4: This is a proposed design for C# 7 immutable as of June 2015.
// Compiler will implicitly mark all fields as readonly.
// Compiler will enforce all fields must be immutable types.
public immutable class Person
{
    public Person(string firstName, string lastName, DateTimeOffset birthDay)
    {
        FirstName = firstName; // Properties can be assigned only in the constructor.
        LastName = lastName;
        BirthDay = birthDay; 
    }

    public string FirstName { get; } // String is [Immutable], so OK to have as a readonly property
    public string LastName { get; }
    public DateTime BirthDay { get; } // Date is [Immutable] too.
}

edit 5. Ноябрь 2016 года, и появляется неизменяемые типы, которые были сброшены с С# 7. На С# 8. всегда есть надежда: -)

edit 6 В ноябре 2017 года. С# 8 выходит на первый план, и пока у нас не будет чистых функций, у нас будет readonly structs. Это делает структуру неизменной, что позволяет несколько оптимизаций компилятора.

Ответ 2

Мало того, что для проверки побочных эффектов нет ничего - нет ничего даже, чтобы проверить, что тип неизменен, что является меньшим шагом по тому же маршруту IMO.

Я не верю, что в С# 4.0 что-то спустится вниз по трубе (хотя я легко ошибаюсь). Я действительно надеюсь, что неизменность влияет на С# 5.0; конечно же, Эрик Липперт довольно много писал об этом, и люди в MS думали о parallelism справедливой сумме.

Извините, это не более обнадеживающая картина.

Изменить: Иудейский ответ значительно ярче... будет ли поддержка фрейма достаточной для вас?:) (я не был бы полностью удивлен, если некоторые аспекты кодовых контрактов не были готовы для .NET 4.0, заметьте - если возможно, они сохранили начальный выпуск относительно небольшим и увеличили его позже.)

Ответ 3

В принципе, проверка того, является ли что-то неизменным и легко ли в коде недостает побочных эффектов. Все поля структуры класса/данных должны быть только для чтения, а их тип должен быть другим неизменяемым объектом. Нам также нужен способ отметить делегат как "чистый" (свободный от побочных эффектов), но это, вероятно, все возможно.

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

Например, отлично работать с массивами "чистым" способом. У вас могут быть такие методы, как Array.map, которые применяют некоторую функцию ко всем элементам и возвращают новый массив без изменения исходного. Эта функция мутирует (вновь созданный) массив перед его возвратом, но массив не мутирует нигде, поэтому это в принципе чистое, но трудно проверяемое (и это довольно полезный шаблон программирования в F #).

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