Re[8]: Ковариантность по возвращаемому значению в виртуальных методах.
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 21.02.13 14:15
Оценка:
Здравствуйте, Jack128, Вы писали:

J>Здравствуйте, gandjustas, Вы писали:


G>>Здравствуйте, Jack128, Вы писали:


G>>>>Ты же наследование делаешь чтобы обращаться к наследникам через ссылку на базовый класс. Соответственно непонятно зачем в наследнике менять типы, и как сообщить компилятору какой тип правильный.

G>>>>Вообще есть вероятность нарушения LSP при таком поведении.
J>>>"такое поведение" — это поведение MyCollection2? естественно нарушит LSP. И именно этого и поможет избежать предлагаемая фича.
G>>Как она поможет избежать? Примером кода пожалуйста.

J>class CollectionItem {}

J>class Collection
J>{
J> protected virtual CollectionItem CreateItem() {...}
J>}



J>class MyCollectionItem: CollectionItem {}

J>class MyCollection: Collection
J>{
J> protected override MyCollectionItem CreateItem() {...}
J>}

J>class MyCollection2: MyCollection

J>{
J> // protected override CollectionItem CreateItem() {...} так ошибка компиляции, так как CollectionItem не является MyCollectionItem, ковариантность нарушится. Раз не компилируется, то LSP не сможем нарушить.
J> protected override MyCollectionItem CreateItem() {...} // а так вполне можно.

J>}


Надо как-то связь межу MyCollection2 и MyCollectionItem передавать. А это делается через генерики.
Делай так:

class CollectionItem {}
class Collection<T> 
{
    protected virtual T CreateItem() {...}
}
Re[10]: Ковариантность по возвращаемому значению в виртуальных методах.
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 21.02.13 14:20
Оценка:
Здравствуйте, samius, Вы писали:

S>Здравствуйте, gandjustas, Вы писали:


G>>Здравствуйте, samius, Вы писали:


S>>>>>вот это уже ковариантность.

G>>>>Да ну? А где здесь функтор?

S>>>А зачем функтор?

G>>А что такое вариантность вообще?
S>Это смотря где.
S>А в контексте программирования под ковариантностью и контрвариантностью подразумевают взаимозаеняемость и эквивалентность типов в определенных ситуациях на основе отношений типов (частное/общее).

С точки зрения теории категорий (на которой основаны системы типов). Есть объект (тип) и стрелки между ними (отношения тип-подтип, она же взаимозаменяемость) вместе это категория. Есть функтор (генерик или массив), который преобразует одну категорию в другую (на самом деле в подкатегорию исходной, но это тут неважно). Так вот в зависимости он воздействия функтора на стрелки его вариантность и определяется. В принципе могут быть и другие функторы, но, насколько я знаю, в C# других, похожих на функторы, частей нету.
Re[5]: Что нужно добавить в C#?
От: Цыба Украина  
Дата: 21.02.13 14:22
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Я исхожу из реальной проблемы: часто встречаешь набор функций, которые относятся только к enum'у, но хостятся в классе Utils, Converters и т.п. Если их можно было бы засунуть в сам enum, было бы понятно:


Решение не менее реальной проблемы на Java:

                             // V - для своего lookupIndexedEnumValue() в ответ на жирный аналог в LengthUnit.Parse
public enum RoleType implements IIndexable<String>, IRoleAuthorizationContextFactory  {

    ADMINISTRATOR("admin") {
        @Override
        public IRoleAuthorizationContext createRoleAuthorizationContext(Request request) {
            return new AdministratorRoleAuthorizationContext();
        }
    },

    EDITOR("editor") {
        @Override
        public IRoleAuthorizationContext createRoleAuthorizationContext(Request request) {
            return new EditorRoleAuthorizationContext(request);
        }
    };

    private final String alias;

    RoleType(String alias) {
        this.alias = alias;
    }

    @Override
    public final String getIndexKey() {
        return alias;
    }

}


И внезапно в аннотациях/аттрибутах:

public interface IService {

    @Role(ADMINISTRATOR)
    void foo();

    @Role(EDITOR)
    void bar();

}


Что здесь плохого?
Re: Что нужно добавить в C#?
От: Osaka  
Дата: 21.02.13 16:16
Оценка: -2
http://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/2049821-debug-lambda-expressions
Друга ищи не того, кто любезен с тобой, кто с тобой соглашается, а крепкого советника, кто полезного для тебя ищет и противится твоим необдуманным словам.
Re[6]: Что нужно добавить в C#?
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 21.02.13 16:24
Оценка:
Здравствуйте, Aлeкceй, Вы писали:

A>Вообще есть шанс, что хоть какие-нибудь наши хотелки реализуют?


Шанс есть. А вот какой — этого я сказать не могу.
... << RSDN@Home 1.2.0 alpha 5 rev. 23 on Windows 8 6.2.9200.0>>
AVK Blog
Re[11]: Ковариантность по возвращаемому значению в виртуальных методах.
От: samius Япония http://sams-tricks.blogspot.com
Дата: 21.02.13 18:39
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Здравствуйте, samius, Вы писали:


S>>А в контексте программирования под ковариантностью и контрвариантностью подразумевают взаимозаеняемость и эквивалентность типов в определенных ситуациях на основе отношений типов (частное/общее).


G>С точки зрения теории категорий (на которой основаны системы типов). Есть объект (тип) и стрелки между ними (отношения тип-подтип, она же взаимозаменяемость) вместе это категория.

Стрелка тип-подтип уже не дает взаимозаменяемости в полной мере, т.к. в зависимости от обстоятельств, либо подтип может быть сконвертирован в тип, либо тип в подтип.

G>Есть функтор (генерик или массив), который преобразует одну категорию в другую (на самом деле в подкатегорию исходной, но это тут неважно). Так вот в зависимости он воздействия функтора на стрелки его вариантность и определяется. В принципе могут быть и другие функторы, но, насколько я знаю, в C# других, похожих на функторы, частей нету.


Генерики там совсем с другой стороны. Функтор (согласно википедии же) определяет функцию преобразования типа F : C x C -> C и совершенно не имеет отношения к массиву. Ну разве что косвенно, т.к. преобразования типов можно делать как на уровне string -> object, так и на уровне T<X> -> T<Y> или string[] -> object[].
C# изначально позволял работать с вариантностью на уровне параметров методов, возврата результата метода, исключений и т.п. И лишь недавно стал более-менее полно поддерживать вариантность дженериков.
Re[9]: Ковариантность по возвращаемому значению в виртуальных методах.
От: Jack128  
Дата: 21.02.13 19:16
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Надо как-то связь межу MyCollection2 и MyCollectionItem передавать. А это делается через генерики.

G>Делай так:

G>
G>class CollectionItem {}
G>class Collection<T> 
G>{
G>    protected virtual T CreateItem() {...}
G>}
G>


http://www.rsdn.ru/forum/dotnet/5077257.1
Автор: Jack128
Дата: 21.02.13
Re[12]: Ковариантность по возвращаемому значению в виртуальн
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 21.02.13 19:50
Оценка:
Здравствуйте, samius, Вы писали:

S>Здравствуйте, gandjustas, Вы писали:


G>>Здравствуйте, samius, Вы писали:


S>>>А в контексте программирования под ковариантностью и контрвариантностью подразумевают взаимозаеняемость и эквивалентность типов в определенных ситуациях на основе отношений типов (частное/общее).


G>>С точки зрения теории категорий (на которой основаны системы типов). Есть объект (тип) и стрелки между ними (отношения тип-подтип, она же взаимозаменяемость) вместе это категория.

S>Стрелка тип-подтип уже не дает взаимозаменяемости в полной мере, т.к. в зависимости от обстоятельств, либо подтип может быть сконвертирован в тип, либо тип в подтип.

Ни слова не понял.

G>>Есть функтор (генерик или массив), который преобразует одну категорию в другую (на самом деле в подкатегорию исходной, но это тут неважно). Так вот в зависимости он воздействия функтора на стрелки его вариантность и определяется. В принципе могут быть и другие функторы, но, насколько я знаю, в C# других, похожих на функторы, частей нету.


S>Генерики там совсем с другой стороны. Функтор (согласно википедии же) определяет функцию преобразования типа F : C x C -> C и совершенно не имеет отношения к массиву. Ну разве что косвенно, т.к. преобразования типов можно делать как на уровне string -> object, так и на уровне T<X> -> T<Y> или string[] -> object[].

Функтор эта статья? Там нет определения, которое ты написал.
Давай с начала.
Есть категория (множество) типов T. Есть преобразование этой категории, которое для каждого типа t из T позволяет получить IEnumerable<t> (по сути тоже из T). Это преобразование называется функтором (в данном случае эндофунктором, но это неважно).
Аналогичное можно сказать по Action<T>, и про массивы.

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

а вот твой пример

object x = 1 as int;

Ну никак он на функторы не похож.


S>C# изначально позволял работать с вариантностью на уровне параметров методов, возврата результата метода, исключений и т.п. И лишь недавно стал более-менее полно поддерживать вариантность дженериков.

На уровне языка — да, на уровне clr всегда так и работало.
Re[6]: Что нужно добавить в C#?
От: Roman Odaisky Украина  
Дата: 21.02.13 21:03
Оценка:
Здравствуйте, VladD2, Вы писали:

Ц>>>Есть "покруче".

KP>>ААА! Вот откуда эту идею в Rust притащили :))
VD>Гы-гы (2005-й год). Думаю, что и до этого где-то было.

В Perl было еще в прошлом веке.
До последнего не верил в пирамиду Лебедева.
Re[4]: Что нужно добавить в C#?
От: Санёк81 Россия  
Дата: 21.02.13 22:00
Оценка:
Здравствуйте, k0st1x, Вы писали:

K>как временное решение или workaround,

K>можно примотать мизинец к безымянному пальцу, ну или приклееть суперклеем.

Пиши на VB
http://rsdn.ru/poll/3816
Автор: Санёк81
Дата: 31.01.13
Вопрос: С кем из участников форума вы хотели бы подраться (добавляйте свои варианты)?
Re[13]: Ковариантность по возвращаемому значению в виртуальных методах.
От: samius Япония http://sams-tricks.blogspot.com
Дата: 22.02.13 00:09
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Здравствуйте, samius, Вы писали:


G>>>С точки зрения теории категорий (на которой основаны системы типов). Есть объект (тип) и стрелки между ними (отношения тип-подтип, она же взаимозаменяемость) вместе это категория.

S>>Стрелка тип-подтип уже не дает взаимозаменяемости в полной мере, т.к. в зависимости от обстоятельств, либо подтип может быть сконвертирован в тип, либо тип в подтип.

G>Ни слова не понял.

Не суть важно. В двух словах отношение тип-подтим и взаимозаменяемость это не одно и то же.

S>>Генерики там совсем с другой стороны. Функтор (согласно википедии же) определяет функцию преобразования типа F : C x C -> C и совершенно не имеет отношения к массиву. Ну разве что косвенно, т.к. преобразования типов можно делать как на уровне string -> object, так и на уровне T<X> -> T<Y> или string[] -> object[].

G>http://ru.wikipedia.org/wiki/%D0%A4%D1%83%D0%BD%D0%BA%D1%82%D0%BE%D1%80_(%D0%BC%D0%B0%D1%82%D0%B5%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B0) эта статья? Там нет определения, которое ты написал.
Covariance and contravariance (computer science) / 2. Origin of the rerms
G>Давай с начала.
Давай

G>Есть категория (множество) типов T.

Что бы построить категорию, нужен еще и морфизм. Одного множества недостаточно для указания категории.
Вариантность рассматривается на категории C, которую образует множество типов и морфизм отношения подтипа.

G>Есть преобразование этой категории, которое для каждого типа t из T позволяет получить IEnumerable<t> (по сути тоже из T). Это преобразование называется функтором (в данном случае эндофунктором, но это неважно).

Я поспорю что это построение T -> IEnumerable<T> есть функтор в общем понимании. В C# он стал функтором только с тех пор, как стал сохранять морфизм отношения подтипов.

G>Аналогичное можно сказать по Action<T>, и про массивы.

Массивы ограниченно сохрнаняли морфизм подтипов с первой версии. А Action<T> — нет.

G>Так вот в категории кроме объектов (типов) есть еще и между объектами. В нашем случае стрелки — отношения "тип-подтип", которые задаются наследованием. Так вот функтор, сохраняющий это отношение в результирующей категории называется ковариантным.

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

G>а вот твой пример


G>
G>object x = 1 as int;
G>

G>Ну никак он на функторы не похож.
Здесь ты прав. Я поспешил и неверно интерпретировал примеры из статьи.

S>>C# изначально позволял работать с вариантностью на уровне параметров методов, возврата результата метода, исключений и т.п. И лишь недавно стал более-менее полно поддерживать вариантность дженериков.

G>На уровне языка — да, на уровне clr всегда так и работало.
А там я тоже поспешил в отношении вариантности возврата результата метода, чем C# никогда не страдал. Это как раз то, о чем пишет Jack128. Подробнее тут (http://en.wikipedia.org/wiki/Covariant_return_type)
Re[5]: Что нужно добавить в C#?
От: k0st1x Марс  
Дата: 22.02.13 06:05
Оценка:
Здравствуйте, Санёк81, Вы писали:

Сё>Здравствуйте, k0st1x, Вы писали:


K>>как временное решение или workaround,

K>>можно примотать мизинец к безымянному пальцу, ну или приклееть суперклеем.

Сё>Пиши на VB


прискорбно, что смена языка — единственное решение неудобства
Re: Что нужно добавить в C#?
От: SergASh  
Дата: 22.02.13 11:42
Оценка: 33 (1) +1
Здравствуйте, AndrewVK, Вы писали:

Нельзя ли сделать так, чтобы enum'ы реализовывали интерфейс IEquatable<> ?
Re[6]: Что нужно добавить в C#?
От: Аноним  
Дата: 22.02.13 22:47
Оценка:
Здравствуйте, Цыба, Вы писали:

Ц>Что здесь плохого?


Не уверен, что я все понял правильно, и если нет, сразу простите дурака. Но если да, то это типичный пример ява-стайл ОООП'а (Over-engineered OOP), который меня просто убивает.

Плохо в этом примере то, что он скрывает неявное множественное наследование от System.Attribute и System.Enum.

Вообще, я за ООП в целом и множественное наследование в частности в каждом УЯП, но МН нужно таааааак редко... и это явно не тот случай. Пусть котлеты будут отдельно, а мухи — отдельно:

public enum RoleType
{
    ADMINISTRATOR,
    EDITOR;

    public IRoleAuthorizationContext ToContext(Request request)
    {
        switch (value)
        {
            case ADMINISTRATOR: return new AdministratorRoleAuthorizationContext(); break;
            case EDITOR:        return new EditorRoleAuthorizationContext(request); break;
            default:            throw new Exception("A new role was added with no converting code."); break;
        }
    }
}

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class RoleTypeAttribute : System.Attribute
{
    ...
}

public interface IService
{
    [RoleTypeAttribute(RoleType.ADMINISTRATOR)]
    void foo();

    [RoleTypeAttribute(RoleType.EDITOR)]
    void bar();
}


Обратите внимание на выделенное. Где ему место в вашем примере?

И раз уж речь зашла о нововведениях и Ските, то вот тут:

http://stackoverflow.com/questions/294216/why-does-c-sharp-forbid-generic-attribute-types

Скит пишет следующее:

Well, I can't answer why it's not available, but I can confirm that it's not a CLI issue. The CLI spec doesn't mention it (as far as I can see) and if you use IL directly you can create a generic attribute. The part of the C# 3 spec that bans it — section 10.1.4 "Class base specification" doesn't give any justification.

The annotated ECMA C# 2 spec doesn't give any helpful information either, although it does provide an example of what's not allowed.

My copy of the annotated C# 3 spec should arrive tomorrow... I'll see if that gives any more information. Anyway, it's definitely a language decision rather than a runtime one.

EDIT: Answer from Eric Lippert (paraphrased): no particular reason, except to avoid complexity in both the language and compiler for a use case which doesn't add much value.


Так что, если бы они ЭТО пофиксили, то ваш пример (именно ваш, без привязки к методам и с потенциальной неоднозначностью ролей) мог бы выглядеть так:

public enum RoleType
{
    ADMINISTRATOR,
    EDITOR;

    public IRoleAuthorizationContext ToContext(Request request)
    {
        switch (value)
        {
            case ADMINISTRATOR: return new AdministratorRoleAuthorizationContext(); break;
            case EDITOR:        return new EditorRoleAuthorizationContext(request); break;
            default:            throw new Exception("A new role was added with no converting code."); break;
        }
    }
}

public interface IService
{
    [System.EnumAttribute<RoleType>(RoleType.ADMINISTRATOR)]
    void foo();

    [System.EnumAttribute<RoleType>(RoleType.EDITOR)]
    void bar();
}


P.S. Чего мне в дотнете всегда не хватало, это набора стандартизированных интерфейсов, чтоб не пилить самому каждый раз, особенно в ремотных системах. System.EnumAttribute<T> это как раз из этой оперы.
Re[2]: Что нужно добавить в C#?
От: neFormal Россия  
Дата: 22.02.13 23:01
Оценка: -1
Здравствуйте, AK85, Вы писали:

AK>
AK>r = a.?b.?c;
AK>

AK>Это кажется называется Maybe monad.
AK>Синтаксис подсмотрен у Bart de Smet.

а если бы дальше первого fail-by-null не выходило, цены бы ему не было
в groovy такое было реализовано, имхо люто неудобно.
...coding for chaos...
Re[7]: Что нужно добавить в C#?
От: Цыба Украина  
Дата: 22.02.13 23:30
Оценка:
Здравствуйте, Аноним, Вы писали:

Синтаксис Java может показаться непривычным и немножко сбивать с толку.

А>Не уверен, что я все понял правильно, и если нет, сразу простите дурака. Но если да, то это типичный пример ява-стайл ОООП'а (Over-engineered OOP), который меня просто убивает.


Пускай. Дело привычки, простоты повторного использования и издержек самой Java.

А>Плохо в этом примере то, что он скрывает неявное множественное наследование от System.Attribute и System.Enum.


Тут нет множественного наследования и не может такового быть. Перечисления неявно наследуются исключительно от java.lang.Enum<E>, хотя и имплементирует интерфейс. Пожалуй, я неудачно выбрал имена Role и RoleType? То, что вы, возможно, посчитали за наследование от System.Attribute -- аннотация @Role, аналог [RoleAttribute] (укажу ниже). Я здесь имел в виду то, что элемент такого перечисления может появляться в качестве значения аннотации. В .NET такое невозможно, насколько мне известно, и поэтому приходится довольствоваться только тем, что может быть константой (по поводу typeof не знаю, то в Java это считается константой, как и элемент перечисления). Могу ошибаться.

А>Обратите внимание на выделенное. Где ему место в вашем примере?


Я тогда просто хотел показать, что полноценный объект, хоть и с ограничениями enum и @interface на типы, а не простая целочисленная константа, может указываться в аннотации (аттрибута). Собственно, тогда уж и недостающий пример:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Role { // аналог аттрибута; аналога AllowMultiple не существует

    RoleType value();    // RoleType - само перечесление, которое можно использовать в качестве значения анотации (value можно опускать)

}


А>И раз уж речь зашла о нововведениях и Ските, то вот тут:

А>http://stackoverflow.com/questions/294216/why-does-c-sharp-forbid-generic-attribute-types
А>Скит пишет следующее:
А>...

@interface в Java тоже не может быть generic, как и enum. В моём случае перечисление просто обязуется реализовать параметризированный generic-интерфейс (для поиска члена перечисления не по имени, а по алиасу). Мне, честно говоря, сложно подобрать случай, в котором нужны generic-аттрибуты, когда из доступных значений аттрибутов могут быть только примитивы и строки.
Re[4]: Что нужно добавить в C#?
От: kkolyan  
Дата: 23.02.13 14:52
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Здравствуйте, Tom, Вы писали:


Tom>>А что не так с x64 если не секрет?


AVK>Он крайне дохлый в плане оптимизации. Поэтому первым будут заменять именно его.



попробовал выполнить код(ниже) на жаве и сишарп
2.9гг
c# — релиз, nf4.5(64 бита за 1700 млс, 32 — 2044)
java — jdk 7u15 выполняет за 2000 млс,
так что вроде с оптимизациями нормально или чтото не так под эклипсом запустил?


public class Tester {

    /**
     * @param args
     */
    public static void main(String[] args) {

        long start = System.currentTimeMillis();
        int m = 1024 * 1024;
        Test(100 * m);
        long end = System.currentTimeMillis();
        System.out.println("time" + (end - start));

    }

    static void Test(int limit_) {
        int limit = limit_;
        int sqr_lim;
        boolean[] is_prime = new boolean[limit + 1];
        int x2, y2;
        int i, j;
        int n;

        sqr_lim = (int) Math.sqrt(limit);
        for (i = 0; i <= limit; i++)
            is_prime[i] = false;
        is_prime[2] = true;
        is_prime[3] = true;

        x2 = 0;
        for (i = 1; i <= sqr_lim; i++) {
            x2 += 2 * i - 1;
            y2 = 0;
            for (j = 1; j <= sqr_lim; j++) {
                y2 += 2 * j - 1;

                n = 4 * x2 + y2;
                if ((n <= limit) && (n % 12 == 1 || n % 12 == 5))
                    is_prime[n] = !is_prime[n];

                // n = 3 * x2 + y2;
                n -= x2;
                if ((n <= limit) && (n % 12 == 7))
                    is_prime[n] = !is_prime[n];

                // n = 3 * x2 - y2;
                n -= 2 * y2; //
                if ((i > j) && (n <= limit) && (n % 12 == 11))
                    is_prime[n] = !is_prime[n];
            }
        }

        for (i = 5; i <= sqr_lim; i++) {
            if (is_prime[i]) {
                n = i * i;
                for (j = n; j <= limit; j += n) {
                    is_prime[j] = false;
                }
            }
        }

    }

}



using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;

namespace cappTestPrime
{
    public class Tester
    {


        public static void Main(String[] args)
        {

            var sw = Stopwatch.StartNew();

            int m = 1024 * 1024;

            Test(100 * m);

            var end = sw.ElapsedMilliseconds;
            Console.WriteLine("elapsed=" + end);


        }

        static void Test(int limit_)
        {
            int limit = limit_;
            int sqr_lim;
            bool[] is_prime = new bool[limit + 1];
            int x2, y2;
            int i, j;
            int n;

            sqr_lim = (int)Math.Sqrt(limit);

            for (i = 0; i <= limit; i++)
                is_prime[i] = false;
            is_prime[2] = true;
            is_prime[3] = true;

            x2 = 0;
            for (i = 1; i <= sqr_lim; i++)
            {
                x2 += 2 * i - 1;
                y2 = 0;
                for (j = 1; j <= sqr_lim; j++)
                {
                    y2 += 2 * j - 1;

                    n = 4 * x2 + y2;
                    if ((n <= limit) && (n % 12 == 1 || n % 12 == 5))
                        is_prime[n] = !is_prime[n];

                    // n = 3 * x2 + y2;
                    n -= x2;
                    if ((n <= limit) && (n % 12 == 7))
                        is_prime[n] = !is_prime[n];

                    // n = 3 * x2 - y2;
                    n -= 2 * y2; // 
                    if ((i > j) && (n <= limit) && (n % 12 == 11))
                        is_prime[n] = !is_prime[n];
                }
            }

            for (i = 5; i <= sqr_lim; i++)
            {
                if (is_prime[i])
                {
                    n = i * i;
                    for (j = n; j <= limit; j += n)
                    {
                        is_prime[j] = false;
                    }
                }
            }

        }

    }
}
Re: Что нужно добавить в C#?
От: FlevelEx Россия  
Дата: 23.02.13 18:45
Оценка: +1 -1
Здравствуйте, AndrewVK, Вы писали:

AVK>Соответственно, от вас хотелось бы получить те фичи, которых не хватает лично вам.




void Test(object sender)
{
    if (sender is not Smth1)
    {
    }
}



вместо


void Test(object sender)
{
    if (!(sender is Smth1))
    {
    }
}
Re[2]: Что нужно добавить в C#?
От: alexzz  
Дата: 23.02.13 18:52
Оценка: +1
Здравствуйте, FlevelEx, Вы писали:

FE>
FE>void Test(object sender)
FE>{
FE>    if (sender is not Smth1)
FE>    {
FE>    }
FE>}
FE>


public static class ObjectExtensions
{
    public static bool IsNot<T>(this object obj)
    {
        return obj is T == false;
    }
}
Re[3]: Что нужно добавить в C#?
От: VladD2 Российская Империя www.nemerle.org
Дата: 23.02.13 20:20
Оценка: :)
Здравствуйте, AndrewVK, Вы писали:

AVK>Основная проблема с ПМ, как озвучил Мэдс, в АТД. Это новый first class citizen, который отчасти дублирует существующие сущности в языке. Так что АТД ака discriminated unions на данный момент однозначно no way. Теоретически можно обойтись без АТД существующими типами с какими то дополнительными доработками, но тут нужно говорить более конкретно.


Перевожу на русский язык — "Нам хочется еще лет 5-10 по-вредничать.", потому как в ином случае объяснить подобные утверждения можно только недостатком знаний и не желанием смотреть на то что валяется под ногами.

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

Две основные фичи ПМ, которые делают его мощной штукой это:
1. Рекурсивность.
2. Динамические проверки типов.

Вот пример ПМ по классам из N2:
match (RuleSymbol)
{
  | ExtensibleRuleSymbol => ()
  | ExtentionRuleSymbol(BaseRule = RuleRef.Some(baseRuleSymbol), ExtentionType = Prefix) =>
    defineExtentionRuleMethods(baseRuleSymbol)

  | ExtentionRuleSymbol(BaseRule = RuleRef.Some(baseRuleSymbol), ExtentionType = Postfix(bindingPower, _)) =>
    defineExtentionRuleMethods(baseRuleSymbol);
    _descriptorTb.DefineConditional(<[decl: public override BindingPower : int { get { $(bindingPower : int) } } ]>);

  | SimpleRuleSymbol  => defineNewParserMethod(<[ N2.Internal.SimpleRuleParser ]>);
  | RegularRuleSymbol => ()
  | _       => assert(false)
}

Здесь BaseRule и ExtentionType — это поля имеющие вариантный тип (АлгТД), а все остальное — это классы.
RuleSymbol — это свойство типа RuleDefSymbol, а ExtensibleRuleSymbol, ExtentionRuleSymbol, SimpleRuleSymbol и RegularRuleSymbol его наследники. Причем непрямые.

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

Кстати, закрытость набора можно обеспечить банальным seled.

Есть только одна фича МП которая упирается в возможности АлгТД — описание паттерна в виде конструктора. Это позволяет несколько сократить синтаксис описывая состояние объекта в виде параметров его конструктора. Чтобы это было возможно нужно иметь соответствие между полями типа и параметрами конструктора.

Так вот, во-первых можно обходиться несколько более длинным синтаксисом в котором внутри паттерна явно указывается имя члена который нужно проверить. Зачастую это даже оказывается более удобным, так как позволяет не перечислять все параметры конструктора забивая большую часть вилдкардами (знаком _ в ФЯ).

Во-вторых, соответствие между аргументами конструктора и полями можно задать и способами отличными от тех что используются в АлгТД. Например, можно обратиться к опыту Скалы. В ней можно объявлять конструкторы прямо в синтаксисе объявления классов (синтаксис псевдошарпа):
class C(int firstField, string secondField)
{
}
...
var c = C(42, "wow");
Console.WriteLine(c.firstField);


Здесь firstField и secondField это одновременно и поля класса С и параметры его единственного конструктора. Прибавляем сюда наследование и получаем все что нужно для классических конструкторных паттернов. Для старых типов можно использовать аннотацию задаваемую кастом-атрибутами.

В общем, если у них проблемы с дизайном, могу за скромную сумму (ну, скажем 10К зеленых) спроектировать поддержку ПМ для шарпа, что называется под ключ (с грамматикой и описанием семантики).
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.