Re[5]: Facebook и язык D - первый шаг наверх.
От: Evgeny.Panasyuk Россия  
Дата: 21.10.13 19:38
Оценка: 7 (1)
Здравствуйте, D. Mon, Вы писали:

EP>>В следующем году будут концепции — большой шаг вперёд. А что тут может предложить D? duck-typing?

DM>Я не знаю всех подробностей плюсовых концептов, но судя по тому, что Страуструп недавно рассказывал на Going Native, обещая в С++14, это уже очень давно есть в D в намного более удобном и мощном виде. Об этом же говорит Александреску.

Александреску скорей всего говорил о static if — что хоть и пересекается в некоторых простых use-case'а с концепциями, но всё таки является более примитивной feature. Пример использования концепций:
void sort(RandomAccessRange &x)
{
   //...
}
void sort(BidirectionalRange &x)
{
   //...
}

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

DM>Про производительность range'й не очень понял — где именно она хуже? В плюсах принято передавать два итератора, begin и end, в D их объединили в одну структуру, получили range.

DM>Смысл тот же, но меньше писанины и меньше ошибок.

Нет — range в D это другое — там совсем убрали итераторы, к ним вообще нет доступа.
Объедение итераторов в структуру это больше про Boost.Range — что действительно сокращает "писанину" и позволяет избежать некоторые ошибки, но из таких Range можно получить доступ к итераторам — они их не прячут.

Итераторы C++ обеспечивают эффективную композицию. Если у нас есть 4 итератора, то из них можно получить 6 range бесплатно, без runtime penalty — просто выбери нужную пару итераторов.

Но, чисто range'ы без итераторов, как в D — теряют свойства композиции, код алгоритмов получается менее эффективным, что неприемлемо для C++. Например тот же partition:
auto result = r;
for (;;)
{
    for (;;)
    {
        if (r.empty) return result;
        if (!pred(r.front)) break;
        r.popFront();
        result.popFront();
    }
    for (;;)
    {
        if (pred(r.back)) break;
        r.popBack();
        if (r.empty) return result;
    }
    swap(r.front, r.back);
    r.popFront();
    result.popFront();
    r.popBack();
}

Чтобы вернуть вменяемый результат, параллельно "рабочему" range'у приходится передёргивать дополнительный range result. В то время как в STL, нет этих лишних телодвижений — возвращается итератор, который практически бесплатно определяет два range'а.
Например код из SGI STL:
while (true)
{
    while (true)
        if (first == last) return first;
        else if (pred(*first)) ++first;
        else break;
    --last;
    while (true)
        if (first == last) return first;
        else if (!pred(*last)) --last;
        else break;
    iter_swap(first, last);
    ++first;
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.