С# 3.0
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 14.09.05 16:32
Оценка: 65 (8)
Вышел первый прообраз спецификации.
Кому лень читать, вот Краткий пересказ
Автор: AndrewVK
Дата: 14.09.05
.
Здесь лабораторка, но компилятор, наверное, будет доступен только после PDC.
... << RSDN@Home 1.2.0 alpha rev. 617>>
AVK Blog
Re: С# 3.0
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 14.09.05 16:34
Оценка: 6 (1)
AVK>Здесь лабораторка, но компилятор, наверное, будет доступен только после PDC.

Сорри, можно скачать уже сейчас:
http://download.microsoft.com/download/4/7/0/4703eba2-78c4-4b09-8912-69f6c38d3a56/LINQ%20Preview.msi
... << RSDN@Home 1.2.0 alpha rev. 617>>
AVK Blog
Re: С# 3.0
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 14.09.05 16:37
Оценка:
А возможности подключения реализаций опять нет
... << RSDN@Home 1.2.0 alpha rev. 617>>
AVK Blog
Re: С# 3.0
От: Igor Trofimov  
Дата: 14.09.05 19:15
Оценка:
Extensions с generic'ами не живут, что в общем, понятно, но обидно:

    static class ListExt<T>
    {
        public static string First(this List<T> list)
        {
            return list[0];
        }
        public static string Last(this List<T> list)
        {
            return list[list.Count-1];
        }
    }    
    ...
    var list = new List<string> {"aaa", "bbb", "ccc"};
        
    Console.WriteLine(list.First()); // А вот тут хочется extension-свойств!


Не пашет такая попыточка. Хотя вообще-то принципиально это можно было бы сделать.
Всего лишь превращать list.First() не в ListExt<T>.First(list), а в ListExt<string>.First(list), гладя на совпадающее количество type-args.
Re: С# 3.0
От: Igor Trofimov  
Дата: 14.09.05 19:24
Оценка:
А вот интерфейсы extension'ами распознаются на ура:
    static class ListExt
    {
        public static object First(this IList list)
        {
            return list[0];
        }
        public static object Last(this IList list)
        {
            return list[list.Count-1];
        }
        public static bool Contains(this IList list, object item)
        {
            return list.Contains(item);
        }
    }
    ...
    var list = new List<string> {"aa", "bbbbb", "cccc", "dddd"};
    int[] ints = {1,2,3,4,5};

    Console.WriteLine(ints.Last());
    Console.WriteLine(list.Last());
    Console.WriteLine(list.Contains("cccc"));
    Console.WriteLine(ints.Contains(4));


Раньше для проверки вхождения элемента в массив требовалось явно приводить массив к IList.
Extension это делает сам.
Re[2]: С# 3.0
От: Igor Trofimov  
Дата: 14.09.05 19:33
Оценка: 37 (2) +1
Аааааа! Торможу!
Все там пашет:

    static class ListExt
    {
        public static T First<T>(this List<T> list)
        {
            return list[0];
        }
        public static T Last<T>(this List<T> list)
        {
            return list[list.Count-1];
        }
    }


Параметризировать надо конкретный метод а не класс.
(В предыдущем сообщении у меня вообще string затесался откуда-то )
Re: С# 3.0
От: Кодёнок  
Дата: 15.09.05 09:23
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Вышел первый прообраз спецификации.

AVK>Кому лень читать, вот Краткий пересказ
Автор: AndrewVK
Дата: 14.09.05
.

AVK>Здесь лабораторка, но компилятор, наверное, будет доступен только после PDC.

Они-таки сделали это Четвертая версия видимо обещает быть еще более интересной.
Re[2]: С# 3.0
От: Cyberax Марс  
Дата: 15.09.05 09:35
Оценка: -1
Кодёнок wrote:

> AVK>Вышел первый прообраз спецификации

> <http://download.microsoft.com/download/9/5/0/9503e33e-fde6-4aed-b5d0-ffe749822f1b/csharp%203.0%20specification.doc&gt;.
> AVK>Кому лень читать, вот Краткий пересказ
> <http://rsdn.ru/forum/Message.aspx?mid=1382740&amp;only=1&gt;
Автор: AndrewVK
Дата: 14.09.05
.

> AVK>Здесь
> <http://download.microsoft.com/download/9/5/0/9503e33e-fde6-4aed-b5d0-ffe749822f1b/csharp%203.0%20language%20enhancements%20hands%20on%20lab.doc&gt;
> лабораторка, но компилятор, наверное, будет доступен только после PDC.
> Они-таки сделали это Четвертая версия видимо обещает быть еще более
> интересной.

Ну и уродство же они с SQL в языке сделали...

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 2.0 beta
Sapienti sat!
Re[3]: С# 3.0
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 15.09.05 12:42
Оценка: +1
Здравствуйте, Cyberax, Вы писали:

C>Ну и уродство же они с SQL в языке сделали...


Это не SQL, просто на него похоже.
... << RSDN@Home 1.2.0 alpha rev. 617>>
AVK Blog
Re: С# 3.0
От: DarkGray Россия http://blog.metatech.ru/post/ogni-razrabotki.aspx
Дата: 15.09.05 19:15
Оценка: 2 (1) +1
До сих пор не хватает "красивой" работы с нулевыми значениями

сейчас вместо:
if (Root.Config.User.Age > 16)
{
   //bla-bla
}


часто приходиться писать:

int? age = null;
var root = Root;
if (root != null)
{
   var config = root.Config;
   if (config != null) 
  {
      var user = config.User;
      if (user != null) 
        age = user.Age;
   }
}
if (age != null && age.Value > 10)
{
 //bla-bla
}



т.е. хочеться иметь оператор вида '.?', который возвращает нуль, если левая часть имеет нулевое значение

if (Root.?Config.?User.?Age > 16)
{
   //bla-bla
}


или может даже лучше:
if (Root?.Config?.User?.Age > 16)
{
   //bla-bla
}



Особенно это нужно при описании правил бизнес логики, т.к. в бизнес-логики часто мы имеем на руках только частичную информацию о мире
Re[2]: С# 3.0
От: FDSC Россия consp11.github.io блог
Дата: 16.09.05 06:27
Оценка:
Здравствуйте, DarkGray, Вы писали:

DG>До сих пор не хватает "красивой" работы с нулевыми значениями


DG>т.е. хочеться иметь оператор вида '.?', который возвращает нуль, если левая часть имеет нулевое значение


DG>
DG>if (Root.?Config.?User.?Age > 16)
DG>{
DG>   //bla-bla
DG>}
DG>


DG>или может даже лучше:

DG>
DG>if (Root?.Config?.User?.Age > 16)
DG>{
DG>   //bla-bla
DG>}
DG>



Первое всё-таки лучше.

DG>Особенно это нужно при описании правил бизнес логики, т.к. в бизнес-логики часто мы имеем на руках только частичную информацию о мире


То же с этим очень мучаюсь. Просто жуть!
Re: С# 3.0
От: FDSC Россия consp11.github.io блог
Дата: 16.09.05 06:30
Оценка: :)
Здравствуйте, AndrewVK.

Я знал чем это всё кончится!


Я боюсь пользоваться продуктами Microsoft — я начинаю просто и абсолютно непонимать их стратегию.
Re[2]: С# 3.0
От: stalcer Россия  
Дата: 16.09.05 06:53
Оценка:
Здравствуйте, DarkGray, Вы писали:

DG>т.е. хочеться иметь оператор вида '.?', который возвращает нуль, если левая часть имеет нулевое значение


Интересная идея.

DG>
DG>if (Root.?Config.?User.?Age > 16)
DG>{
DG>   //bla-bla
DG>}
DG>


Пусть Root == null. Ты предлагаешь, чтобы ((RootClass)null).?Config тоже вычислялось в null? А во что же должно вычисляться все выражение Root.?Config.?User.?Age. В 0 (ноль)? И тип у него естественно будет int?
Дык, возраст со знаением ноль и возраст с неизвестным значением — это ведь две разные вещи.
А если тип будет, например, строка? возвращать пустую строку? А если структура?

Сколько народу ругается на Oracle, где пустая строка и NULL — это одно и тоже!




ИМХО, нужно вводить специальные типы, по анаголии с NULL концепцией в SQL. Так чтобы переменная этого типа могла кроме определенного знаения хранить еще и признак наличия значения, т.е. попросту говоря могла бы не иметь значения. И соответственно вводить специальные операции с такими типами.

Я в своем DSL, основа которого была нагло стырена с C#, ввел такие типы. null оставил как есть в C#, а в дополнение к этому ввел константу undefined (типа <undefined>, как и null в C# имеет специальный тип <null>).

int  x = 0;  // Обыный int.
int% y = 0;  // Как я его назвал - undefinable int.

if (defined y) // Пройдет. Аналогия с SQL-ым IS NULL.
    ...;
    
y = undefined;
    
if (y == undefined) // Не пройдет. Так как undefined != undefined, как в SQL.
    ...;
    
x = (int)y; // Требуется явное приведение. В ран-тайм будет ошибка.

y = y + x; // Выполнится как y + (int%)x. Получится undefined.


Это для простых типов. Теперь про классы с полями и свойствами:

class A
{
    public B% b;
}

class B
{
    public int x;
}

A% a = new A();
a.b  = undefined;

int% y = a.b.x; // y будет undefined. Так как a.b - undefined.
                // Несмотря на то, что поле x имеет тип int,
                // операция ((B%)somevar).x имеет тип int%.
                // но только на чтение.

a.b.x = 7;      // В ран-тайм будет ошибка. На запись a.b.x
                // имеет тип int.


Также работают свойства и индексеры.

Дык вот о птичках. Вроде в C# уже ввели работу с SQL-like типами. Там вроде какой-то стандартный дженерик есть, не помню как он там называется. С помощью такого дженерика и перегрузки операторов конечно можно имитировать работу с примитивными SQL-like типами.
А вот с полями и свойствами так как я показал — фигушки...
http://www.lmdinnovative.com (LMD Design Pack)
Re[2]: С# 3.0
От: Кодёнок  
Дата: 16.09.05 06:56
Оценка:
Здравствуйте, DarkGray, Вы писали:

DG>До сих пор не хватает "красивой" работы с нулевыми значениями

DG>сейчас вместо:
DG>if (Root.Config.User.Age > 16)
DG>часто приходиться писать:
DG>int? age = null;
DG>var root = Root;
DG>if (root != null)
DG>{
DG> var config = root.Config;
DG> if (config != null)
DG> {
DG> var user = config.User;
DG> if (user != null)
DG> age = user.Age;
DG> }
DG>}
DG>if (age != null && age.Value > 10)

Минимум наверное должен быть такой:

if ( (Root == null || Root.Config == null || Root.Config.User == null ? default_value : Root.Config.User.Age) > 10 )
...


Если бы был мощный препроцессор, можно быть бы написать универсальный макрос, принимающий конструкцию `a.b.c.*.z`, проверяющий каждый член на null и возвращающий некое значение по умолчанию в таком случае. Но вот этого в C# что-то не предвидится.
Re[3]: С# 3.0
От: FDSC Россия consp11.github.io блог
Дата: 16.09.05 07:00
Оценка: :)
Здравствуйте, stalcer, Вы писали:

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


DG>>т.е. хочеться иметь оператор вида '.?', который возвращает нуль, если левая часть имеет нулевое значение


S>Интересная идея.


DG>>
DG>>if (Root.?Config.?User.?Age > 16)
DG>>{
DG>>   //bla-bla
DG>>}
DG>>


S>Пусть Root == null. Ты предлагаешь, чтобы ((RootClass)null).?Config тоже вычислялось в null? А во что же должно вычисляться все выражение Root.?Config.?User.?Age. В 0 (ноль)? И тип у него естественно будет int?

S>Дык, возраст со знаением ноль и возраст с неизвестным значением — это ведь две разные вещи.
S>А если тип будет, например, строка? возвращать пустую строку? А если структура?

S>Сколько народу ругается на Oracle, где пустая строка и NULL — это одно и тоже!


Я думаю, необязательно именно возвращать NULL. Можно, например, просто выходить без исключения из условного оператора, так как условие заранее не выполнено.
Re[4]: С# 3.0
От: stalcer Россия  
Дата: 16.09.05 07:07
Оценка:
Здравствуйте, FDSC, Вы писали:

DG>>>
DG>>>if (Root.?Config.?User.?Age > 16)
DG>>>{
DG>>>   //bla-bla
DG>>>}
DG>>>


FDS>Я думаю, необязательно именно возвращать NULL. Можно, например, просто выходить без исключения из условного оператора, так как условие заранее не выполнено.


Где не обязательно возвращать? Какой порядок выисления выражений то?

1) tmp1 = Root;
2) tmp2 = tmp1.?Config;
3) tmp3 = tmp2.?User;
4) tmp4 = tmp3.?Age;
5) tmp5 = tmp4 > 16;
6) if (tmp5)

Что должно быть на каждом шаге? Какого типа каждое из этих промежуточных выражений?

А если так:
int x = Root.?Config.?User.?Age;
http://www.lmdinnovative.com (LMD Design Pack)
Re[5]: С# 3.0
От: FDSC Россия consp11.github.io блог
Дата: 16.09.05 07:13
Оценка:
Здравствуйте, stalcer, Вы писали:

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


DG>>>>
DG>>>>if (Root.?Config.?User.?Age > 16)
DG>>>>{
DG>>>>   //bla-bla
DG>>>>}
DG>>>>


S>Какого типа каждое из этих промежуточных выражений?

CObject

S>Что должно быть на каждом шаге?


Компилятор должен обрабатывать примерно так:

Root.Config инициализированно? — нет — выйти из условного оператора

Root.?Config.?User инициализированно? — аналогично
Re[6]: С# 3.0
От: stalcer Россия  
Дата: 16.09.05 07:19
Оценка: :)
Здравствуйте, FDSC, Вы писали:

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


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


DG>>>>>
DG>>>>>if (Root.?Config.?User.?Age > 16)
DG>>>>>{
DG>>>>>   //bla-bla
DG>>>>>}
DG>>>>>


S>>Какого типа каждое из этих промежуточных выражений?

FDS>CObject

Ну-ну. А разве CObject имеет поле Config? А? Или может быть поле User. Или может быть CObject можно сравнивать с int (c 16)? Чушь!

FDS>Root.Config инициализированно? — нет — выйти из условного оператора


FDS>Root.?Config.?User инициализированно? — аналогично


if (!(Root.?Config.?User.?Age > 16))
    ...;
    
if ((Root.?Config.?User.?Age > 16) || someBoolVar)
    ...;
    
bool x = (Root.?Config.?User.?Age > 16);


Дык откуда ты говоришь надо сразу выходить?
http://www.lmdinnovative.com (LMD Design Pack)
Re[6]: С# 3.0
От: Кодёнок  
Дата: 16.09.05 07:23
Оценка:
Здравствуйте, FDSC, Вы писали:

FDS>Компилятор должен обрабатывать примерно так:

FDS>Root.Config инициализированно? — нет — выйти из условного оператора
FDS>Root.?Config.?User инициализированно? — аналогично

Людям явно не нравится механизм обработки исключений и они ощут альтернативы

P.S. Мне тоже не нравится.
Re[7]: С# 3.0
От: stalcer Россия  
Дата: 16.09.05 07:30
Оценка:
Здравствуйте, Кодёнок, Вы писали:

Кё>Людям явно не нравится механизм обработки исключений и они ощут альтернативы


А при чем здесь исключения. null есть только для ссылочных типов. А, например, возмем структуру Address. Пусть адрес может быть не задан по условию задачи. И что? Придется заводить еще и булевый признак? Не зря же в SQL сделали NULL. Да и не только в SQL.
http://www.lmdinnovative.com (LMD Design Pack)
Re[7]: С# 3.0
От: FDSC Россия consp11.github.io блог
Дата: 16.09.05 07:35
Оценка:
Здравствуйте, stalcer, Вы писали:

S>Ну-ну. А разве CObject имеет поле Config? А? Или может быть поле User. Или может быть CObject можно сравнивать с int (c 16)? Чушь!


FDS>>Root.Config инициализированно? — нет — выйти из условного оператора


FDS>>Root.?Config.?User инициализированно? — аналогично


S>
S>if (!(Root.?Config.?User.?Age > 16))
S>    ...;
    
S>if ((Root.?Config.?User.?Age > 16) || someBoolVar)
S>    ...;
    
S>bool x = (Root.?Config.?User.?Age > 16);
S>


S>Дык откуда ты говоришь надо сразу выходить?


Повторяю, из условного оператора "if"
Re[8]: С# 3.0
От: FDSC Россия consp11.github.io блог
Дата: 16.09.05 07:39
Оценка:
Здравствуйте, FDSC, Вы писали:

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


S>>Ну-ну. А разве CObject имеет поле Config? А? Или может быть поле User. Или может быть CObject можно сравнивать с int (c 16)? Чушь!


Я имею ввиду, что для компилятора проверяемое поле — указатель на базовый тип
Re[7]: С# 3.0
От: FDSC Россия consp11.github.io блог
Дата: 16.09.05 07:43
Оценка:
Здравствуйте, Кодёнок, Вы писали:


Кё>Людям явно не нравится механизм обработки исключений и они ощут альтернативы


Что ж я каждый условный оператор в try .. extept (cath) должен ставить?
Re[8]: С# 3.0
От: stalcer Россия  
Дата: 16.09.05 07:45
Оценка:
Здравствуйте, FDSC, Вы писали:

S>>Дык откуда ты говоришь надо сразу выходить?


FDS>Повторяю, из условного оператора "if"


Повторяю примеры:

if (!(Root.?Config.?User.?Age > 16))
    ...;
    
if ((Root.?Config.?User.?Age > 16) || someBoolVar)
    ...;
    
bool x = (Root.?Config.?User.?Age > 16);


Во первых, в первых двух if должен выполниться (при условии, что someBoolVar = true). Во вторых, в третьем примере вообще нет if. И?
http://www.lmdinnovative.com (LMD Design Pack)
Re[8]: С# 3.0
От: Кодёнок  
Дата: 16.09.05 07:49
Оценка: +1
Здравствуйте, FDSC, Вы писали:

FDS>Повторяю, из условного оператора "if"


А вообще интересная идея — считать условие невыполненным, если оно не может быть вычислено (а не тупо сравнивать числа).

Если нас это устраивает, мы просто пишем
if (a.b > 10)

Если надо наоборот — чтобы оно выполнилось в случае невычислимости, то пишем
if (!(a.b <= 10))

Проблема в том, что будут ситуации, когда некоторые случаи невычислиости должны обязательно выкидывать исключение. Т.е. если a.b === null — исключение, а если a.b.c === null — считать условие невыполненным. И еще не ко всякому условию можно записать обратное через !(...)
Re[9]: С# 3.0
От: FDSC Россия consp11.github.io блог
Дата: 16.09.05 07:49
Оценка:
Здравствуйте, stalcer, Вы писали:


S>
S>if (!(Root.?Config.?User.?Age > 16))
S>    ...;
    
S>if ((Root.?Config.?User.?Age > 16) || someBoolVar)
S>    ...;
    
S>bool x = (Root.?Config.?User.?Age > 16);
S>


S>Во первых, в первых двух if должен выполниться (при условии, что someBoolVar = true). Во вторых, в третьем примере вообще нет if. И?


Последние два примера не корректны для данной постановки задачи.
Re[9]: С# 3.0
От: stalcer Россия  
Дата: 16.09.05 07:55
Оценка:
Здравствуйте, FDSC, Вы писали:

FDS>Я имею ввиду, что для компилятора проверяемое поле — указатель на базовый тип


Ты ответь на мой вопрос. Какого типа, с точки зрения предполагаемой спецификации языка должно быть каждое из перечисленных мной выражений. И какое значение каждое из них должно вернуть. Особенно <...>.?Age.

С точки зрения логики. Ведь именно с этой точки зрения мы обсуждаем введение нового типа выражения ".?" в язык.

Его синтаксис можно обозначить так:

<primary> ".?" <field-name>

Где <primary> — это тоже выражение. Вот и объясни мне правила выисления этого выражения вне зависимости от контекста (наличия if, ect.). Объясни также как это объяснено для других выражений в спецификации.
http://www.lmdinnovative.com (LMD Design Pack)
Re[9]: С# 3.0
От: FDSC Россия consp11.github.io блог
Дата: 16.09.05 07:58
Оценка: +1
Здравствуйте, Кодёнок, Вы писали:

Кё>Проблема в том, что будут ситуации, когда некоторые случаи невычислиости должны обязательно выкидывать исключение. Т.е. если a.b === null — исключение, а если a.b.c === null — считать условие невыполненным. И еще не ко всякому условию можно записать обратное через !(...)



Тогда можно записать так a.b.?c вместо a.?b.?c. Если b == NULL — в первом случае будет поднято исключение
Re[10]: С# 3.0
От: stalcer Россия  
Дата: 16.09.05 08:00
Оценка:
Здравствуйте, FDSC, Вы писали:

S>>
S>>if (!(Root.?Config.?User.?Age > 16))
S>>    ...;
    
S>>if ((Root.?Config.?User.?Age > 16) || someBoolVar)
S>>    ...;
    
S>>bool x = (Root.?Config.?User.?Age > 16);
S>>


FDS>Последние два примера не корректны для данной постановки задачи.


Почему это, интересно знать?

Пучть Root = null, а someBoolVar = true.
Второй пример: должно получиться if (false || true), т.е. if должен выполниться.
Третий пример: x = false;

Все корректно. И вообще, любое выражение я могу применять в любом контексте. Из любых более мелких выражений я могу конструировать более сложные.
http://www.lmdinnovative.com (LMD Design Pack)
Re[11]: С# 3.0
От: FDSC Россия consp11.github.io блог
Дата: 16.09.05 08:05
Оценка:
Здравствуйте, stalcer, Вы писали:

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


S>>>
S>>>if (!(Root.?Config.?User.?Age > 16))
S>>>    ...;
    
S>>>if ((Root.?Config.?User.?Age > 16) || someBoolVar)
S>>>    ...;
    
S>>>bool x = (Root.?Config.?User.?Age > 16);
S>>>


FDS>>Последние два примера не корректны для данной постановки задачи.


S>Почему это, интересно знать?


Согласен. Всякий синтаксически правильный код — корректен.

S>Пучть Root = null, а someBoolVar = true.

S>Второй пример: должно получиться if (false || true), т.е. if должен выполниться.
S>Третий пример: x = false;

S>Все корректно. И вообще, любое выражение я могу применять в любом контексте. Из любых более мелких выражений я могу конструировать более сложные.


Кодёнок предложил считать условие не выполненным, если соотв. значение некорректно.
Тогда всё получается.
Re[10]: С# 3.0
От: FDSC Россия consp11.github.io блог
Дата: 16.09.05 08:09
Оценка:
Здравствуйте, stalcer, Вы писали:

S>Его синтаксис можно обозначить так:


S><primary> ".?" <field-name>


S>Где <primary> — это тоже выражение. Вот и объясни мне правила выисления этого выражения вне зависимости от контекста (наличия if, ect.). Объясни также как это объяснено для других выражений в спецификации.


В общем, примерно так:

<object1>.?<Object2> == if (Object1.Object != NULL) ... ; else return false;
Re[12]: С# 3.0
От: stalcer Россия  
Дата: 16.09.05 08:11
Оценка:
Здравствуйте, FDSC, Вы писали:

FDS>Кодёнок предложил считать условие не выполненным, если соотв. значение некорректно.

FDS>Тогда всё получается.

Неа. Вот это:
bool x = (Root.?Config.?User.?Age > 16);


Я перепишу так:

int  age = Root.?Config.?User.?Age;
bool x   = (age > 16);


Утверждаю, что это должно быть абсолютно эквивалентно первому варианту. Об этом даже спорить не буду.

Вопрос 1: правильно ли я объявил переменную age типа int. Или должен быть другой тип?
Вопрос 2: чему будет равно значение переменной age?
http://www.lmdinnovative.com (LMD Design Pack)
Re[11]: С# 3.0
От: stalcer Россия  
Дата: 16.09.05 08:17
Оценка:
Здравствуйте, FDSC, Вы писали:

FDS>В общем, примерно так:


FDS><object1>.?<Object2> == if (Object1.Object != NULL) ... ; else return false;


А вот и фигушки. Для начала расшифрую твое многоточие. Ты, наверное, имел ввиду следующее:

if (Object1.Object2 != NULL) return Object1.Object2; else return false;

А вот теперь подумай:

<EpressionType> retval;

if (Object1.Object2 != NULL) 
    retval = Object1.Object2; 
else 
    retval = false;
    
return retval;


Каким должен быть <EpressionType>? С одной стороны — типом поля Object2. С другой стороны по твоей логике — bool (так как ты ему false присваиваешь). Как я и говорил — чушь.
http://www.lmdinnovative.com (LMD Design Pack)
Re[13]: С# 3.0
От: FDSC Россия consp11.github.io блог
Дата: 16.09.05 08:18
Оценка:
Здравствуйте, stalcer, Вы писали:

S>Неа. Вот это:

S>
S>bool x = (Root.?Config.?User.?Age > 16);
S>


S>Я перепишу так:


S>
S>int  age = Root.?Config.?User.?Age;
S>bool x   = (age > 16);
S>


S>Утверждаю, что это должно быть абсолютно эквивалентно первому варианту. Об этом даже спорить не буду.

Согласен...

S>Вопрос 1: правильно ли я объявил переменную age типа int. Или должен быть другой тип?

S>Вопрос 2: чему будет равно значение переменной age?

Честно говоря, не знаю, как это правильно объявить. Но оператор .? должен возвращать булевский тип. Вообще-то ерудна получается.

Надо долго думать...
Re[12]: С# 3.0
От: FDSC Россия consp11.github.io блог
Дата: 16.09.05 08:22
Оценка:
Здравствуйте, stalcer, Вы писали:

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


FDS>>В общем, примерно так:


FDS>><object1>.?<Object2> == if (Object1.Object != NULL) ... ; else return false;


S>А вот и фигушки. Для начала расшифрую твое многоточие. Ты, наверное, имел ввиду следующее:


S>if (Object1.Object2 != NULL) return Object1.Object2; else return false;


S>А вот теперь подумай:


S>
S><EpressionType> retval;

S>if (Object1.Object2 != NULL) 
S>    retval = Object1.Object2; 
S>else 
S>    retval = false;
    
S>return retval;
S>


S>Каким должен быть <EpressionType>? С одной стороны — типом поля Object2. С другой стороны по твоей логике — bool (так как ты ему false присваиваешь). Как я и говорил — чушь.


Правильно.

Надо ввести тогда оператор .? ... .?... условие . Тогда оператор станет возвращать bool в обоих случаях. Только как это сделать?
Re[14]: С# 3.0
От: Кодёнок  
Дата: 16.09.05 08:30
Оценка:
Здравствуйте, FDSC, Вы писали:

FDS>Честно говоря, не знаю, как это правильно объявить. Но оператор .? должен возвращать булевский тип. Вообще-то ерудна получается.


FDS>Надо долго думать...


Нет, оператор не дожен возвращать никакой тип, иначе ничего не выйдет Именно это мне и показалось интересным — не простое вычисление выражения в операторе if по правилам языка, а какое-то более сложное поведение, в данном случае — считать само условие невыполненным в случае невозможности вычислить аргументы.

Т.е. этот код
if (Object1.?Object2.?Object3)
  DoSmth();


должен транслироваться в

if (Object1 != null && Object1.Object2 != null)
{
  if (Object1.Object2.Object3)
    DoSmth();
}


Т.е. .? не просто оператор, который ведет себя каким-то хитрым образом, а изменение поведения компилятора.

Проблема тут сразу очевидна — как отличить "провал" оператора .? от нормального выполнения? Что если провал одного из операторов должен приводить к невыполнению всего условия, а провал другого — к выполнению всего условия? Еще проблема — если этот оператор влияет на способ всего вычисления выражения в if, то могут быть какие-нибудь неочевидные проблемы.
Re[15]: С# 3.0
От: FDSC Россия consp11.github.io блог
Дата: 16.09.05 08:39
Оценка:
Здравствуйте, Кодёнок, Вы писали:


Кё>Т.е. .? не просто оператор, который ведет себя каким-то хитрым образом, а изменение поведения компилятора.


Кё>Проблема тут сразу очевидна — как отличить "провал" оператора .? от нормального выполнения? Что если провал одного из операторов должен приводить к невыполнению всего условия, а провал другого — к выполнению всего условия? Еще проблема — если этот оператор влияет на способ всего вычисления выражения в if, то могут быть какие-нибудь неочевидные проблемы.


Я собственно то же это хотел. Но возникает вопрос синтаксиса при использовании оператора .? вне оператора if.

Можно ввести разновидность оператора .? и .~?, которые будут всё-таки возвращать булевский тип для определённого условия, но работать только в команде с условием.

a.b = NULL;
a.?b = true
a.~?b = false
Re[15]: С# 3.0
От: stalcer Россия  
Дата: 16.09.05 08:43
Оценка: +1
Здравствуйте, Кодёнок, Вы писали:

Кё>...то могут быть какие-нибудь неочевидные проблемы.


Очевидная проблема, в том, то невозможно формально описать логику поведения такого оператора.
Возможно только если он выполняется обычным образом, и в нашем примере (с Age) возвращает 0 (ноль) типа int.

То есть пусть Object1.?Age выполняется так:
if (Object1 != null)
    return Object1.Age;
else
    return (AgeType)default_value;


Где, AgeType — тип поля Age, а default_value — значение, зависящее от AgeType. Для ссылочных типов default_value = null, для числовых — 0, для строки — "", для структур — ??? может структура забитая нулями.

Это, ИМХО, единственный нормальный способ описать поведение такого оператора. Только не очень красиво, Age может быть и так равен нулю.

Или же расширить синтаксис до такого, например: Object1.?Age{7}, что будет означать, то вместо default_value использовать 7.
http://www.lmdinnovative.com (LMD Design Pack)
Re[16]: С# 3.0
От: FDSC Россия consp11.github.io блог
Дата: 16.09.05 08:49
Оценка:
Здравствуйте, stalcer, Вы писали:

S>Здравствуйте, Кодёнок, Вы писали:


Кё>>...то могут быть какие-нибудь неочевидные проблемы.


S>Очевидная проблема, в том, то невозможно формально описать логику поведения такого оператора.

S>Возможно только если он выполняется обычным образом, и в нашем примере (с Age) возвращает 0 (ноль) типа int.

S>То есть пусть Object1.?Age выполняется так:

S>
S>if (Object1 != null)
S>    return Object1.Age;
S>else
S>    return (AgeType)default_value;
S>


S>Где, AgeType — тип поля Age, а default_value — значение, зависящее от AgeType. Для ссылочных типов default_value = null, для числовых — 0, для строки — "", для структур — ??? может структура забитая нулями.


S>Это, ИМХО, единственный нормальный способ описать поведение такого оператора. Только не очень красиво, Age может быть и так равен нулю.


S>Или же расширить синтаксис до такого, например: Object1.?Age{7}, что будет означать, то вместо default_value использовать 7.


Не пойдёт! К сожалению. Смысл в том, что оператор должен прекращать выполнение обработки условного выражения, а не возвращать значение по умолчанию. Как тогда справиться с последовательным вызовом a.?b.?c.? Хранить "нулевые" объекты-значения по умолчанию?
Re[17]: С# 3.0
От: stalcer Россия  
Дата: 16.09.05 08:59
Оценка:
Здравствуйте, FDSC, Вы писали:

FDS>Не пойдёт! К сожалению. Смысл в том, что оператор должен прекращать выполнение обработки условного выражения, а не возвращать значение по умолчанию. Как тогда справиться с последовательным вызовом a.?b.?c.? Хранить "нулевые" объекты-значения по умолчанию?


А чего не пройдет-то? С последовательным вызовом как раз все нормально. Например, a.?b.?c.?Age
Пусть поле 'b' будет равно null.

1) A tmp1 = a; // not null
2) B tmp2 = (tmp1 != null) ? tmp1.b : null; // a.b (== null)
3) C tmp3 = (tmp2 != null) ? tmp2.c : null; // null, так как tmp2 == null
4) int tmp4 = (tmp3 != null) ? tmp3.Age : 0; // 0, так как tmp3 == null

Результат будет 0 (ноль).
http://www.lmdinnovative.com (LMD Design Pack)
Re[18]: С# 3.0
От: FDSC Россия consp11.github.io блог
Дата: 16.09.05 09:03
Оценка:
Здравствуйте, stalcer, Вы писали:

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


FDS>>Не пойдёт! К сожалению. Смысл в том, что оператор должен прекращать выполнение обработки условного выражения, а не возвращать значение по умолчанию. Как тогда справиться с последовательным вызовом a.?b.?c.? Хранить "нулевые" объекты-значения по умолчанию?


S>А чего не пройдет-то? С последовательным вызовом как раз все нормально. Например, a.?b.?c.?Age

S>Пусть поле 'b' будет равно null.

S>1) A tmp1 = a; // not null

S>2) B tmp2 = (tmp1 != null) ? tmp1.b : null; // a.b (== null)
S>3) C tmp3 = (tmp2 != null) ? tmp2.c : null; // null, так как tmp2 == null
S>4) int tmp4 = (tmp3 != null) ? tmp3.Age : 0; // 0, так как tmp3 == null

S>Результат будет 0 (ноль).


Ага. Получится NULL > 16?
Re[5]: С# 3.0
От: WolfHound  
Дата: 16.09.05 09:05
Оценка:
Здравствуйте, stalcer, Вы писали:

S>Что должно быть на каждом шаге? Какого типа каждое из этих промежуточных выражений?


S>А если так:

S>
S>int x = Root.?Config.?User.?Age;
S>

В C#2 появились nullable типы.
Те в данном случае будет так
int? x = Root.?Config.?User.?Age;

и приводится это к такому коду
int? x;
if (Root != null && Root.Config != null && Root.Config.User != null)
    x = Root.Config.User.Age;
else
    x = null;


В C#2 такой код
int? a;
a = null;
Console.WriteLine(a > 1);
a = 1;
Console.WriteLine(a > 1);
a = 2;
Console.WriteLine(a > 1);

выводит
False
False
True

Те в случае если a == null то любые сравнения с числом возвращают false.
... << RSDN@Home 1.1.4 beta 6a rev. 436>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[4]: С# 3.0
От: Sinclair Россия https://github.com/evilguest/
Дата: 16.09.05 09:07
Оценка:
Здравствуйте, FDSC, Вы писали:

FDS>Я думаю, необязательно именно возвращать NULL. Можно, например, просто выходить без исключения из условного оператора, так как условие заранее не выполнено.

int age;
try {  age = Root.Config.User.Age;} 
catch (NullReferenceException)  {age=0;}
if (age > 16)
{
  bla-bla
|

Значительно короче. И не растет с удлиннением выражения.
... << RSDN@Home 1.1.4 stable rev. 510>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[19]: С# 3.0
От: stalcer Россия  
Дата: 16.09.05 09:07
Оценка:
Здравствуйте, FDSC, Вы писали:

S>>1) A tmp1 = a; // not null

S>>2) B tmp2 = (tmp1 != null) ? tmp1.b : null; // a.b (== null)
S>>3) C tmp3 = (tmp2 != null) ? tmp2.c : null; // null, так как tmp2 == null
S>>4) int tmp4 = (tmp3 != null) ? tmp3.Age : 0; // 0, так как tmp3 == null

S>>Результат будет 0 (ноль).


FDS>Ага. Получится NULL > 16?


Стоп. tmp4 имеет тип int, и значение не null, а 0.
http://www.lmdinnovative.com (LMD Design Pack)
Re[20]: С# 3.0
От: FDSC Россия consp11.github.io блог
Дата: 16.09.05 09:09
Оценка:
Здравствуйте, stalcer, Вы писали:

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


S>>>1) A tmp1 = a; // not null

S>>>2) B tmp2 = (tmp1 != null) ? tmp1.b : null; // a.b (== null)
S>>>3) C tmp3 = (tmp2 != null) ? tmp2.c : null; // null, так как tmp2 == null
S>>>4) int tmp4 = (tmp3 != null) ? tmp3.Age : 0; // 0, так как tmp3 == null

S>>>Результат будет 0 (ноль).


FDS>>Ага. Получится NULL > 16?


S>Стоп. tmp4 имеет тип int, и значение не null, а 0.


М-м. Видать я не совсем понял. Надо бы более строгое описание.

Если так — согласен. Очередь за Microsoft
Re[6]: С# 3.0
От: FDSC Россия consp11.github.io блог
Дата: 16.09.05 09:10
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>В C#2 появились nullable типы.


Спасибо. Это как раз то, что мы обсуждали.
Re[5]: С# 3.0
От: FDSC Россия consp11.github.io блог
Дата: 16.09.05 09:13
Оценка:
Здравствуйте, Sinclair, Вы писали:

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


FDS>>Я думаю, необязательно именно возвращать NULL. Можно, например, просто выходить без исключения из условного оператора, так как условие заранее не выполнено.

S>
S>int age;
S>try {  age = Root.Config.User.Age;} 
S>catch (NullReferenceException)  {age=0;}
S>if (age > 16)
S>{
S>  bla-bla
S>|
S>

S>Значительно короче. И не растет с удлиннением выражения.

А исполняется это значительно медленее и не очень читаемо (такое впечатление). Тут вопрос был ещё и в том, что возможно один из объектов не может быть равен NULL и это нужно обработать как ошибку.
Re[6]: С# 3.0
От: stalcer Россия  
Дата: 16.09.05 09:14
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>В C#2 появились nullable типы.

WH>Те в данном случае будет так
WH>
WH>int? x = Root.?Config.?User.?Age;
WH>


То есть оператор '.?' уже есть?

WH>Те в случае если a == null то любые сравнения с числом возвращают false.


Операции как в SQL? Наверное не только к сравнениям относится, на и к другим операциям (+, — и т.п.)

А спецификация есть в инете? Где почитать?
http://www.lmdinnovative.com (LMD Design Pack)
Re[7]: С# 3.0
От: WolfHound  
Дата: 16.09.05 09:47
Оценка:
Здравствуйте, stalcer, Вы писали:

S>То есть оператор '.?' уже есть?

Такого оператора нет. Есть int? те инт который может быть null.

WH>>Те в случае если a == null то любые сравнения с числом возвращают false.

S>Операции как в SQL? Наверное не только к сравнениям относится, на и к другим операциям (+, — и т.п.)
S>А спецификация есть в инете? Где почитать?
Ищи спецификацию C#2.
... << RSDN@Home 1.1.4 beta 6a rev. 436>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re: С# 3.0
От: Igor Trofimov  
Дата: 16.09.05 10:43
Оценка:
Вообще мне не очень понятно (и не очень нравится) это стремление добавить в шарп возможности (и спец-синтаксис)функционального программирования. Так ли оно надо именно в рамках шарпа, если есть F# и т.п? Мне кажется, что эта попытка собрать все в одну кучу-малу до добра не доведет — пропадает простота, лаконичность, концептуальная цельность.. Или это во мне говорит закоренелый консерватор, воспитанный на императивных языках?
Re[6]: С# 3.0
От: Sinclair Россия https://github.com/evilguest/
Дата: 16.09.05 10:43
Оценка:
Здравствуйте, FDSC, Вы писали:

FDS>А исполняется это значительно медленее

Ну, насчет "значительнее" — зависит только от вероятности того, что кто-то все-таки null. Если такая ситуация встречается слишком часто, то надо будет пересмотреть логику. Тем не менее, premature optimization is the root of all evil.
FDS>и не очень читаемо (такое впечатление).
Это ошибочное впечатление. Более короткий код читается всегда легче. Во-первых, здесь с первого взгляда виден весь путь доступа (Root.Config.User.Age) без необходимости продираться через цепочку присваиваний (именно за такой эффект всегда критиковали конструкцию with в паскале). Во-вторых, единство политики обработки отсутствия данных выражено ровно в одной строке — сразу видно, что где бы ни произошел NullReferenceException, мы примем дефолтный возраст за Null.
FDS> Тут вопрос был ещё и в том, что возможно один из объектов не может быть равен NULL и это нужно обработать как ошибку.
Простите, но в начальном коде этого не было. См. Re: С# 3.0
Автор: DarkGray
Дата: 15.09.05
. Проблема была ровно в том, что приходится писать паразитный код для проверок. Я привел корректное решение этой проблемы.
... << RSDN@Home 1.1.4 stable rev. 510>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re: С# 3.0
От: GlebZ Россия  
Дата: 16.09.05 11:09
Оценка: 5 (2) +1
Здравствуйте, AndrewVK, Вы писали:

Честно говоря, я пришел к выводу, что все нововведения построены ради прозрачного обслуживания DLinq, XLinq. Причем так, чтобы их интеграция небыла заметна для прикладника. Чтобы не было заметно, с чем он работает. Синтаксиса языка явно не хватало потому как для генерации и оптимизации предикатов нужно иметь AST. И оно должно быть в функциональном стиле(без лишнего состояния). Плюс генерация типов (чтобы прозрачно можно было запросы менять). Плюс расширение типов(чтобы добавлять поведение для типов к которому доступа нет, так как он создан тем-же DLinq. Ну таким образом, можно все и приплюсовать.

С уважением, Gleb.
Re[2]: С# 3.0
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 16.09.05 12:34
Оценка: 1 (1)
Здравствуйте, DarkGray, Вы писали:

DG>До сих пор не хватает "красивой" работы с нулевыми значениями


DG>сейчас вместо:

DG>
DG>if (Root.Config.User.Age > 16)
DG>{
DG>   //bla-bla
DG>}
DG>


DG>часто приходиться писать:


Можно воспользоваться паттерном Null Object, тогда проверок вобще делать нужно не будет.
... << RSDN@Home 1.2.0 alpha rev. 617>>
AVK Blog
Re[15]: С# 3.0
От: Andrei N.Sobchuck Украина www.smalltalk.ru
Дата: 16.09.05 13:46
Оценка: 2 (1)
Здравствуйте, Кодёнок, Вы писали:

Кё>Нет, оператор не дожен возвращать никакой тип, иначе ничего не выйдет Именно это мне и показалось интересным — не простое вычисление выражения в операторе if по правилам языка, а какое-то более сложное поведение, в данном случае — считать само условие невыполненным в случае невозможности вычислить аргументы.


Как работает nil в Objective-C:

nil возвращаемый из методов в Objective-C /.../ в ответ на посылаемое ему сообщение nil не бросает исключение, а попросту игнорирует это сообщение. То есть, nil из Objective-C ведёт себя как "черная дыра". Это пустота. Это ничто. При посылке к nil-у любого сообщения, всё что вы получите назад — это nil. Не будет никаких исключений, никаких возвращенных значений. Ничего.
/.../
поведение ``поедающее'' сообщения позволяет создавать более элегантный код!
/.../
Предположим, что мы хотим найти последний телефонный номер, который вы набрали со своего офисного телефона, и сохранить этот номер в переменной, скажем, 'последнийНомер'. Далее предположим, что мы хотим сохранить этот номер как строку и затем отобразить его в виджете (или же использовать этот номер позже). Если вы -- это 'человек' в последовательности сообщений приведённой далее, то достаточно ли этой последовательности для получения работоспособной программы?


    последнийНомер := человек офис телефон последнийИсходящийНомер какСтрока.
    виджет строковоеЗначение: последнийНомер.

Возможно.

Но что, если у человека нет офиса? Или в офисе нет телефона? Или что если это новый телефон и по нему еще никто не звонил? В любом из этих случаев, при использовании ``исключенческого'' nil-а будет выброшено исключение, которое приведёт к остановке программы, если только не будет создан соответствующий обработчик исключения.

А что с nil-ом ``поедающим'' сообщения? В этом случае 'последнийНомер' может в качестве значения принять nil, но всё будет работать и в этом случае. Даже передача nil-а как аргумента для метода #строковоеЗначение:1будет работать, потому что ``поедающий'' nil может нормально работать с виджетами. Совершенно не важно, что аргумент это nil. Всё будет работать без бросания исключений и без заметных с первого взгляда побочных эффектов (на этом подробнее остановимся позже).

Для сравнения, ниже приведён код для работы с ``исключенческим'' nil-ом:

    | врем |
  врем := человек офис.
  врем неПусто еслиИстина: [врем := врем телефон].
    врем неПусто еслиИстина: [врем := врем последнийИсходящийНомер].
    врем неПусто еслиИстина: [врем := врем какСтрока].
    виджет строковоеЗначение: последнийНомер.

... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Я ненавижу Hibernate
Автор: Andrei N.Sobchuck
Дата: 08.01.08
!
Re[3]: С# 3.0
От: VladD2 Российская Империя www.nemerle.org
Дата: 16.09.05 14:15
Оценка:
Здравствуйте, FDSC, Вы писали:

FDS>Первое всё-таки лучше.


DG>>Особенно это нужно при описании правил бизнес логики, т.к. в бизнес-логики часто мы имеем на руках только частичную информацию о мире


FDS>То же с этим очень мучаюсь. Просто жуть!


А слабо придумать хорошие значения по умолчанию? Ну, 0 для возраста...
... << RSDN@Home 1.2.0 alpha rev. 611>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: С# 3.0
От: VladD2 Российская Империя www.nemerle.org
Дата: 16.09.05 14:15
Оценка: 1 (1)
Здравствуйте, FDSC, Вы писали:

FDS>Компилятор должен обрабатывать примерно так:


FDS>Root.Config инициализированно? — нет — выйти из условного оператора


FDS>Root.?Config.?User инициализированно? — аналогично


Создайте для всех этих классов null-объектв которые будут возвращать дефолтную информацию и не мучайтесь. Компилятор тут не причем.
... << RSDN@Home 1.2.0 alpha rev. 611>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: С# 3.0
От: VladD2 Российская Империя www.nemerle.org
Дата: 16.09.05 14:15
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>В C#2 появились nullable типы.

WH>Те в данном случае будет так
WH>
WH>int? x = Root.?Config.?User.?Age;
WH>


Такой синтаксис не поддерживается. Откда ты это взял, я не знаю.
... << RSDN@Home 1.2.0 alpha rev. 611>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: С# 3.0
От: VladD2 Российская Империя www.nemerle.org
Дата: 16.09.05 14:15
Оценка: 7 (3)
Здравствуйте, DarkGray, Вы писали:

DG>До сих пор не хватает "красивой" работы с нулевыми значениями


DG>сейчас вместо:

DG>
DG>if (Root.Config.User.Age > 16)
DG>{
DG>   //bla-bla
DG>}
DG>


DG>часто приходиться писать:...


Для вашей проблемы сто лет назад был придуман паттерн NuulObject. То есть объект выполняющий роль того самого null. При этом он предоставлеяет некие значения которые считаются недействительными. Для ссылочных объектов это специальные синглтон-экземлпяры, для вэлью-типов предопределенные значения. Вот пример использования данного паттерна:
class A
{
    public A(int i) { I = i; }
    public int I;
    public static readonly A Default = new A(-1);
}

class B
{
    public B() { A = A.Default; }
    public B(A a) { A = a; }
    public A A;
    public static readonly B Default = new B();
}

class Program
{
    static void Main()
    {
        B b = new B();

        int i = b.A.I;
    }
}


При этом код классов увеличевается незначительно, а основной код выглядит полностью читабельным и незамусоренным.
... << RSDN@Home 1.2.0 alpha rev. 611>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: С# 3.0
От: VladD2 Российская Империя www.nemerle.org
Дата: 16.09.05 14:15
Оценка:
Здравствуйте, Igor Trofimov, Вы писали:

iT>Вообще мне не очень понятно (и не очень нравится) это стремление добавить в шарп возможности (и спец-синтаксис)функционального программирования. Так ли оно надо именно в рамках шарпа, если есть F# и т.п? Мне кажется, что эта попытка собрать все в одну кучу-малу до добра не доведет — пропадает простота, лаконичность, концептуальная цельность.. Или это во мне говорит закоренелый консерватор, воспитанный на императивных языках?


Функцональные возможности в Шарпе были изначально (делегатов уже достаточно). Просто их было очень неудобно использовать. Во втором шарпе их улучшели, но не самым лучшим образом. В третьем шарпе просто довели до ума идеи второго шарпа. Ничего нового в нем не введено. Просто более краткий синтаксис.

Что же необходимости фунционального стиля... С появлением дженериков делегаты стали самым удобным средством абстрагирования дженерик кода от подробностей конкретных типов. И чем проще можно будет работать с ними тем проще и читабельнее будет код.

К тому же функциональный подход позволяет производить более детальную декомпозицию кода. Так что лишним он не будет.

Ну, и главное, что функциональный стиль не навязывается обязательным. Те кто его не понимает могут пользоваться только его плодами. Не думаю, что это будет проблемой.
... << RSDN@Home 1.2.0 alpha rev. 611>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: С# 3.0
От: Andrei N.Sobchuck Украина www.smalltalk.ru
Дата: 16.09.05 14:24
Оценка: :)
Здравствуйте, VladD2, Вы писали:

VD>Функцональные возможности в Шарпе были изначально (делегатов уже достаточно). Просто их было очень неудобно использовать. Во втором шарпе их улучшели, но не самым лучшим образом. В третьем шарпе просто довели до ума идеи второго шарпа. Ничего нового в нем не введено. Просто более краткий синтаксис.


Врядли синтаксис тех лямб пойдёт в серию. Там же ни одной скобки нету. Ни круглой ни фигурной. Массы такого абстракционизма не поймут
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Я ненавижу Hibernate
Автор: Andrei N.Sobchuck
Дата: 08.01.08
!
Re[4]: С# 3.0
От: VladD2 Российская Империя www.nemerle.org
Дата: 16.09.05 14:40
Оценка:
ANS>Врядли синтаксис тех лямб пойдёт в серию. Там же ни одной скобки нету. Ни круглой ни фигурной. Массы такого абстракционизма не поймут

Наоботор пойдут на ура. К стати, скобки там можно приделать. Более того если у лямбды два и более параметра, то без них не обойтись:
(x, y) => x * y
(x)    => x * x

А учитывая, что нет проблем использовать и более расширенный синтаксис:
(int x, double y) => x * y
(int x) => { return x * x; }

и даже "старый" синтаксис:
delegate(int x, double y) {  return x * y; }
delegate(int x) { return x * x; }

народ поймет, что это просто такая сокращенная форма записи.
А когда он сравнит:
(x, y) => x * y

и
delegate(int x, double y) {  return x * y; }

то вопросы отпадут сами собой.
... << RSDN@Home 1.2.0 alpha rev. 611>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: С# 3.0
От: GlebZ Россия  
Дата: 16.09.05 14:45
Оценка:
Здравствуйте, VladD2, Вы писали:

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

По-моему, вся фигня крутится вокруг коллекций. Анонимные делегаты пользуются только в коллекциях. В реале, я ни разу не делал анонимный предикат за пределами коллекций(и не видел его использования). Это некоторый флаг Microsoft, чем удобнее пользовать коллекции, тем лучше С# . Очень сомневаюсь что подобный синтаксис выйдет за пределы этого. IMHO Функциональный стиль и объекты одновременно не очень хорошо живут. Объекты с их состоянием и строгой типизированностью — ограничивают функциональный стиль. И ввод неименованных типов, по моему, как козе баян, а может и еще хуже.
Причина вполне понятна. Microsoft делает язык для серверов приложений. И коллекции немаловажная часть DSL. Если еще при этом, прозрачно связать с персистентностью объектов, то такая реализация DSL будет весьма здоровская. Похоже это и есть цель C# 3.0. За пределами коллекций, => по моему не катит.

С уважением, Gleb.
Re[7]: С# 3.0
От: WolfHound  
Дата: 16.09.05 15:10
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Такой синтаксис не поддерживается. Откда ты это взял, я не знаю.

Я знаю.
Автор: WolfHound
Дата: 16.09.05

Просто я сделал предположение как это можно реализовать малой кровью.
... << RSDN@Home 1.1.4 beta 6a rev. 436>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[5]: С# 3.0
От: Andrei N.Sobchuck Украина www.smalltalk.ru
Дата: 16.09.05 16:30
Оценка:
Здравствуйте, VladD2, Вы писали:

ANS>>Врядли синтаксис тех лямб пойдёт в серию. Там же ни одной скобки нету. Ни круглой ни фигурной. Массы такого абстракционизма не поймут

VD>Наоботор пойдут на ура. К стати, скобки там можно приделать. Более того если у лямбды два и более параметра, то без них не обойтись:
VD>народ поймет, что это просто такая сокращенная форма записи.
VD>А когда он сравнит:

Занятно, что "длина" синтаксиса таки имеет значение

VD>
VD>(x, y) => x * y
VD>

VD>и
VD>
VD>delegate(int x, double y) {  return x * y; }
VD>

VD>то вопросы отпадут сами собой.

запись вверху неконсистентна, выбивается из общей массы. Я вроде как за краткость, но нужно же придерживаться некого стиля. Не нравится декларация типов (вот уж от тебя не ожидал ) — убери:
delegate(x, y) {  return x * y; }

в рамках С-шарп (именно в "рамках") понятнее чем
(x, y) => x * y
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Я ненавижу Hibernate
Автор: Andrei N.Sobchuck
Дата: 08.01.08
!
Re[4]: С# 3.0
От: VladD2 Российская Империя www.nemerle.org
Дата: 16.09.05 16:43
Оценка: 6 (1) +1
Здравствуйте, GlebZ, Вы писали:

GZ>По-моему, вся фигня крутится вокруг коллекций. Анонимные делегаты пользуются только в коллекциях. В реале, я ни разу не делал анонимный предикат за пределами коллекций(и не видел его использования).


Дык коллекции, точнее списки — это самый часто используемый механизм в программах. И как раз функциональный стиль (ФС) при обработке списков показывает себя очень и очень хоношо.

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

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

GZ> Это некоторый флаг Microsoft, чем удобнее пользовать коллекции, тем лучше С# .


Дык это к любому языку относится. Если ты не в курсе, есть такой язык Лисп, так он вообще изначально предназначался для обработки списков. А на поверку оказался одним из самых интересных языков программирования.

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


Это полноейшее заблцждение. "Сменная функция" позволяет делать код настраиваемым. Конечно можно обходиться интерфейсами или абстрактными классами, но это же ведь неудобно.

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

GZ>Причина вполне понятна. Microsoft делает язык для серверов приложений.


Microsoft слава богу делает язык общего назначения (GP-язык). А коллекции они и в Африке коллекции. Я еще не видел ЯП который мог бы обходиться без список в том или ином виде.

GZ>И коллекции немаловажная часть DSL.


А где коллекции маловажная вещь? Да и как раз для создания DSL C# подходит не лучшим образом. Будем надеяться, что только пока.

GZ>Если еще при этом, прозрачно связать с персистентностью объектов, то такая реализация DSL будет весьма здоровская. Похоже это и есть цель C# 3.0. За пределами коллекций, => по моему не катит.


Ты просто привык к одному взгляду на мир. А мир более разнообразен.
Как я уже говорил функция является отличной абстракцией. Ну, давай попробую объяснить это на простеньком примере. Предположим у нас есть некоторое вычисление содержащее повторяющиеся части (первое вхождение выделено жирным):
int x = 2;
int y = 3;
int z = 3;

int res1 = (x + 123 + z * z) * y + (x + 321 + z * z) * y 
  + (x + 111 + z * z) * y + (x + 222 + z * z) * y;

Некрасиво, правда?
Что мы может сделать чтобы устранить дублирование? Правильно ввести функцию. Но это приведет к куче лишних действий и к тому, что код станет более большим и не станет сильно понятнее:
int res2 = f1(x, y, z, 123) + f1(x, y, z, 321) 
  + f1(x, y, z, 111) + f1(x, y, z, 222);
...

private static int f1(int x, int y, int z, int a)
{
    return (x + a + z * z) * y;
}

По сути мы избавились от дублирования слишком дорогой ценой. А вот если мы имеем возможность оперировать функциями более вольготно и если этот синтаксис будет более компактным, то мы можем получить куда более приятный результат. Вот как тоже самое можно записать с применением лямбды:
Func<int, int> f2 = a => (x + a + z * z) * y;
var res3 = f2(123) + f2(321) + f2(111) + f2(222);

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

Так что функциональный стиль при условии грамотного реализации в языке – это очень хорошо (по крайней мере для тех кто способен думать).

А проблемой которая будет препятствовать его применению скорее станет не его непонятность, а ухудшение производительности. Дело в том, что в истинно функциональном языке выражения обрабатываются еще во время компиляции. А в C# 2.0/3.0 будет производиться довольно неэффективный косвенный вызов. В данном примере будет 4 вызова. Плюс ко всему прочему будет порожден временный объект (чтобы лямбда могла получить доступ к локальным переменным x, y, z они будет превращены в поля этого объекта).
И это еще легкий случай. А ведь вложенность при функциональной декомпозиции может быть многократной. И это уже может существенно повлиять на производительность.
Я уверен, что все эти проблемы мог бы устранить оптимизирующий компилятор или JIT, но пока что этого никто не делает. А стало быть производительность столь красивых решений будет меньшей нежели аналогичных лобовых.
... << RSDN@Home 1.2.0 alpha rev. 611>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: С# 3.0
От: VladD2 Российская Империя www.nemerle.org
Дата: 16.09.05 17:22
Оценка:
Здравствуйте, Andrei N.Sobchuck, Вы писали:

ANS>Занятно, что "длина" синтаксиса таки имеет значение


Дык ведь линий мусор еще никому не помогал.

ANS>запись вверху неконсистентна, выбивается из общей массы.


Чё?

ANS> Я вроде как за краткость, но нужно же придерживаться некого стиля. Не нравится декларация типов (вот уж от тебя не ожидал


Почему не ожидал? Это наверно ты путашь мое отношение к статической типизации и наличие явной декларации типов.
В приведенных примерах типизация остается строгой и статической. В ней применяется вывод типов. Он столь же логичен для человека как и для компилятора. А стало быть это те подробности которые в большинстве случаев можно опусить.

ANS>) — убери:

ANS>
ANS>delegate(x, y) {  return x * y; }
ANS>

ANS>в рамках С-шарп (именно в "рамках") понятнее чем
ANS>
ANS>(x, y) => x * y
ANS>


Дык мне еще не нравится, что в анонимном методе я не могу использовать выражения (expressions) и вынужден использовать предложения (statments). Все это приводит к довольно сильному удленнению кода, а стало быт и к его замыливанию неважными фрмгментами.
Например, сравни следующие две строки:
list.Sort(delegate(KeyValuePair<string, int> x, KeyValuePair<string, int> y { return x.Value.CompareTo(y.Value); });
и:
list.Sort((x, y) => x.Value.CompareTo(y.Value));

по-моему, очевидно, что при всей непривычности синтаксиса второй вариант намного более понятен и приятен.

ЗЫ

Уверен, что после выхода C# 3.0 синтаксис delegate(...){ ... } быстро будет забыт.
... << RSDN@Home 1.2.0 alpha rev. 611>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: С# 3.0
От: GlebZ Россия  
Дата: 16.09.05 18:47
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Так что итераторы и функции высшего порядка добавленные в коллекции во втором фрэймворке — это очень вреное решение.

В этом как раз я не сомневаюсь.

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

Или попросту ненужно. Дизайн вполне описывается паттернами. И оно самодостаточно(если конечно голова на плечах есть). Иногда там встречается observer, но это все равно к функц. языкам отношения не имеет.

VD>Если ты не в курсе, есть такой язык Лисп,

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

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


VD>Это полноейшее заблцждение. "Сменная функция" позволяет делать код настраиваемым. Конечно можно обходиться интерфейсами или абстрактными классами, но это же ведь неудобно.

Почему?
А теперь представим такую вещь. Мы делаем какой-то здоровую функциональную функциональность. Но тут у нас произошло изменение. Нам нужно использовать класс с состоянием на чтение — запись. Оптимизация графа, летит к ... маме. След., возможности чистого функционального подхода, здесь становятся практически недоступны. Либо мы юзаем лямбда, либо императив.(я в чем-то ошибаюсь?)

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

Если методы объектов выполняют ограничения ФП.

VD>А где коллекции маловажная вещь? Да и как раз для создания DSL C# подходит не лучшим образом. Будем надеяться, что только пока.

Лисповцы наступают!!! Метапрограммирование? Честно говоря, все средства есть. Хочешь генери новые классы. Хочешь используй неименованные типы(приводя их к именнованным). Чего тебе не хватает? Да, это не Лисп. Кое что, в построении отдельного языка, будет труднее сделать. Но в рамках C# описать язык вполне можно. Особенно, если это будет C# синтаксис. Он тебе недостаточен?

VD>Ты просто привык к одному взгляду на мир. А мир более разнообразен.

Грешен.
VD>
VD>Func<int, int> f2 = a => (x + a + z * z) * y;
VD>var res3 = f2(123) + f2(321) + f2(111) + f2(222);
VD>

VD>Согласись это значительно лучше читается и занимает куда меньше места. Ведь функция уложилась в одну строку, да еще и ее применение стало намного компактнее.
Чудно, только это слишком простой пример. Это применение возможной только в области видимости данной процедуры. А если решение побольше, то это выливается в обычные методы.

VD>А проблемой которая будет препятствовать его применению скорее станет не его непонятность, а ухудшение производительности. Дело в том, что в истинно функциональном языке выражения обрабатываются еще во время компиляции. А в C# 2.0/3.0 будет производиться довольно неэффективный косвенный вызов. В данном примере будет 4 вызова. Плюс ко всему прочему будет порожден временный объект (чтобы лямбда могла получить доступ к локальным переменным x, y, z они будет превращены в поля этого объекта).

Именно. Не в бровь, а в глаз. delegate — это объект. Притом объект с состоянием. Ты знаешь как его можно сделать без состояния? Реформировать процедуру чтобы сохранять состояние в параметрах? Тогда получается беспредел с рекурсией(если эта шняга работает только в рамках процедуры, а то еще больше интересного).
VD>И это еще легкий случай. А ведь вложенность при функциональной декомпозиции может быть многократной. И это уже может существенно повлиять на производительность.
Absolutly right. Тело функциональной программы — это граф. И его надо оптимизировать.
Что будет если написать так:
Func<int, int> f2 = a => (f2(a) + 1);
var t=f2;


VD>Я уверен, что все эти проблемы мог бы устранить оптимизирующий компилятор или JIT, но пока что этого никто не делает. А стало быть производительность столь красивых решений будет меньшей нежели аналогичных лобовых.

Мне интересен вопрос, как они это сделают?

С уважением, Gleb.
Re[3]: С# 3.0
От: DarkGray Россия http://blog.metatech.ru/post/ogni-razrabotki.aspx
Дата: 16.09.05 20:06
Оценка:
Кё>
Кё>if ( (Root == null || Root.Config == null || Root.Config.User == null ? default_value : Root.Config.User.Age) > 10 )
Кё>...
Кё>


Этот код совсем неэквивалентен примеру, особенно в многопоточном приложении, или в приложении с side-эффектами.
Re[6]: С# 3.0
От: DarkGray Россия http://blog.metatech.ru/post/ogni-razrabotki.aspx
Дата: 16.09.05 20:11
Оценка:
S>>А если так:
S>>
S>>int x = Root.?Config.?User.?Age;
S>>

WH>В C#2 появились nullable типы.
WH>Те в данном случае будет так

Да, результирующий тип должен быть или тем же самым, для ссылочных,
или Nullable<Type> для value-type-ов.

ps
но еще раз повторяю, что данный код совсем не равносилен исходному примеру, и может выдавать некорректный результат для многопоточного приложения или для кода с side-эффектами.

WH>
WH>int? x = Root.?Config.?User.?Age;
WH>

WH>и приводится это к такому коду
WH>
WH>int? x;
WH>if (Root != null && Root.Config != null && Root.Config.User != null)
WH>    x = Root.Config.User.Age;
WH>else
WH>    x = null;
WH>



генерится код должен такой, как из исходного примера.
Re[3]: С# 3.0
От: DarkGray Россия http://blog.metatech.ru/post/ogni-razrabotki.aspx
Дата: 16.09.05 20:26
Оценка:
VD>Для вашей проблемы сто лет назад был придуман паттерн NuulObject. То есть объект выполняющий роль того самого null. При этом он предоставлеяет некие значения которые считаются недействительными. Для ссылочных объектов это специальные синглтон-экземлпяры, для вэлью-типов предопределенные значения. Вот пример использования данного паттерна:


NullObject — совсем не тоже самое, что null, т.к. возникают проблемы с преобразованием типов, со сравнениями и т.д.

например:
interface IA{}
interface IB:IA{}
class NullableIA:IA
{
  public static readonly IA Null = new NullableIA();
}
class NullableIB:IB
{
  public static readonly IB Null = new NullableIB();
}

class Program
{
  static void Main()
  {
     IA a = NullableIA.Null;
     CheckForNull(a); //print null
     
     IB b = NullableIB.Null;
     CheckForNull(b); //print null
 
     a = b;
     CheckForNull(a); //print not null     

     
  }
  public static void CheckForNull(IA a)
  {
     if (a == NullableIA.Null)
       Console.WriteLine("null");
     else
       Console.WriteLine("not null");  
  }
  public static void CheckForNull(IB b)
  {
     if (b == NullableIB.Null)
       Console.WriteLine("null");
     else
       Console.WriteLine("not null");  
  }
}


как должны быть написаны методы CheckForNull, чтобы возвращать правильный результат?
ради чего программист должен писать Null-заглушки?
если использовать Null-объекты, то какие операции использовать вместо is, as и (Type)? ведь Null-объект, формально декларируя поддержку интерфейса, на самом деле же нифига не поддерживает.
и т.д.
Re[2]: С# 3.0
От: DarkGray Россия http://blog.metatech.ru/post/ogni-razrabotki.aspx
Дата: 16.09.05 20:50
Оценка:
iT>Extensions с generic'ами не живут, что в общем, понятно, но обидно:

Extensions с полями работает? или только с методами?

т.е. можно ли через Extension добавить поле?
Re[2]: С# 3.0
От: DarkGray Россия http://blog.metatech.ru/post/ogni-razrabotki.aspx
Дата: 16.09.05 21:10
Оценка:
оператор .? в применении к полям на get выглядит более менее логично
логику использования уже правильно описал wolfhound.
но код должен генериться более страшный, чем у него в примере, чтобы избежать проблем, связанных с повторным доступом к полям.

но также есть еще вопрос, можно ли применять оператор .? к set-полям/свойствам, и к функциям и процедурам.

адекватен ли код:

1.
a.?Value = 5;


2.
a.?Eval(5);


3.
int? v = a.?Execute();


имхо, адекватен, т.к. в случае вызова функции, мы по аналогии с полем на get просто возвращаем null,
а в случае — set-а или процедуры просто не выполняется правая часть.

Резюме:

1. get

код вида
<res> = <primary> ".?" <field-name>


имеет тип результата:
typeof(<primary>.<field-name>) — для ссылочных типов
и
Nullable<typeof<primary>.<field-name> — для value-типов

и код преобразуется в
var q = <primary>;
if (q != null)
  <res> = q.<field-name>;
else
  <res> = null;


2. set
<primary>.?<field-name> = value;

преобразуется в
var q = <primary>;
if (q != null)
  q = value;

значение value не вычисляется, если .? возвращает null.


3. вызов процедуры (void метода)
код вида
<primary>.?<method-name>(<arg-1>, <arg-2>)


преобразуется в
var q = <primary>;
if (q != null)
  q.<method-name>(<arg-1>, <arg-2>);

выражения arg-1 и arg-2 не вычисляются, если <primary> == null


4. вызов функции (метода, возвращающего значение):
<res> = <primary> ".?" ?<method-name>(<arg-1>, <arg-2>)

тип результата такой же как и в случае get

генерируемый код
var q = <primary>;
if (q != null)
  <res> = q.<method-name>(<arg-1>, <arg-2>);
else
  <res> = null;

<arg-1>, <arg-2> также не вычисляются, если <primary> — null.
Re[3]: С# 3.0
От: GarryIV  
Дата: 16.09.05 21:39
Оценка: +2
Здравствуйте, FDSC, Вы писали:

DG>>Особенно это нужно при описании правил бизнес логики, т.к. в бизнес-логики часто мы имеем на руках только частичную информацию о мире


FDS>То же с этим очень мучаюсь. Просто жуть!


Может быть пока не вышел C# 4.0 патерн Special Case (Null Object) поможет?
WBR, Igor Evgrafov
Re[4]: С# 3.0
От: VladD2 Российская Империя www.nemerle.org
Дата: 16.09.05 22:41
Оценка:
Здравствуйте, DarkGray, Вы писали:

DG>как должны быть написаны методы CheckForNull, чтобы возвращать правильный результат?


Идея паттерна NullObject заключается в том, чтобы вообще исключить подобные проверки. Для тебя null вообще не существует. Если уж нужно проверять на реальность объекта, то просто сравнивашь с тем самым Null-объектом.

DG>ради чего программист должен писать Null-заглушки?


Ради того, чтобы не трахаться с провекрами и не получать случайные вылеты. Логика приложения при этом строется так, чтобы все проверки приводили к какому-то поведению принятому по умолчанию и корректному с точки зрения приложения.

DG>если использовать Null-объекты, то какие операции использовать вместо is, as и (Type)?


А причем тут is и as? Систему типов они не отменяют. Они устранят необходимость постоянно проверять все ссылки на нул.

Тебя, кстати, не угнетает, что в дотнете принят паттерн в соотвествии с которым свойства и методы возвращающие коллекции и массив всегда должны возвращать пустой массив, а не null?

DG> ведь Null-объект, формально декларируя поддержку интерфейса, на самом деле же нифига не поддерживает.


Null-объект поддерживает такой же интферйс как и другие обхекты того же класса. Просто он используется вместо null. Не придумывай лишнего.
... << RSDN@Home 1.2.0 alpha rev. 611>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: С# 3.0
От: VladD2 Российская Империя www.nemerle.org
Дата: 16.09.05 22:41
Оценка:
Здравствуйте, GlebZ, Вы писали:

GZ>я в чем-то ошибаюсь?


Да, но чтобы это понять нужно просто попрограммировать с использованием новых возможностей, а потом попробовать жить без них.

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

GZ>Если методы объектов выполняют ограничения ФП.

Какие еще ограничения? Ты о чем?

GZ>Лисповцы наступают!!!


Лисп только один из примеров. С тем же успхом можно привести и ОКамл, и даже С++.

GZ> Метапрограммирование? Честно говоря, все средства есть.


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

GZ> Хочешь генери новые классы. Хочешь используй неименованные типы(приводя их к именнованным). Чего тебе не хватает?


Удобства.

GZ> Да, это не Лисп. Кое что, в построении отдельного языка, будет труднее сделать. Но в рамках C# описать язык вполне можно. Особенно, если это будет C# синтаксис. Он тебе недостаточен?


Я не смог уловить смысла этого абзаца.

VD>>Ты просто привык к одному взгляду на мир. А мир более разнообразен.

GZ>Грешен.

Вот в этом и проблема. Я тоже долго жил в этом мире, но понял, что другой мир имеет свои приемущества. Но и этот новый мир не идеален. А вот когда оба мира доступны в рамках одного языка, то жить становится удобно и приятно.

GZ>Чудно, только это слишком простой пример.


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

GZ> Это применение возможной только в области видимости данной процедуры. А если решение побольше, то это выливается в обычные методы.


Нет, будет проще. Будет кое-как написанная гора кода вообще без декомпозиции. Средств то подходящих нет ведь.

GZ>Именно. Не в бровь, а в глаз. delegate — это объект.


Ну, заявление что делегат — это объект слишком натянуто. Для компилятора это всего лишь ссылка на функцию — примити.

GZ> Притом объект с состоянием.


Что? У самого делегата состояния нет. Это всго лишь указатеь. А в языке вообще ссылка на метод (безтелесная).

GZ> Ты знаешь как его можно сделать без состояния?


У него нет состояния. Состояние может быть у ассоциированного объекта, но это не одно и то же.

GZ> Реформировать процедуру чтобы сохранять состояние в параметрах? Тогда получается беспредел с рекурсией(если эта шняга работает только в рамках процедуры, а то еще больше интересного).


Есть куча работ по комбинаторной логике и по преобразованию функций. Математически доказоно, что функции можно гибко переписывать во время компиляции. Многие ФЯ делают это без проблем и достигают очень нехилой производительности.

Так что производительность упирается в качество реализации компиляторов (как языков, так и джита). И рано или поздно компиляторы дотнета научатся оптимизировать функцональный код.

GZ>Absolutly right. Тело функциональной программы — это граф. И его надо оптимизировать.


Это, извини, чушь. Функциональные программы — это программы. Их моно представить как угодно. Есть стековые машины. Есть основанные на свертке графов, но они тоже по сути используют стэк. Ну, а что до компилируемых ФЯ, то в большинстве случае код после преобразований превращается в машинный (или IL). Так что никаких пробем тут нет.

Еще раз повторюсь. Есть куча научных работ и работающие компиляторы. Возми те же SML.NET и F#. Они показывают очень высокую производительность и полностью компилируются в MSIL. Вот только если компилятор C# преобразует код в MSIL практически 1 в 1, то функциональные компиляторы перед этоим выполняют преобразование АСТ таким образом, чтобы обеспечить масимальную эффективность. Что-то оптимизируется. Какие-то методы сливаются и плучаются новые (невидимые). Где-то все переписывается настолько, что уже вообще нельзя говорить о похожести на исходную программу.

GZ>Что будет если написать так:

GZ>
GZ>Func<int, int> f2 = a => (f2(a) + 1);
GZ>var t=f2;
GZ>


Для шарпа это неверная программа. Но она переписывается так:
Func<int, int> f2 = null;
f2 = a => (f2(a) + 1);
var t = f2;

и будет здесь банальный рекурсивный вызов. Ну, и так как код написан бездумно, то будет переполнение стека в виду вечной рекурсии. Линивых вычислений в Шарпе ведь нет.

А вот на Хаскеле подобная программа порождала бы список чисел. И это был бы совершенно корректной программой.

VD>>Я уверен, что все эти проблемы мог бы устранить оптимизирующий компилятор или JIT, но пока что этого никто не делает. А стало быть производительность столь красивых решений будет меньшей нежели аналогичных лобовых.

GZ>Мне интересен вопрос, как они это сделают?

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

Где их найти можно узнать спросив в форуме Декларативное программирование. Ну, или попытать счастье через гугль "code rewriting" "functional language".
... << RSDN@Home 1.2.0 alpha rev. 611>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: С# 3.0
От: VladD2 Российская Империя www.nemerle.org
Дата: 16.09.05 22:41
Оценка:
Здравствуйте, DarkGray, Вы писали:


DG>Extensions с полями работает? или только с методами?


DG>т.е. можно ли через Extension добавить поле?


А подумть? Как ты добавишь поле? Ты же не можешь изменять сам объект. Это только синтаксический сахар.

ЗЫ

Пока вообще можно добавлять только методы. Как я понимаю вопрос о свойствах и событиях обсуждается.
... << RSDN@Home 1.2.0 alpha rev. 611>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: С# 3.0
От: DarkGray Россия http://blog.metatech.ru/post/ogni-razrabotki.aspx
Дата: 17.09.05 07:02
Оценка:
DG>>Extensions с полями работает? или только с методами?

DG>>т.е. можно ли через Extension добавить поле?


VD>А подумть? Как ты добавишь поле? Ты же не можешь изменять сам объект. Это только синтаксический сахар.


А самому подумать?

конечно, же я имел ввиду свойства.
Re[5]: С# 3.0
От: DarkGray Россия http://blog.metatech.ru/post/ogni-razrabotki.aspx
Дата: 17.09.05 07:17
Оценка:
VD> Идея паттерна NullObject заключается в том, чтобы вообще исключить подобные проверки. Для тебя null вообще не существует. Если уж нужно проверять на реальность объекта, то просто сравнивашь с тем самым Null-объектом.

ню-ню, посмотрю я как, ты в большом проекте на каждый чих сможешь написать корректный Null-object.

Взять тот же пример с возврастом:

Как должен выглядеть Null-объект, чтобы корректно работали оба варианта:
if (user.Age > 21)
{
  //bla-bla
}
if (user.Age < 16)
{
  //bla-bla
}


Во-вторых:
как написать Null-объект, если исходный интерфейс не подразумевал null-возвраст?
interface IUser
{
  int Age {get;}
}

class NullUser:
  IUser
{
  public int Age {get {return xxx;}}
}

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


VD>Тебя, кстати, не угнетает, что в дотнете принят паттерн в соотвествии с которым свойства и методы возвращающие коллекции и массив всегда должны возвращать пустой массив, а не null?


Вообще-то, в бизнес-логике null и пустой массив — это не одно и тоже

null — это "я не знаю, какие есть элементы у этого объекта"
пустой массив — это "я знаю, что элементов у объекта нет".


ps
и, вообще, авторитетом подавил, а не на один из моих вопросов, так адекватного ответа и не дал.
Re[5]: С# 3.0
От: Алексей.  
Дата: 17.09.05 07:24
Оценка:
Здравствуйте, stalcer, Вы писали:

S>1) tmp1 = Root;

S>2) tmp2 = tmp1.?Config;
S>3) tmp3 = tmp2.?User;
S>4) tmp4 = tmp3.?Age;
S>5) tmp5 = tmp4 > 16;
S>6) if (tmp5)

S>Что должно быть на каждом шаге? Какого типа каждое из этих промежуточных выражений?


S>
S>int x = Root.?Config.?User.?Age;
S>


Тип на каждом промежуточном шаге может быть любым. Но эти типы должны неявно приводиться к типу указанному слева от последовательности
Root.?Config.?User.?Age
Специально для if-выражений можно предусмотреть дополнительно преобразование T? -> bool.
Re[5]: С# 3.0
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 17.09.05 07:29
Оценка:
Здравствуйте, DarkGray, Вы писали:

DG>конечно, же я имел ввиду свойства.


Читай мое сообщение или спецификацию, там про это упоминается.
... << RSDN@Home 1.2.0 alpha rev. 615 on Windows XP 5.1.2600.131072>>
AVK Blog
Re[7]: С# 3.0
От: Andrei N.Sobchuck Украина www.smalltalk.ru
Дата: 17.09.05 09:27
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Почему не ожидал? Это наверно ты путашь мое отношение к статической типизации и наличие явной декларации типов.


А есть ли жизнь без интелисенса?

VD>ЗЫ


VD>Уверен, что после выхода C# 3.0 синтаксис delegate(...){ ... } быстро будет забыт.


Я пока подозреваю, что в C# нового синтаксиса не будет. Проще новый язык разработать без старого багажа. Типа Z#, а C# объявить устаревшим Это как раз вписывается в популярную в нынешней индустрии схему "раз в пять-сем лет — новый язык".
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Я ненавижу Hibernate
Автор: Andrei N.Sobchuck
Дата: 08.01.08
!
Re[4]: С# 3.0
От: Igor Trofimov  
Дата: 17.09.05 11:12
Оценка:
VD>Пока вообще можно добавлять только методы. Как я понимаю вопрос о свойствах и событиях обсуждается.

Непонятно, как они с синтаксисом будут решать. Для методов получилось удачно, лишних ключевых свойств не потребовалось.. А для свойств тех же?

События не очень понятно как можно расширять — только если за счет других событий целевого класса. Оно в реальности-то пригодится?

А вот свойства и операторы — это действительно было бы полезно..

По мне, так лучше бы ввели ключевое слово и приписывали бы его к самому классу, а то как сейчас — сам класс получается вообще не при чем...
Re[5]: С# 3.0
От: DarkGray Россия http://blog.metatech.ru/post/ogni-razrabotki.aspx
Дата: 17.09.05 11:40
Оценка: +1
iT>По мне, так лучше бы ввели ключевое слово и приписывали бы его к самому классу, а то как сейчас — сам класс получается вообще не при чем...

к классу-то как раз и неинтересно приписывать...

т.к. хочется добавлять внешние методы и к готовым классам (библиотечным, чужим и т.д.).
Re[6]: С# 3.0
От: Igor Trofimov  
Дата: 17.09.05 12:42
Оценка:
DG>к классу-то как раз и неинтересно приписывать...
DG>т.к. хочется добавлять внешние методы и к готовым классам (библиотечным, чужим и т.д.).

Не, ты не понял. Я имею в виду что-то наподобие следующего:

public class extension StringExtr : string
{
     // Модификатор доступа вообще говоря для расширений не нужен

     bool IsEmpty  // Это расширение свойством. 
     {
        get { return this != null || Length == 0; }
     }

     int ToInt32(int defaultValue) // Это расширение методом
     {...} 
}


Т.е. во-первых явно сгруппировать члены, расширяющие конкретный целевой класс (сейчас их можно смешать в один static класс Util и все.)

Во-вторых, Перенести "новый" синтаксис в определение самого класса-расширителя, а не метода.
"Условное" наследование от string означает, что this имеет тип string (хотя может быть null для reference-типов), а дополнительное ключевое слово extension подразумевает, что экземпляры StringExtr создавать нельзя (как static), и что нужно применять этот класс как набор расширений для string.
Re[7]: С# 3.0
От: DarkGray Россия http://blog.metatech.ru/post/ogni-razrabotki.aspx
Дата: 17.09.05 13:11
Оценка:
iT>Во-вторых, Перенести "новый" синтаксис в определение самого класса-расширителя, а не метода.
iT>"Условное" наследование от string означает, что this имеет тип string (хотя может быть null для reference-типов), а дополнительное ключевое слово extension подразумевает, что экземпляры StringExtr создавать нельзя (как static), и что нужно применять этот класс как набор расширений для string.

но тогда придется бороться с объявлением полей внутри такого класса, создания экземпляра такого класса и т.д.
Re[5]: С# 3.0
От: VladD2 Российская Империя www.nemerle.org
Дата: 17.09.05 16:46
Оценка:
Здравствуйте, DarkGray, Вы писали:

DG>А самому подумать?


О том, что ты незнашь значений слов? Не, я не телепат.
На будущее, "поле" — это переменная-член класса.

DG>конечно, же я имел ввиду свойства.


Про свойства я тебе уже сказал.
... << RSDN@Home 1.2.0 alpha rev. 611>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: С# 3.0
От: VladD2 Российская Империя www.nemerle.org
Дата: 17.09.05 16:46
Оценка:
Здравствуйте, Igor Trofimov, Вы писали:

iT>Непонятно, как они с синтаксисом будут решать. Для методов получилось удачно, лишних ключевых свойств не потребовалось.. А для свойств тех же?


Вариантов много. Или тот же this куда-нибудь всунуть. Или атрибутом указать.

iT>События не очень понятно как можно расширять — только если за счет других событий целевого класса. Оно в реальности-то пригодится?


Вот народ и думат надо ли...

iT>А вот свойства и операторы — это действительно было бы полезно..


С операторами проблема. Они нужны внутри дженерик-алгоритмов которые компилирвются в мсил. А расширения это чисто синтаксический механизм. Так что смысла в них будет не очень много. Вернее может и будет. Но уж больно будет не полноценное решение.

iT>По мне, так лучше бы ввели ключевое слово и приписывали бы его к самому классу, а то как сейчас — сам класс получается вообще не при чем...


А он и не причем. Расширение может возидействовать сразу на несколько классов. Даже на интерфейсы.
... << RSDN@Home 1.2.0 alpha rev. 611>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: С# 3.0
От: VladD2 Российская Империя www.nemerle.org
Дата: 17.09.05 16:46
Оценка:
Здравствуйте, DarkGray, Вы писали:

DG>ню-ню, посмотрю я как, ты в большом проекте на каждый чих сможешь написать корректный Null-object.


Все грамотные программися сто лет как пользуются этим паттерном. Так что приобщайся.

DG>Взять тот же пример с возврастом:


DG>Как должен выглядеть Null-объект, чтобы корректно работали оба варианта:

DG>
DG>if (user.Age > 21)
DG>{
DG>  //bla-bla
DG>}
DG>if (user.Age < 16)
DG>{
DG>  //bla-bla
DG>}
DG>


Будет у тебя нал-объект попадать во второй диапазон. Что страшного?

DG>Во-вторых:

DG>как написать Null-объект, если исходный интерфейс не подразумевал null-возвраст?

Есть такая штука — проектирование. Очень полезная вещь.

DG>Вообще-то, в бизнес-логике null и пустой массив — это не одно и тоже


Ты видимо читашь что-то свое. Попробуй еще раз и не думай в этот момент о постороннем.

DG>ps

DG>и, вообще, авторитетом подавил, а не на один из моих вопросов, так адекватного ответа и не дал.

Никто тебя ничем не довил. Просто ты воспринимашь данный паттерн в штыки и намеренно боришся с ним. А если нет желания принимать что-то нове, то никто тебя не убидит.

Попробуй на практике. Потом поделишся результатами.
Как и любой паттерн этот не безупречен и имеет свои недостатки. Под них нужно подстараиваться. Бывает что паттерн не применим или неудобен. Что же поделашь?

Я стараюсь вообще избегать ситуаций когда null являтся шатной ситуацией. Это разко упрощает код. Те же нал-объекты нужны тольк там где возможно отсуствие объекта. А во многих случаях это просто не нужно. В том же конфиге объект просто обязан присуствовать. Зачем там null?
... << RSDN@Home 1.2.0 alpha rev. 611>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[8]: С# 3.0
От: VladD2 Российская Империя www.nemerle.org
Дата: 17.09.05 16:46
Оценка:
Здравствуйте, Andrei N.Sobchuck, Вы писали:

ANS>А есть ли жизнь без интелисенса?


А кто тебе сказал, что его не будет? Вывод типов ведь есть? А занчит есть и типы. А раз они есть, то будет и ителисенс. Пока что его нет и это сильно напрягает. Но всему свое время.

ANS>Я пока подозреваю, что в C# нового синтаксиса не будет.


Да он уже есть. И я не вижу чтобы кто-то хотел от него отказаться.

ANS> Проще новый язык разработать без старого багажа.


Не, ну, нужно все же более трезво смотреть на реальность. Что проще? Он уже есть!

ANS> Типа Z#, а C# объявить устаревшим Это как раз вписывается в популярную в нынешней индустрии схему "раз в пять-сем лет — новый язык".


Дык есть C# 1.х, есть C# 2.х, и будет C# 3.х. Это три разных языка имеющие обратную совместимость сверху вниз. При этом ты можешь писать на C# 1.х используя компилятор и среду от 3.х. Что еще нужно? Тебя же никто не заставляет использовать неудобные или непонятные по твоему мнению констркции?

Я думаю, синтаксис лямбд уже не изменится. Хорошо бы чтобы анонимные типы стали полноценными tuple-ами (т.е. типами которые можно сравнивать при совпадении структуры). Так же хотелось бы, чтобы компилятор научился делать преобразования лямбд во время компиляции. Еще было бы здорово если деревья выражения можно было бы в рантайме и компайлтайме преобразовывать в код (после модификации). Все это дало бы неслыханную гибкость при впролне простом синтаксисе и позволило бы стать C#-у безусловным лидером среди языков общего назначения.
... << RSDN@Home 1.2.0 alpha rev. 611>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[8]: С# 3.0
От: Igor Trofimov  
Дата: 17.09.05 17:39
Оценка:
DG>но тогда придется бороться с объявлением полей внутри такого класса, создания экземпляра такого класса и т.д.

Это как раз для разработчиков языка и не сложно. Самое сложное — это а) проработать семантику — какая она должны быть, чтобы не было каких-нибудь нежелательных побочных эффектов и б) придумать синтаксис, такой, чтобы сохранить совместимость и не слишком усложнить все.
Re[7]: С# 3.0
От: DarkGray Россия http://blog.metatech.ru/post/ogni-razrabotki.aspx
Дата: 17.09.05 18:28
Оценка:
VD> Будет у тебя нал-объект попадать во второй диапазон. Что страшного?

страшно то, что результат должен был быть не такой.

если это было бизнес-правило, например, для интернет-магазина:
Если возвраст < 10, то показать рекламу детских игрушек.

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

И это ты называешь не страшно?

VD>Попробуй на практике. Потом поделишся результатами.


Пробовал. Очень громоздко и неудобно.
Кол-во всего кода возврастает на четверть.
Сопровождение усложняется раза в полтора, т.к. при изменении основного объекта, надо также менять и Null-ипостаси.

Речь идет о том, что Null-паттерн в C# реализовывать неудобно, в SmallTalk-е удобно, а в C# — неудобно.

Поэтому и нужен специальный синтаксический сахар для работы с нулевыми значениями.
Re[9]: С# 3.0
От: Andrei N.Sobchuck Украина www.smalltalk.ru
Дата: 17.09.05 20:01
Оценка: +2 :))
Здравствуйте, VladD2, Вы писали:

VD>Дык есть C# 1.х, есть C# 2.х, и будет C# 3.х. Это три разных языка имеющие обратную совместимость сверху вниз. При этом ты можешь писать на C# 1.х используя компилятор и среду от 3.х. Что еще нужно? Тебя же никто не заставляет использовать неудобные или непонятные по твоему мнению констркции?


Да мне то, как раз, всё равно. А бедному Васе Пупкину *всё* нужно будет выучить. Ибо на собеседовании могут спросить...
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Я ненавижу Hibernate
Автор: Andrei N.Sobchuck
Дата: 08.01.08
!
Re[7]: С# 3.0
От: Igor Trofimov  
Дата: 18.09.05 12:30
Оценка:
Кстати, это бы еще позволило расширять статические члены класса.
Например, "засунуть" в DateTime статическое свойство TimeOfDinner Или расширить какой-то enum более дружественным, типизированным методом Parse.

Вообще позволило бы чуть-чуть "дописывать" стандартную библиотеку под нужды системы. Сахар, конечно, но очень сладкий и в целом безопасный.
Re[7]: С# 3.0
От: GlebZ Россия  
Дата: 18.09.05 13:33
Оценка:
Здравствуйте, VladD2, Вы писали:

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

GZ>>Если методы объектов выполняют ограничения ФП.
VD>Какие еще ограничения? Ты о чем?
Пока оставлю эту тему. Только ламеры читают help. Нескольких часов мутузанья клавиатуры и компилятора, не дали результата. А сейчас заглянул в спецификацию:

Note
The PDC 2005 Technology Preview compiler does not support lambda expressions with a statement block body. In cases where a statement block body is needed, the C# 2.0 anonymous method syntax must be used.

Так что, пока беру слова назад.

GZ>> Хочешь генери новые классы. Хочешь используй неименованные типы(приводя их к именнованным). Чего тебе не хватает?

VD>Удобства.
R# тебя спасет?

GZ>> Да, это не Лисп. Кое что, в построении отдельного языка, будет труднее сделать. Но в рамках C# описать язык вполне можно. Особенно, если это будет C# синтаксис. Он тебе недостаточен?

VD>Я не смог уловить смысла этого абзаца.
DSL — слишком абстрактное понятие. Не хотелось бы затевать флейм (который, к тому-же, уже был здесь не раз).

VD>>>Ты просто привык к одному взгляду на мир. А мир более разнообразен.

GZ>>Грешен.
VD>Да, но чтобы это понять нужно просто попрограммировать с использованием новых возможностей, а потом попробовать жить без них.
VD>Вот в этом и проблема. Я тоже долго жил в этом мире, но понял, что другой мир имеет свои приемущества. Но и этот новый мир не идеален. А вот когда оба мира доступны в рамках одного языка, то жить становится удобно и приятно.
Напоминает слова проповедника.
Я жил в темном мире, занимался сексом, курил, пил, дизассемблировал PowerBuilder и писал классы. Но однажды во сне ко мне пришел Haskell Curry и сказал — лямбда есть комбинаторика, и я прозрел. Я бросил старый темный мир погрязший в грехе. Теперь я живу в светлом мире, отшельником в келье среди лесной чащи, ем один горох, и пишу на Лисп. Вот оно счастье нирваны.


GZ>>Именно. Не в бровь, а в глаз. delegate — это объект.

VD>Ну, заявление что делегат — это объект слишком натянуто. Для компилятора это всего лишь ссылка на функцию — примити.
GZ>> Притом объект с состоянием.
VD>Что? У самого делегата состояния нет. Это всго лишь указатеь. А в языке вообще ссылка на метод (безтелесная).
GZ>> Ты знаешь как его можно сделать без состояния?
VD>У него нет состояния. Состояние может быть у ассоциированного объекта, но это не одно и то же.
Имеется ввиду именно анонимный делегат. А у него есть состояние в виде локальных переменных. А следовательно, это нужно решать, старая реализация в виде анонимных делегатов мне, кажется, не подойдет.

GZ>> Реформировать процедуру чтобы сохранять состояние в параметрах? Тогда получается беспредел с рекурсией(если эта шняга работает только в рамках процедуры, а то еще больше интересного).

VD>Есть куча работ по комбинаторной логике и по преобразованию функций. Математически доказоно, что функции можно гибко переписывать во время компиляции. Многие ФЯ делают это без проблем и достигают очень нехилой производительности.
VD>Так что производительность упирается в качество реализации компиляторов (как языков, так и джита). И рано или поздно компиляторы дотнета научатся оптимизировать функцональный код.
Ага. Правда при условии, если фукнции можно представить как лямбда-термы. Иначе возможности оптимизации существенно сужаются. А у нас тут в statement block body может твориться все что угодно.


GZ>>Absolutly right. Тело функциональной программы — это граф. И его надо оптимизировать.

VD>Это, извини, чушь. Функциональные программы — это программы. Их моно представить как угодно. Есть стековые машины. Есть основанные на свертке графов, но они тоже по сути используют стэк. Ну, а что до компилируемых ФЯ, то в большинстве случае код после преобразований превращается в машинный (или IL). Так что никаких пробем тут нет.
Хорошо, скажу по другому. Хотелось бы оптимизировать.

VD>и будет здесь банальный рекурсивный вызов. Ну, и так как код написан бездумно, то будет переполнение стека в виду вечной рекурсии. Линивых вычислений в Шарпе ведь нет.

Поскольку нет оптимизации как таковой, то и ленивых вычислений(в самом высоком смысле этого слова) нет. IMHO А вот то что рекурсия так долбануто сделана — это плохо. Я сразу что-то прогнал про это, потому и спросил. Испугался что ее вообще нет.

GZ>>Мне интересен вопрос, как они это сделают?

VD>Ести тебе серьезно интересен этот вопрос, то советую обратиться к научным работам по этому поводу.
Не-а. Я тоже послать могу. Мне нужна обзорная статья по оптимизации в функциональных языках. Чтобы прочел, и сразу просветленный. Сразу бы бросил пить и начал бы жрать горох. (а то мои знания ограничены "примерным" понимание graph rewrite ).

С уважением, Gleb.
Re[8]: С# 3.0
От: VladD2 Российская Империя www.nemerle.org
Дата: 18.09.05 21:34
Оценка: :)
Здравствуйте, DarkGray, Вы писали:

VD>> Будет у тебя нал-объект попадать во второй диапазон. Что страшного?


DG>страшно то, что результат должен был быть не такой.


Проектируй так чтобы должен был бы быть такой.
... << RSDN@Home 1.2.0 alpha rev. 611>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[10]: С# 3.0
От: VladD2 Российская Империя www.nemerle.org
Дата: 18.09.05 21:34
Оценка:
Здравствуйте, Andrei N.Sobchuck, Вы писали:

ANS>Да мне то, как раз, всё равно. А бедному Васе Пупкину *всё* нужно будет выучить. Ибо на собеседовании могут спросить...


От лишних знаний еще никто не погибал. А то что ламеры будут отсеиваться — это хорошо.
... << RSDN@Home 1.2.0 alpha rev. 611>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[8]: С# 3.0
От: VladD2 Российская Империя www.nemerle.org
Дата: 18.09.05 21:34
Оценка:
Здравствуйте, GlebZ, Вы писали:

GZ>R# тебя спасет?


R# это исследование. К тому же тесная интеграция с языком.

GZ>Напоминает слова проповедника.



GZ>Я жил в темном мире, занимался сексом, курил, пил, дизассемблировал PowerBuilder и писал классы. Но однажды во сне ко мне пришел Haskell Curry и сказал — лямбда есть комбинаторика, и я прозрел. Я бросил старый темный мир погрязший в грехе. Теперь я живу в светлом мире, отшельником в келье среди лесной чащи, ем один горох, и пишу на Лисп. Вот оно счастье нирваны.

GZ>

Не не так. Теперь у меня есть два мира, так что я занимаюсь сексом, курю, пью и т.п. но еще и колюсь.


GZ>Имеется ввиду именно анонимный делегат.


Метод, наверно.

GZ> А у него есть состояние в виде локальных переменных. А следовательно, это нужно решать, старая реализация в виде анонимных делегатов мне, кажется, не подойдет.


Состояние есть у любого метода. Так что ничго нового.

GZ>Ага. Правда при условии, если фукнции можно представить как лямбда-термы. Иначе возможности оптимизации существенно сужаются. А у нас тут в statement block body может твориться все что угодно.


Компилятор приципиально оперирует AST. Так что никаких проблем у него нет. Деревья выражений — это и есть AST. Так что все пучком.

GZ>Хорошо, скажу по другому. Хотелось бы оптимизировать.


Со временем будут и оптимизаторы. Про Феникс слышал? Вот в нем будут еще те возможности по оптимизации. Да и на уровне ЯП можно все что нужно сделать.

VD>>и будет здесь банальный рекурсивный вызов. Ну, и так как код написан бездумно, то будет переполнение стека в виду вечной рекурсии. Линивых вычислений в Шарпе ведь нет.

GZ>Поскольку нет оптимизации как таковой, то и ленивых вычислений(в самом высоком смысле этого слова) нет. IMHO

Это не связанные вещи. Линиые же вычисления легко достигаются за счет использования итераторов.
List<int> list = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int i = 0;
var lazyList =
                from elem in list
                select ++i;

Console.WriteLine("i = " + i);

foreach (int x in lazyList)
     Console.WriteLine("x = " + x + " i = " + i);

Console.WriteLine();

foreach (int x in lazyList)
{
    if (x > 15)
        break;
    Console.WriteLine("x = " + x + " i = " + i);
}

Console.WriteLine();

foreach (int x in lazyList)
     Console.WriteLine("x = " + x + " i = " + i);

Результат:
i = 0
x = 1 i = 1
x = 2 i = 2
x = 3 i = 3
x = 4 i = 4
x = 5 i = 5
x = 6 i = 6
x = 7 i = 7
x = 8 i = 8
x = 9 i = 9
x = 10 i = 10

x = 11 i = 11
x = 12 i = 12
x = 13 i = 13
x = 14 i = 14
x = 15 i = 15

x = 17 i = 17
x = 18 i = 18
x = 19 i = 19
x = 20 i = 20
x = 21 i = 21
x = 22 i = 22
x = 23 i = 23
x = 24 i = 24
x = 25 i = 25
x = 26 i = 26


GZ>>>Мне интересен вопрос, как они это сделают?

VD>>Ести тебе серьезно интересен этот вопрос, то советую обратиться к научным работам по этому поводу.
GZ>Не-а. Я тоже послать могу. Мне нужна обзорная статья по оптимизации в функциональных языках. Чтобы прочел, и сразу просветленный. Сразу бы бросил пить и начал бы жрать горох. (а то мои знания ограничены "примерным" понимание graph rewrite ).

Я закладок не делал. Если тебе в лом задать вопрос самому, то могу для тебя это сделать.
... << RSDN@Home 1.2.0 alpha rev. 611>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[8]: С# 3.0
От: VladD2 Российская Империя www.nemerle.org
Дата: 18.09.05 21:34
Оценка:
Здравствуйте, Igor Trofimov, Вы писали:

iT>Кстати, это бы еще позволило расширять статические члены класса.

iT>Например, "засунуть" в DateTime статическое свойство TimeOfDinner Или расширить какой-то enum более дружественным, типизированным методом Parse.

А чем хуже так:
static class EnumEx
{
    public static T Parse<T>(string str)
    {
        return (T)Enum.Parse(typeof(T), str, true);
    }
}
... << RSDN@Home 1.2.0 alpha rev. 611>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[11]: С# 3.0
От: Cyberax Марс  
Дата: 19.09.05 06:34
Оценка: 9 (1) :))) :)))
VladD2 wrote:

> ANS>Да мне то, как раз, всё равно. А бедному Васе Пупкину *всё* нужно

> будет выучить. Ибо на собеседовании могут спросить...
> От лишних знаний еще никто не погибал. А то что ламеры будут
> отсеиваться — это хорошо.

Неужели вы стали фанатом С++???!!!!

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 2.0 beta
Sapienti sat!
Re[7]: С# 3.0
От: stalcer Россия  
Дата: 19.09.05 06:38
Оценка:
Здравствуйте, DarkGray, Вы писали:

DG>Да, результирующий тип должен быть или тем же самым, для ссылочных,

DG>или Nullable<Type> для value-type-ов.

Точно, точно!

DG>но еще раз повторяю, что данный код совсем не равносилен исходному примеру, и может выдавать некорректный результат для многопоточного приложения


Это почему?

DG>или для кода с side-эффектами.


Ну, операторы ||, && ведут себя аналогино.
http://www.lmdinnovative.com (LMD Design Pack)
Re[8]: С# 3.0
От: DarkGray Россия http://blog.metatech.ru/post/ogni-razrabotki.aspx
Дата: 19.09.05 07:27
Оценка:
DG>>но еще раз повторяю, что данный код совсем не равносилен исходному примеру, и может выдавать некорректный результат для многопоточного приложения
DG>>или для кода с side-эффектами.

S>Это почему?



Потому что при такой записи вызовы свойств происходят несколько раз, поэтому при первом вызове может быть не null, а при втором вызове уже null, такое возможно если мы работаем с многопоточным приложением (и какой-то другой поток сбросил свойство), или с кодом, который имеет side-эффекты (и меняет значение свойства во время вызова)

допустим у нас есть свойство Name с side-эффектом (которое, то устанавливает свойство, то его сбрасывает) в классе User
public string Name
{
   get
   {
      if (_Name == null)
         _Name = "Вася";
      else
         _Name = null;
      return _Name;
   }
}
string _Name;


тогда при вызове вот такого кода мы будет падать по NullException-у с вероятностью 50%:
if (user != null && user.Name != null && user.Name.Length > 10)


поэтому код
if (user.?Name.?Length > 10)

должен преобразовываться в (чтобы исключить повторные вызовы)
int? length = null;
if (user != null)
{
  string name = user.Name;
  if (name != null)
    length = name.Length;
}
if (length > 10)
Re[8]: С# 3.0
От: Sinclair Россия https://github.com/evilguest/
Дата: 19.09.05 08:52
Оценка:
Здравствуйте, stalcer, Вы писали:
S>А при чем здесь исключения. null есть только для ссылочных типов. А, например, возмем структуру Address. Пусть адрес может быть не задан по условию задачи. И что?
Nullable<Address>. И все.
Оператор .? работает только на ссылочных типах и на value типах реализующих INullable. Попытка применить его к Address вызовет compile-time error.
... << RSDN@Home 1.1.4 stable rev. 510>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[9]: С# 3.0
От: stalcer Россия  
Дата: 19.09.05 09:02
Оценка:
Здравствуйте, DarkGray, Вы писали:

DG>поэтому код

DG>
DG>if (user.?Name.?Length > 10)
DG>

DG>должен преобразовываться в (чтобы исключить повторные вызовы)
DG>
DG>int? length = null;
DG>if (user != null)
DG>{
DG>  string name = user.Name;
DG>  if (name != null)
DG>    length = name.Length;
DG>}
DG>if (length > 10)
DG>


Да, конечно. Так же примерно работают индексеры:

foo[bar.getIndex()] += 7;


getIndex() будет вызван один раз, хотя для индексера будут вызваны и get и set.
http://www.lmdinnovative.com (LMD Design Pack)
Re[9]: С# 3.0
От: stalcer Россия  
Дата: 19.09.05 09:02
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Nullable<Address>. И все.

S>Оператор .? работает только на ссылочных типах и на value типах реализующих INullable. Попытка применить его к Address вызовет compile-time error.

Дык, я как раз это и пытался еловеку объяснить .
http://www.lmdinnovative.com (LMD Design Pack)
Re[12]: С# 3.0
От: VladD2 Российская Империя www.nemerle.org
Дата: 19.09.05 11:21
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Неужели вы стали фанатом С++???!!!!


Я уже пережил эту стадию... лет 5 назад.
... << RSDN@Home 1.2.0 alpha rev. 611>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[13]: С# 3.0
От: alexeiz  
Дата: 20.09.05 02:34
Оценка:
Здравствуйте, VladD2, Вы писали:

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


C>>Неужели вы стали фанатом С++???!!!!


VD>Я уже пережил эту стадию... лет 5 назад.


Известная история. Тот, кто недавно отрубал головы драконам, сейчас сам им стал.
Re[14]: С# 3.0
От: VladD2 Российская Империя www.nemerle.org
Дата: 20.09.05 13:09
Оценка: :)
Здравствуйте, alexeiz, Вы писали:

A>Известная история. Тот, кто недавно отрубал головы драконам, сейчас сам им стал.


Не, я стал слоником.
... << RSDN@Home 1.2.0 alpha rev. 611>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: Офтоп
От: McSeem2 США http://www.antigrain.com
Дата: 20.09.05 23:40
Оценка: 1 (1) +1 :))


Счасливое число в оценках! Мои поздравления!
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re[9]: С# 3.0
От: WolfHound  
Дата: 23.09.05 07:21
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Я думаю, синтаксис лямбд уже не изменится. Хорошо бы чтобы анонимные типы стали полноценными tuple-ами (т.е. типами которые можно сравнивать при совпадении структуры).

Tuple возможны на рантайме .NET2
Что то типа такого
using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication1
{
    class RefTuple<T, U>
    {
        public T First;
        public U Second;

        public override string ToString()
        {
            return "{" + First.ToString() + ";" + Second.ToString() + "}";
        }

        public override bool Equals(object obj)
        {
            RefTuple<T, U> that = obj as RefTuple<T, U>;
            if (that == null)
                return false;
            return Equals(this, that);
        }

        public override int GetHashCode()
        {
            return First.GetHashCode() ^ Second.GetHashCode();
        }

        private static bool Equals(RefTuple<T, U> l, RefTuple<T, U> r)
        {
            return l.First.Equals(r.First) && l.Second.Equals(r.Second);
        }

        public static bool operator ==(RefTuple<T, U> l, RefTuple<T, U> r)
        {
            return Equals(l, r);
        }

        public static bool operator !=(RefTuple<T, U> l, RefTuple<T, U> r)
        {
            return !Equals(l, r);
        }
    }

    struct ValueTuple<T, U>
    {
        public T First;
        public U Second;

        public override int GetHashCode()
        {
            return First.GetHashCode() ^ Second.GetHashCode();
        }

        public override string ToString()
        {
            return First.ToString() + ";" + Second.ToString();
        }
    }

    class Program
    {
        static RefTuple<int, ValueTuple<float, ValueTuple<float, string>>> Test()
        {
            RefTuple<int, ValueTuple<float, ValueTuple<float, string>>> t = new RefTuple<int, ValueTuple<float, ValueTuple<float, string>>>();
            t.First = 1;
            t.Second.First = 1.1f;
            t.Second.Second.First = 123;
            t.Second.Second.Second = "asdf";
            return t;
        }

        static void Main()
        {
            RefTuple<int, ValueTuple<float, ValueTuple<float, string>>> t1 = Test();
            RefTuple<int, ValueTuple<float, ValueTuple<float, string>>> t2 = Test();
//            t1.Second.First = 1;
            Console.WriteLine(t1 == t2);
            Console.WriteLine(t1);
            Console.WriteLine(t2);
        }
    }
}

Осталось прикрутить синтаксический сахар както так:
    class Program
    {
        static {int, float, float, string} Test()
        {
            return {1, 1.1f, 123f, "asdf"};
        }

        static void Main()
        {
            {int, float, float, string} t1 = Test();
            {int, float x, float, string} t2 = Test();
//            x = 1;
            Console.WriteLine(t1 == t2);
            Console.WriteLine(t1);
            Console.WriteLine(t2);
        }
    }
... << RSDN@Home 1.1.4 beta 6a rev. 436>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[10]: С# 3.0
От: VladD2 Российская Империя www.nemerle.org
Дата: 24.09.05 02:27
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Осталось прикрутить синтаксический сахар както так:

WH>
WH>    class Program
WH>    {
WH>        static {int, float, float, string} Test()
WH>        {
WH>            return {1, 1.1f, 123f, "asdf"};
WH>        }

WH>        static void Main()
WH>        {
WH>            {int, float, float, string} t1 = Test();
WH>            {int, float x, float, string} t2 = Test();
WH>//            x = 1;
WH>            Console.WriteLine(t1 == t2);
WH>            Console.WriteLine(t1);
WH>            Console.WriteLine(t2);
WH>        }
WH>    }
WH>


Во-во. Осталось начать и кончить.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[9]: С# 3.0
От: Igor Trofimov  
Дата: 25.09.05 17:31
Оценка:
VD>
VD>    public static T Parse<T>(this string str)
VD>


Да, тоже вариент...
Re[8]: С# 3.0
От: Igor Trofimov  
Дата: 25.09.05 17:54
Оценка:
Кстати, любопытно, что в LINQ Preview, в Query.dll вводится атрибут System.Runtime.CompilerServices.ExtensionAttribute, который прицеплен ко всем операциям над последовательностями (класс System.Query.Sequence). Кажется именно это и является для комплятора признаком метода-расширения.
Re[2]: С# 3.0
От: Дарней Россия  
Дата: 28.09.05 11:56
Оценка:
Здравствуйте, DarkGray, Вы писали:

DG>До сих пор не хватает "красивой" работы с нулевыми значениями


А может быть, вместо null надо использовать специальный "нулевой" объект для каждого типа? Например, для массивов он будет возвращать Count = 0
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Всех излечит, исцелит
добрый Ctrl+Alt+Delete
Re[3]: С# 3.0
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 28.09.05 12:18
Оценка:
Здравствуйте, Дарней, Вы писали:

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


DG>>До сих пор не хватает "красивой" работы с нулевыми значениями


Д>А может быть, вместо null надо использовать специальный "нулевой" объект для каждого типа? Например, для массивов он будет возвращать Count = 0

В Net стараются внедрять статическое свойство empty
... << RSDN@Home 1.1.4 stable rev. 510>>
и солнце б утром не вставало, когда бы не было меня
Re[2]: С# 3.0
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 01.10.05 01:12
Оценка:
AVK>А возможности подключения реализаций опять нет

Разговаривал сегодня на эту тему с Хейлсбергом. Итог таков — они много думали про подобное, но посчитали что это слишком тяжело для восприятия, посему ничего в таком направлении не сделали и перспектив на ближайшее будущее никаких.

P.S. Слева направо: Хейлсберг, я.
... << RSDN@Home 1.2.0 alpha rev. 617>>
AVK Blog
Re: С# 3.0
От: Merle Австрия http://rsdn.ru
Дата: 01.10.05 13:31
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Вышел первый прообраз спецификации.

Жаль... Задумка была хорошей, но похоже обречена....
Вся команда ObjectSpaces перешла в LINQ.
... << RSDN@Home 1.1.4 beta 6a rev. 0>>
Мы уже победили, просто это еще не так заметно...
Re[3]: С# 3.0
От: VladD2 Российская Империя www.nemerle.org
Дата: 03.10.05 01:37
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Разговаривал сегодня на эту тему с Хейлсбергом. Итог таков — они много думали про подобное, но посчитали что это слишком тяжело для восприятия, посему ничего в таком направлении не сделали и перспектив на ближайшее будущее никаких.


А ты ему не додумался дать в качестве идеи Скалу?
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: С# 3.0
От: VladD2 Российская Империя www.nemerle.org
Дата: 03.10.05 01:39
Оценка:
Здравствуйте, Merle, Вы писали:

M>Жаль... Задумка была хорошей, но похоже обречена....

M>Вся команда ObjectSpaces перешла в LINQ.

Вы бы им там сказали, что писат select в конце запросы — это по меньше мере странно (это я про квари компрехэншон).
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[8]: С# 3.0
От: ie Россия http://ziez.blogspot.com/
Дата: 03.10.05 02:40
Оценка: +1
Здравствуйте, DarkGray, Вы писали:

VD>> Будет у тебя нал-объект попадать во второй диапазон. Что страшного?


DG>страшно то, что результат должен был быть не такой.


DG>если это было бизнес-правило, например, для интернет-магазина:

DG>Если возвраст < 10, то показать рекламу детских игрушек.

DG>то пользователях, которые не указали возраст будет показывать не интересная им реклама, что для интернет магазина означает недополучение прибыли.


DG>И это ты называешь не страшно?


А на самом деле, что должно показываться таким пользователям?

Третий вид рекламы?

if (user.Age > 21)
{
//bla-bla
}
if (user.Age < 16 && user.Age > 0)
{
//bla-bla
}


Реклама для взрослых?

Тогда дефолтное значение можно взять заведомо большое, типа int.MaxValue.
Превратим окружающую нас среду в воскресенье.
Re[9]: С# 3.0
От: DarkGray Россия http://blog.metatech.ru/post/ogni-razrabotki.aspx
Дата: 03.10.05 07:45
Оценка:
ie>А на самом деле, что должно показываться таким пользователям?
ie>Третий вид рекламы?
ie>Реклама для взрослых?

Может быть ничего, может какая-то другая реклама, может еще что-то.

В том-то и дело, что я не хочу об этом думать, когда пишу вышеперечисленные правила, я хочу иметь атомарность при внесении новых правил, изменении старых и т.д..
Если же я завожу какие-то NullObject-ы, default-ные MinValue, MaxValue — то у меня эта атомарность пропадает.

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



ie>Тогда дефолтное значение можно взять заведомо большое, типа int.MaxValue.


Чтобы сделать такое предположение, я должен иметь полное представление о том, какие правила у меня есть сейчас, будут завтра.
А зачем мне тратить свое время на то, чтобы такое знание получить?
Re: С# 3.0
От: ie Россия http://ziez.blogspot.com/
Дата: 03.10.05 11:23
Оценка:
Написал такой Extension:
    static class StringExt
    {
        public static bool IsEmpty(this string str)
        {
            return (str == null || str.Length == 0);
        }
    }

Юзаю во всю, красота:
    param.IsEmpty();

А потом подумалось: если раньше глядя на такой код, ты можешь быть уверен, что в в случае param == null вылетит NullReferenceException, то теперь эта уверенность пропадает. С одной стороны "ООП всегда! ООП везде! ООП на радость нам!", а с другой стороны, какой-то не правильный ООП получается
Превратим окружающую нас среду в воскресенье.
Re[3]: С# 3.0
От: IT Россия linq2db.com
Дата: 03.10.05 11:26
Оценка: :))) :))) :))) :))) :)
Здравствуйте, AndrewVK, Вы писали:

AVK>P.S. Слева направо: Хейлсберг, я.


Фотошоп?
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[3]: С# 3.0
От: GlebZ Россия  
Дата: 03.10.05 12:10
Оценка: :)
Здравствуйте, VladD2, Вы писали:

VD>Вы бы им там сказали, что писат select в конце запросы — это по меньше мере странно (это я про квари компрехэншон).

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

С уважением, Gleb.
Re[3]: С# 3.0
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 03.10.05 13:39
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Вы бы им там сказали, что писат select в конце запросы — это по меньше мере странно (это я про квари компрехэншон).


Там, если копнуть поглубже, странного намного больше. На самом деле как SQL он только выглядит на совсем простых запросах. А как чего посложнее с участием нескольких таблиц, так больше начинает смахивать на эдакий гибрид sql и xpath (а в васике вобще, уроды, в запросе xml используют).
... << RSDN@Home 1.2.0 alpha rev. 617>>
AVK Blog
Re[2]: С# 3.0
От: Alexey Axyonov Украина  
Дата: 03.10.05 14:01
Оценка:
Здравствуйте, ie, Вы писали:

ie>Написал такой Extension:


А зачем?

string.IsNullOrEmpty(str);


не подходит?
... << RSDN@Home 1.2.0 alpha rev. 618>>
Re[3]: С# 3.0
От: ie Россия http://ziez.blogspot.com/
Дата: 03.10.05 14:44
Оценка: :)
Здравствуйте, Alexey Axyonov, Вы писали:

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


ie>>Написал такой Extension:


AA>А зачем?


AA>
string.IsNullOrEmpty(str);


AA>не подходит?


Ну это пример такой. Могу другой придумать...
... << RSDN@Home 1.1.4 stable rev. 510>>
Превратим окружающую нас среду в воскресенье.
Re[4]: С# 3.0
От: VladD2 Российская Империя www.nemerle.org
Дата: 03.10.05 15:26
Оценка:
Здравствуйте, GlebZ, Вы писали:

GZ>Все програссивное теловетчество наоборот, плачет из-за того что select находится впереди, а не позади from.


Можно пальцем на это "Все програссивное теловетчество"?

GZ>Приходится вторым проходом проверять семантику селекта, потому как низзя узнать семантически что же здесь хотели юзвери без полей из from.


Это ты про проходы людских глаз? Или ты беспокошся за эффективность компиляторов? Если, за последнее, то лучше не беспокойся. У компиляторов проблем нет. Они один хрен сначала AST создают.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: С# 3.0
От: alexeiz  
Дата: 03.10.05 17:35
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>P.S. Слева направо: Хейлсберг, я.


Re[4]: С# 3.0
От: VladD2 Российская Империя www.nemerle.org
Дата: 04.10.05 00:30
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Там, если копнуть поглубже, странного намного больше. На самом деле как SQL он только выглядит на совсем простых запросах. А как чего посложнее с участием нескольких таблиц, так больше начинает смахивать на эдакий гибрид sql и xpath (а в васике вобще, уроды, в запросе xml используют).


Дык это то понятно. Все же иерархические запросы, хотя как я понял из примеров и джоины там есть как в старом SQL и вообще все очень даже похоже.

Но select сздани — это полнейший изврат. Читашь и чувствуешь себя дебилом. А вся аргументация про области видимости выглядит просто смешно, да и в Жлабэйсике то сделали по человечески.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: С# 3.0
От: VladD2 Российская Империя www.nemerle.org
Дата: 04.10.05 00:30
Оценка: :)
Здравствуйте, ie, Вы писали:

ie>Написал такой Extension:

ie>
ie>    static class StringExt
ie>    {
ie>        public static bool IsEmpty(this string str)
ie>        {
ie>            return (str == null || str.Length == 0);
ie>        }
ie>    }  
ie>

Скажи, а выделенные скобки — это чтобы возврат из функции не дай бог не выполнися раньше чем вычисление выражения?

Кстати, можно было бы просо:
string.IsEmtyOrNull(str == null || str.Length == 0)


ie>А потом подумалось: если раньше глядя на такой код, ты можешь быть уверен, что в в случае param == null вылетит NullReferenceException, то теперь эта уверенность пропадает. С одной стороны "ООП всегда! ООП везде! ООП на радость нам!", а с другой стороны, какой-то не правильный ООП получается


+1
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.