Снова D: Зверёк читает мануал
От: Зверёк Харьковский  
Дата: 02.05.05 19:15
Оценка: 17 (4)
Предыстория вопроса
D — интересный язык, который мы тут обсуждаем в последнее время
Автор: c-smile
Дата: 01.05.05
. Я начал изучать его недавно, и он мне нра В "Дизайне и Эволюции С++" был такой пассажик: Бьерн сомневается, в правильном ли направлении он движется, и один из создателей языка С успокаивает его фразой "С++ — это то, чем бы мы сделали С, если бы могли". Так, вот, при ознакомлении с D у меня временами (далеко не всегда!) возникает впечатление, что D — это то, чем мог бы быть С++.

Так вот — сейчас сижу читаю мануал этого забавного языка. И возникло у меня желание делиться с окружающими интересными фактами. А раз возникло — то этим я в этой ветке и займусь. Цель этого мне видится не в ознакомлении всего РСДНа с новым языком — а в обсуждении новых или не очень концепций D и их реализации. В конце концов, если это никому не интересно — бомбочек навешаете и всех делов
Поехали!



Перегрузка операторов
Хорошая новость: она есть. Но выглядит несколько... вычурно, что ли?
В С++ мы имеем "естественный синтаксис:
class A
{
...
    int operator+(int);        //оператор сложения A+int
...
}

В принципе, такой синтаксис в некоторой степени самоописателен.

В D та же задача решается следующим способом:
class A
{
...
    int opAdd(int);        //оператор сложения A+int - функция со "специальным" именем opAdd
...
}

Результат, как бы, тот же. Но выглядит это слегка менее очевидно.
Зачем это сделано?
Во-первых, один из design goals языка D — упрощение (по сравнению с С++) лексического/синтаксического анализатора (поэтому D вообще больше склонен к словам, чем к "значками").
Во-вторых, при этом достигается довольно интересный эффект:
A a;
double d = 1/a;     //как написать кастомный оператор для этого случая?


В С++ выходом из этой ситуации стали операторы — свободные функции:
class A
{
...
};

double operator/(int, A&);

А вот в D — "несимметричные операторные функции" ((с) термина мой):
class A
{
    double opDiv_r(int, A&);    //opDiv + _r (right)
};


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

А вот — очень интересная фича операторов D: они в явном виде поддерживают "зависимые операторы":
//C++
A a, b;
if(a == b)    ...            //вызов A.operator==
if(a != b)    ...            //вызов A.operator!=

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

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

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

//C++
A a, b;
if(a > b)    ...            //вызов A.operator>
if(a < b)    ...            //вызов A.operator<
//...и т.д.

//D
A a, b;
if(a <  b)    ...            //вызов A.opCmp(b) <  0
if(a >  b)    ...            //вызов A.opCmp(b) >  0
if(a <= b)    ...            //вызов A.opCmp(b) <= 0
if(a >= b)    ...            //вызов A.opCmp(b) >= 0

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

К слову, эта идея (избавления от "ненужных операторов") не распространена на операторы вида op= (+=, -= и т.д.). Почему? То есть, конечно, логику в этом, видимо, можно найти... Но лень.

Уф... умаялся. Все пока.
... << RSDN@Home 1.1.4 beta 6a rev. 436>>
FAQ — це мiй ай-кью!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.