Re[4]: Снова D: Зверёк читает мануал
От: Зверёк Харьковский  
Дата: 03.05.05 13:55
Оценка: +2
Здравствуйте, eao197, Вы писали:

ЗХ>>Я, когда мне нужно использовать в качестве ключей мапы класс, сравнение объектов которого бессмысленно, предпочитаю определять для этого свой функтор-компаратор, который не выглядит как operator<


E>Вообще-то я не думаю, что сравнение объектов, которые используются в качестве ключа map-а бессмыслено. Ведь в std::map ключи элементов как раз-таки сравниваются


E>А пример мой был к тому, что если в C++ мне потребуется сделать класс, от которого средства языка (std::{multi}map, std::{multi}set, std::find, ...) требуют только наличия operator<(), то я и реализую только это. И если от моего класса начинают требовать чего-то еще, то тут же получают по рукам.


На что я и ответил: по сути, существует два омонима: оператор "меньше" (в "численном" смысле. Преполагает наличие операторов больше, меньше-равно, больше-равно, равно, неравно...) и оператор порядка ("предыдущий").

Первый используется в "арифметических" операциях (a+b < c+d*x); второй — только и исключительно (кажется ) для создания сортированных последовательностей.

Грубо говоря, complex::operator< ты скорее всего будешь использовать "лично", а string::operator< тебе нужен только для того, чтобы можно было создавать всякие штуки вроде сортированных списков — либо для представления их пользователю, либо для эффективных алгоритмов. Так?

То есть в идеале строк вида if(string1 < string2) в прикладном коде ваааще не встретится.

Соответственно, в случае "арифметического оператора" ему нужны соответствующие дополнительные операторы; в случае "оператора порядка" — не, не нужны.

А еще какие-то случаи ты можешь придумать, когда тебе нужен только 1 оператор, а не все?

E>И если я по своей лени в D напишу что-то подобное:

...
E>    int    opCmp( Compound_Key o )
E>    {
E>        if( a_ < o.a_ || ( a_ == o.a_ && b_ < o.b_ ) )
E>            return -1;
E>        // Оптимистично предполагаем, что всегда будет использоваться (c1<c2).
E>        return 0;
E>    }
...

E>то приведенная тобой конструкция (if(a>b)) на этапе компиляции вообще ошибки не диагностирует.

А вот тут не могу не согласиться. Еще одно замечание не в пользу D — для использования в качестве ключа ассоциативного массива (в D они являются частью core language) класс должен иметь-таки opCmp (а кроме того, кстати, еще и функцию Hash() )

ЗЫ: я все еще не доказываю превосходство/уродство D, а показываю штуки, которые мне в нем показались занятными
... << RSDN@Home 1.1.4 beta 6a rev. 436>>
FAQ — це мiй ай-кью!
Re[5]: Снова D: Зверёк читает мануал
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 03.05.05 14:13
Оценка: +1
Здравствуйте, Зверёк Харьковский, Вы писали:

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


ЗХ>>>Я, когда мне нужно использовать в качестве ключей мапы класс, сравнение объектов которого бессмысленно, предпочитаю определять для этого свой функтор-компаратор, который не выглядит как operator<


E>>Вообще-то я не думаю, что сравнение объектов, которые используются в качестве ключа map-а бессмыслено. Ведь в std::map ключи элементов как раз-таки сравниваются


E>>А пример мой был к тому, что если в C++ мне потребуется сделать класс, от которого средства языка (std::{multi}map, std::{multi}set, std::find, ...) требуют только наличия operator<(), то я и реализую только это. И если от моего класса начинают требовать чего-то еще, то тут же получают по рукам.


ЗХ>На что я и ответил: по сути, существует два омонима: оператор "меньше" (в "численном" смысле. Преполагает наличие операторов больше, меньше-равно, больше-равно, равно, неравно...) и оператор порядка ("предыдущий").


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

ЗХ>А еще какие-то случаи ты можешь придумать, когда тебе нужен только 1 оператор, а не все?


Пожалуй нет. За исключением того, что STL доказал, что достаточно в каком-то типе определить всего один оператор, а все остальные операторы сравнения (именно в "численном" смысле) можно различными темплейтовыми обертками добавить.

ЗХ>ЗЫ: я все еще не доказываю превосходство/уродство D, а показываю штуки, которые мне в нем показались занятными

Да я тоже, просто конкретно это решение мне показалось не столь удачным, как некоторые другие штуки в D.
Когда-то год-полтора назад я сам прочитал описание D и подумал, что это тот язык на который бы я с C++ перешел. Будь он больше обеспечен всякими сторонними библиотеками (криптография там всякая, XML, HTTP, ...)
Может со временем ситуация наладится.
... << RSDN@Home 1.1.4 beta 6a rev. 436>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[6]: Снова D: Зверёк читает мануал
От: Зверёк Харьковский  
Дата: 03.05.05 14:28
Оценка:
Здравствуйте, eao197, Вы писали:

ЗХ>>На что я и ответил: по сути, существует два омонима: оператор "меньше" (в "численном" смысле. Преполагает наличие операторов больше, меньше-равно, больше-равно, равно, неравно...) и оператор порядка ("предыдущий").


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


Я бы с удовольствием... Но в нужный момент не вспомнил слово "предшествование"

ЗХ>>А еще какие-то случаи ты можешь придумать, когда тебе нужен только 1 оператор, а не все?


E>Пожалуй нет. За исключением того, что STL доказал, что достаточно в каком-то типе определить всего один оператор, а все остальные операторы сравнения (именно в "численном" смысле) можно различными темплейтовыми обертками добавить.


+1
по сути, идея "реализуй необходимый минимум, а все остальное добавится автоматом" — она вполне какчественно реализована в boost::operators и boost::iterator_adaptors.
Но включение этого принципа в явном виде в core language — имхо, вполне достойная задумка! (хотя реализация этой задумки в D, как мы уже выяснили — дааалеко не идеал)

ЗХ>>ЗЫ: я все еще не доказываю превосходство/уродство D, а показываю штуки, которые мне в нем показались занятными

E>Да я тоже, просто конкретно это решение мне показалось не столь удачным, как некоторые другие штуки в D.
E>Когда-то год-полтора назад я сам прочитал описание D и подумал, что это тот язык на который бы я с C++ перешел. Будь он больше обеспечен всякими сторонними библиотеками (криптография там всякая, XML, HTTP, ...)
E>Может со временем ситуация наладится.

Да я вот все думаю, с какой бы стороны подступиться к интеграции его с С++ными библиотеками... ИМХО, решение должно быть где-то рядом
... << RSDN@Home 1.1.4 beta 6a rev. 436>>
FAQ — це мiй ай-кью!
Re: Снова D: Зверёк читает мануал
От: Conr Россия  
Дата: 03.05.05 14:29
Оценка: 6 (2) +2
Здравствуйте, Зверёк Харьковский, Вы писали:

Добавлю от себя:
Не существует неинициализированных стековых переменных
byte[100] array; // будут инициализированны по умолчанию.


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

Передача параметров в функции
По умолчанию все in. Для out & inout нужно указывать специально. Причем для out переменная инициализируется по умолчанию или вызывается соответствующий конструктор.
void foo(out int bar)
{
}
    int bar = 3;
    foo(bar);
//    bar is now 0
Re: Снова D: Зверёк читает мануал
От: McSeem2 США http://www.antigrain.com
Дата: 03.05.05 14:32
Оценка: 3 (1) +1
Здравствуйте, Зверёк Харьковский, Вы писали:

ЗХ>А вот — очень интересная фича операторов D: они в явном виде поддерживают "зависимые операторы":

ЗХ>
ЗХ>//D
ЗХ>A a, b;
ЗХ>if(a == b)    ...            //вызов A.opEquals
ЗХ>if(a != b)    ...            //вызов !A.opEquals
ЗХ>

ЗХ>то есть оператора != не существует по определению.

ЗХ>И даже более того: все четыре сравнения (>, <, >=, <=) выполняются одним оператором opCmp:


С точки зрения производительности я бы не назвал opCmp однозначным рулезом.
Во избежание сюрпризов надо писать так:
int opCmp(T a, T b) 
{ 
   if(a < b) return -1;
   if(a > b) return 1;
   return 0;
}


С учетом наличия методов у простых типов, можно, конечно писать return a.opCmp(b), но при этом компилятор все равно обязан сгенерировать код приведенный выше. Иначе — чревато сюрпризами. То есть, снаружи выглядит конечно удобно, но внутри подпадает под случай "вылить воду из чайника и таким образом свести задачу к предыдущей".
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re[7]: Снова D: Зверёк читает мануал
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 03.05.05 14:33
Оценка:
Здравствуйте, Зверёк Харьковский, Вы писали:

ЗХ>Да я вот все думаю, с какой бы стороны подступиться к интеграции его с С++ными библиотеками... ИМХО, решение должно быть где-то рядом


Ну а я пока решил подождать и посмотреть, чем же все-таки развитие D продолжится.
К тому же сейчас меня не устраивает еще и то, что компилятор D существует только для Windows и Linux. У меня такая специфика, что в любой момент могут обязать перейти куданить в BSD или Solaris, или еще куда поэкзотичнее. А там пока D нет
... << RSDN@Home 1.1.4 beta 6a rev. 436>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[3]: Снова D: Зверёк читает мануал
От: IT Россия linq2db.com
Дата: 03.05.05 14:39
Оценка: :)
Здравствуйте, Зверёк Харьковский, Вы писали:

ЗХ>

ЗХ>(с) я.


Вау! Мы уже себя цетируем Хочешь я тебе надпись сделаю под ником "великий и ужасный"?
... << RSDN@Home 1.1.4 beta 5 rev. 395>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[2]: Снова D: Зверёк читает мануал
От: Зверёк Харьковский  
Дата: 03.05.05 15:07
Оценка:
Здравствуйте, FR, Вы писали:

FR>У меня прямо дежавю какое то, все как в питоне


забавно а как это там выглядит?
... << RSDN@Home 1.1.4 beta 6a rev. 436>>
FAQ — це мiй ай-кью!
Re[2]: Зверёк читает мануал: properties
От: LCR Россия lj://_lcr_
Дата: 03.05.05 15:09
Оценка:
c-smile, Зверёк из Харькова,

CS>
CS>typedef uint Color; 
CS>Color c; 
CS>c += 28; // ошибка компиляции.
CS>


Увы, здесь имхо D перенял идеологический косяк из C++, гораздо лучше было бы следущее
typedef Color = ....;
// или
type Color = ...;


Лучше, потому что естественнее; непосредственно соответствует нормальному предложению на естественном языке "тип Color это то-то и то-то".

Ы?
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[4]: Снова D: Зверёк читает мануал
От: Зверёк Харьковский  
Дата: 03.05.05 15:18
Оценка:
Здравствуйте, IT, Вы писали:

ЗХ>>

ЗХ>>(с) я.


IT>Вау! Мы уже себя цетируем Хочешь я тебе надпись сделаю под ником "великий и ужасный"?


А можно? Хочу Буду Влада пугать
... << RSDN@Home 1.1.4 beta 6a rev. 436>>
FAQ — це мiй ай-кью!
Re[2]: Снова D: Зверёк читает мануал
От: Зверёк Харьковский  
Дата: 03.05.05 15:18
Оценка:
Здравствуйте, McSeem2, Вы писали:

ЗХ>>И даже более того: все четыре сравнения (>, <, >=, <=) выполняются одним оператором opCmp:


MS>С точки зрения производительности я бы не назвал opCmp однозначным рулезом.

MS>Во избежание сюрпризов надо писать так:
MS>
MS>int opCmp(T a, T b) 
MS>{ 
MS>   if(a < b) return -1;
MS>   if(a > b) return 1;
MS>   return 0;
MS>}
MS>


MS>С учетом наличия методов у простых типов, можно, конечно писать return a.opCmp(b), но при этом компилятор все равно обязан сгенерировать код приведенный выше. Иначе — чревато сюрпризами. То есть, снаружи выглядит конечно удобно, но внутри подпадает под случай "вылить воду из чайника и таким образом свести задачу к предыдущей".


Угу, я тоже об этом подумал... Решение вообще говоря, несколько искусственное.
Вот с автогенеренным != мне больше понравилось — естественнее что ли.

Моя бы воля — я бы сделал как-то так:
//это - С++
//надо определить:

bool operator==(A&);
bool operator< (A&);

//сами сгенерятся:
bool operator!=(A&);    //!operator==
bool operator>=(A&);    //!operator<
bool operator<=(A&);    //operator== || operator<
bool operator> (A&);    //!operator<=

Два последних оператора — не очень-то рулез по производительности. Зато по очевидности — это, имхо намного лучше, чем "многозначный" оператор из D
К слову сказать, если я правильно понимаю, boost::operators как раз и позволяет так сделать
... << RSDN@Home 1.1.4 beta 6a rev. 436>>
FAQ — це мiй ай-кью!
Re[3]: Зверёк читает мануал: properties
От: Зверёк Харьковский  
Дата: 03.05.05 15:24
Оценка:
Здравствуйте, LCR, Вы писали:

CS>>
CS>>typedef uint Color; 
CS>>


LCR>Увы, здесь имхо D перенял идеологический косяк из C++, гораздо лучше было бы следущее

LCR>
LCR>typedef Color = ....;
LCR>// или
LCR>type Color = ...;
LCR>


LCR>Лучше, потому что естественнее; непосредственно соответствует нормальному предложению на естественном языке "тип Color это то-то и то-то".


LCR>Ы?


Зато в том виде, как оно есть — оно совпадает с синтаксисом определения, и это гут:
int c;    //переменная типа int
typedef int mycoolint;    //тип "типа" int


вообще, фигня это, охота за воробьями...
Dim VBAForeva As Rulezzzz;
... << RSDN@Home 1.1.4 beta 6a rev. 436>>
FAQ — це мiй ай-кью!
Re: Арифметические операции
От: McSeem2 США http://www.antigrain.com
Дата: 03.05.05 15:34
Оценка:
В высокоуровневых языках часто возникает ситуация "за лесом деревьев не видать".
Взять, хртя бы простейшее выражение (операция целочисленного масштабирования):
int v = a*b/c;

a, b, c — все int. Так вот, на всех известных мне современных архитектурах, операция MUL выдает результат вдвое большей разрядности. А операция DIV тоже требует двойной разрядности. Таким образом, при использовании ассемблера, можно масштабировать целые значения практически во всем их диапазоне, не переходя на двойную разрядность целиком.

Но копилятор обязан обрезать промежуточный результат a*b снова до одинарной разрядности и нет способа объяснить, что вот в данном случае обрезать не надо. Почему "обязан" — во-первых, компилятор не знает — может быть переполнение играет важную роль в данном алгоритме. Во-вторых, если мы усложним выражение: a*b*c/d — нам уже понадобится не двойная а тройная разрядность. Таким образом, в языках высокого уровня нет способа задействовать простую и эффективную последовательность инструкций mul/div. Таким образом, хотелось бы иметь что-то типа:

v = a.muldiv(b, c);
или 
v = a.mulshift(b, 32); // - умножаем и берем старшие 32 бита


Повторю еще раз — в рамках арифметической записи задача нерешаема в любом языке.

Другая часто возникающая потребность — получение частного и остатка. Во всех извесных мне архитектурах это делается одной командой DIV. Но вот мы пишем:
int lift = a/b;
int rem  = a%b;

И у нас нет ни малейшей гарантии того, что компилятор соптимизирует данную конструкцию в одну команду. А хотелось бы именно гарантии. Но для этого нужна специальная конструкция языка, причем весьма нетривиальная — с двумя взвращаемыми значениями.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re[8]: Снова D: Зверёк читает мануал
От: Conr Россия  
Дата: 03.05.05 15:36
Оценка:
Здравствуйте, eao197, Вы писали:

E>Здравствуйте, Зверёк Харьковский, Вы писали:


ЗХ>>Да я вот все думаю, с какой бы стороны подступиться к интеграции его с С++ными библиотеками... ИМХО, решение должно быть где-то рядом

Сомневаюсь Будет большая проблема с тем, что D строит аналог vtable произвольным образом. То есть он может менять местами методы и даже их удалять за ненадобностью...

E>Ну а я пока решил подождать и посмотреть, чем же все-таки развитие D продолжится.

E>К тому же сейчас меня не устраивает еще и то, что компилятор D существует только для Windows и Linux. У меня такая специфика, что в любой момент могут обязать перейти куданить в BSD или Solaris, или еще куда поэкзотичнее. А там пока D нет
Есть GNU D Compiler + http://home.earthlink.net/~dvdfrdmn/d. То есть в теории собирать можно где угодно, нужно только GCC старше 3.3
Re[5]: Снова D: Зверёк читает мануал
От: IT Россия linq2db.com
Дата: 03.05.05 16:12
Оценка:
Здравствуйте, Зверёк Харьковский, Вы писали:

ЗХ>А можно? Хочу Буду Влада пугать


А ну ка попробуй чего-нибудь написать
... << RSDN@Home 1.1.4 beta 5 rev. 395>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[7]: Снова D: Зверёк читает мануал
От: uw  
Дата: 03.05.05 16:15
Оценка: 70 (2)
Здравствуйте, Зверёк Харьковский, Вы писали:

ЗХ>Да я вот все думаю, с какой бы стороны подступиться к интеграции его с С++ными библиотеками... ИМХО, решение должно быть где-то рядом

SWIG

Вроде кто-то реализовывал поддержку D. Самые новые исходники там, в svn репозитории. В каком это состоянии, я не в курсе, но возможно во вполне работоспособном. Вот страница с более старыми версиями(включая бинарники) и хоть каким-то описанием.
Re[3]: Снова D: Зверёк читает мануал
От: uw  
Дата: 03.05.05 16:15
Оценка: +2
Здравствуйте, Зверёк Харьковский, Вы писали:

ЗХ>Два последних оператора — не очень-то рулез по производительности. Зато по очевидности — это, имхо намного лучше, чем "многозначный" оператор из D

Этот "многозначный" оператор придуман в первую очередь для случаев, когда сравниваемые значения(или их часть) можно привести к целочисленному типу. Такая модель сравнения давным-давно используется скажем в libc(strcmp, qsort, итд), Java(интерфейс Comparable), .NET(IComparable).

Что может быть проще и очевидней вот такого кода?

class Task
{
    private int priority;
    public int opCmp(Task t)
    {
        return priority - t.priority;
    }
}
Re[2]: Арифметические операции
От: uw  
Дата: 03.05.05 16:31
Оценка: 15 (1)
Здравствуйте, McSeem2, Вы писали:

MS>Повторю еще раз — в рамках арифметической записи задача нерешаема в любом языке.

MS>Другая часто возникающая потребность — получение частного и остатка. Во всех извесных мне архитектурах это делается одной командой DIV. Но вот мы пишем:
MS>
MS>int lift = a/b;
MS>int rem  = a%b;
MS>

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

На самом деле работы в этом направлении(гарантированная оптимизация) ведутся, пока только исследовательские. И для этого не нужна будет специальная конструкция языка. Кстати два возвращаемых значения для функциональных языков(коими ни D,ни C++ естественно не являются) не проблема.
Re[4]: Зверёк читает мануал: properties
От: LCR Россия lj://_lcr_
Дата: 03.05.05 16:32
Оценка:
Зверёк,

Только давай чуть-чуть усовершенствуем
ЗХ>
ЗХ>int c;    //переменная типа int
ЗХ>typedef int mycoolint;    //тип "типа" int
ME>typedef int (*mcfp[](int (*fp)(void* v1, void* v2), int& r);
ME>struct S {....};
ME>struct _tagS {....} S1; // определение типа S1!
ME>class C {...};
ME>enum E {...};
ЗХ>

И куда делась твоя аналогия? Ты видишь, она годится только для простых случаев.

ЗХ>вообще, фигня это, охота за воробьями...

ЗХ>
ЗХ>Dim VBAForeva As Rulezzzz;
ЗХ>


type ocaml_owns_all =
  Val of int
  | Fun of (float->string) * ocaml_owns_all;;


В данном случае type (может быть в васике тоже самое, в паскале что-то типа этого) совершенно однородно и для простых, и для сложных случаев — выражение после знака равенства может быть сколько угодно сложным и при этом мы в своём головном мозге это выражение раскручиваем по одним и тем же правилам независимо от сложности этого выражения. Правила простые, но применяться они могут к различным уровням разбора, то есть рекурсивно.

Посмотрим на случай с сями. Каждый раз глядя на ензувуа мы должны мысленно его отбросить и выяснить, какого же типа переменная объявлена в данном случае. Потом выяснив тип переменной, мы должны мысленно себе сказать: "Вот, это такой тип". Более того, для других типов (классов, структур, перечислений) определения должны выглядеть по-другому. Примечателен пример определения для типа S1.

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

type mcfp = array of
(
  func * : ( (func * : (void *, void *) -> int ), void * ) -> int
);

Определение однородно и расширяемо.

И на засыпку. Можешь ли ты с такой же лёгкостью, как ты говоришь слово "ХА", сказать, что в данном случае указатель на массив, а что массив указателей:
typedef int *myarr1[];
typedef int (*myarr2)[];

?
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[5]: Зверёк читает мануал: properties
От: LCR Россия lj://_lcr_
Дата: 03.05.05 16:37
Оценка:
К модератору,

Подредактируй(те) пожалуйста моё сообщение http://www.rsdn.ru/Forum/?mid=1154797&amp;flat=0
Автор: LCR
Дата: 03.05.05
— нужно убрать ME перед type, и вставить закрывающий тэг перед словами "Определение однородно и расширяемо". Никак не могу себя приучить делать предпросмотр...
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.