Re[4]: C# 7 - названия и прочее
От: VladD2 Российская Империя www.nemerle.org
Дата: 29.04.15 22:27
Оценка: 36 (1) +1
Здравствуйте, Sinix, Вы писали:

S>Не, это

S>
S>if (dict.TryGetValue(key, out var value)
S>{
S>  // do smth with value
S>}
S>

S>Мелочь, но в куче мест сводит необходимость тюплов к нулю.

Вот в F# методы out-параметрами интерпретируются как возвращающие кортеж. Если представить такую фичу в C#, то можно было бы писать следующим образом:
if ((true, var value) = dict.TryGetValue(key))
{
  // do smth with value
}

а лучше:
if (var (true, value) = dict.TryGetValue(key))
{
  // do smth with value
}

так как пихать var в каждую переменную в кортеже не очень разумно.

S>Так ты не с знатоками общайся, а с design team. Они вот тут перечислены.


Они меня среди "знатоков" просто не заметят. В общем, проверено. Это то место откуда информация доходит до кого надо .

S>С теорией всё более-менее ок. А вот ничего близкого к

S>
S>type switchstate =
S>    | On
S>    | Off
S>    | Adjustable of float
S>

S>в шарпе на сегодня нет. Конечно, можно выразить ч/з наследование, но это всё-таки слегка не то.

То, то. F#, просто еще несколько старомоден (унаследовал много от ML и далек от ОО-мира).
В Немерле это выглядит так:
variant SwitchState
{
  | On
  | Off
  | Adjustable { Value : float; }
}

И переписывается в:
[Variant("SwitchState.On,SwitchState.Off,SwitchState.Adjustable")]
internal abstract class SwitchState
{
    [ConstantVariantOption]
    public class On : SwitchState
    {
        public static readonly SwitchState.On _N_constant_object;
        public static SwitchState.On _N_constant_object_generator()
        {
            return SwitchState.On._N_constant_object;
        }
        static On()
        {
            SwitchState.On._N_constant_object = new SwitchState.On();
        }
        public override int _N_GetVariantCode()
        {
            return 0;
        }
        [RecordCtor]
        private On()
        {
        }
    }
    [ConstantVariantOption]
    public class Off : SwitchState
    {
        public static readonly SwitchState.Off _N_constant_object;
        public static SwitchState.Off _N_constant_object_generator()
        {
            return SwitchState.Off._N_constant_object;
        }
        static Off()
        {
            SwitchState.Off._N_constant_object = new SwitchState.Off();
        }
        public override int _N_GetVariantCode()
        {
            return 1;
        }
        [RecordCtor]
        private Off()
        {
        }
    }
    [VariantOption]
    public class Adjustable : SwitchState
    {
        public readonly float Value;
        public override int _N_GetVariantCode()
        {
            return 2;
        }
        [RecordCtor]
        public Adjustable([MappedMember("Value")] float value)
        {
            this.Value = value;
        }
    }
    public abstract override int _N_GetVariantCode();
    public static int _N_GetVariantCodeSafe(SwitchState x)
    {
        return ((object)x != null) ? x._N_GetVariantCode() : -1;
    }
    public static int _N_GetVariantCodeObject(object x)
    {
        int arg_1E_0;
        if (x is SwitchState)
        {
            SwitchState switchState = (SwitchState)x;
            arg_1E_0 = switchState._N_GetVariantCode();
        }
        else
        {
            arg_1E_0 = -1;
        }
        return arg_1E_0;
    }
}

Если абстрагироваться от оптимизаций, то это чистое наследование.
В Скале так вообще сделано так же как в шарпе планируется.

S>Ну да. Но нbкто не запрещает сделать тип с primary ctor но без is operator.


1. Зачем это нужно?
2. Я вообще не вижу смысла в этом операторе is. Точнее то не плохая фича для расширяемости ПМ, но по умолчанию ПМ должен работать и без наличия этого метода. В Немерле информация о связи между полями и параметрами конструктора записывается в атрибут Variant (видно в примере декомпилята).

S>Или использовать PM на любом типе дотнета. Эти фичи ортогональны. record просто позволяет получить типовую реализацию без лишнего кода.


Рекорд просто лишний. Очередная ошибка дизайна, на мой взгляд.

S>Ну блин, это opt-in возможности. Можно добавлять, можно не добавлять. Без модификатора record такое поведение красиво не сделать.


Возможности которые всегда полезны можно добавлять по умолчанию не думая. Если кому-то нужно вручную что-то реализовать, то они могут переопределить нужные методы врунчую.

Тебя ведь не смущает, что для объектов по молчанию работает GetHashCode и т.п.?

А для ПМ не нужно ничего из перечисленного выше. Только первичный конструктор. Да и тот, если хочется пользоваться более лаконичным паттерном конструктор. А для матчинга по свойствам/полям и сойдет любой класс.

S>Что-то я не заметил. Как насчёт чего-нить вот такого

S>
S>type switchstate =
S>    | On
S>    | Off
S>    | Adjustable of float
S>

S>на шарпе? Со всеми прелестями discriminated unions типа контроля со стороны компилятора "проверили все варианты".

См. выше. А для контроля полноты нужно иметь возможность предотвратить создание наследников. В Скале это называется sealed, но смысл отличается от шарповского.
sealed abstract class LogMessage
case class StringMessage(message:String) extends LogMessage
case class ExceptionMessage(exception:Throwable) extends LogMessage
case class BothMessage(message:String, exception:Throwable) extends LogMessage
 
class Logger {
  def debug(l:LogMessage) = log(10,l)
  def info(l:LogMessage) = log(5,l)
  def error(l:LogMessage) = log(1,l)
 
  def log(level:Int, l:LogMessage):Unit = l match  {
    case StringMessage(msg) => println(msg)
    case ExceptionMessage(exception:Error) => exception.printStackTrace
    case ExceptionMessage(ex) => println(ex.toString)
  }
}


S>Нету этого на сегодня. По крайней мере в публичных источниках.


Сегодня ничего нет. Мы же говорим о C# 7. Смотри на Немерл. Его в C# 5 пророчили многие, но он, похоже, C# и в десятой версии всех фичь не реализует.

S>Авральными темпами пилят поддержку всего, от дотнета в docker-контейнерах и до интеропа с android и objective-c кодом. Ага, обе платформы поддерживаются в win 10, на build пару часов назад сознались всё-таки. Занятые они, короче.


Ну, да. 10 лет это ведь так мало для МС.

S>Ну а как equals и хэшкод для таких типов определять? Это надо или нормальные макросы впихивать, или не страдать фигнёй и один раз в жизни сгенерить однотипный код. Т.е. или макросы, или кодогенерацию в compile-time.


Посмотри примеры на С++. Там конечно многе на метапрограммирование завязано, но кое-что можно и более простыми темпами.

Ну, и вы говорите об МП, как о чем-то плохом (ц)
МП — это очень даже хорошо. Когда-нибудь они и до этого дорастут. Но это уже будет C# 10, наверно.

VD>>Ну, и до кучи надо ввести замену этому убогому delegate — функциональный тип.

S>В другой жизни разве что. Слишком многое завязано.

Это можно даже не меняя рантйм сделать. В Nemerle и F# такие типы есть.

Ну, да. У МС процесс озревания идет десятилетиями. Когда-нибудь и до этого дозреют. А жаль, так как такие типы нужны именно в рантайме, а не в отдельных языках.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.