LINUX.ORG.RU

Rust 0.10

 ,


2

8

Вышла новая версия Rust, языка программирования разрабатываемого Mozilla. Релиз несет в себе около 1500 изменений и исправлений ошибок.

Основные изменения:

  • Язык:
    • новый процесс RFC для изменения языка;
    • паттерны с '@'-указателями удалены из языка;
    • паттерны с '~[T]'-векторами удалены из языка;
    • паттерны с '~str'-строками удалены из языка;
    • '@str' удален;
    • '@[T]' удален;
    • '@self' удален;
    • '@Trait' удален;
    • заголовки, содержащие '@'-boxes для подсчета ссылок внутри типа, при '~'-аллокациях удалены;
    • семантика времени жизни временных выражений (temporary expressions) изменена. Подробнее в #3511, #11585;
    • добавлен новый cross-crate синтаксис расширений (доступен через feature gates). Подробнее в #11151. Эта возможность включает в себя макросы 'macro_rules!' и 'format!' как синтаксические расширения;
    • добавлены новые режимы lint, использование старых по умолчанию выдает предупреждения:
      • лишние скобки;
      • static в верхнем регистре;
      • Camel Case типы;
      • переменные в верхнем регистре;
      • приватные типы с публичной видимостью;
      • '#[deriving]' с raw-указателями.
    • unsafe-функции больше не преобразуются к замыканиям;
    • некоторые макросы с неясными названиями, например 'log_syntax!', теперь доступны через feature gates;
    • атрибут '#[simd]' теперь доступен через feature gates;
    • запрещены инструкции 'extern crate' в настройках видимости, модификатор 'priv' запрещен к использованию вместе с 'use' инструкциями;
    • замыкающие запятые запрещены в списках аргументов и шаблонах кортежей;
    • ключевое слово 'do' теперь является резервированным ключевым словом;
    • добавлены параметры типов по умолчанию, доступно через feature gates;
    • изменен механизм захвата borrowed-переменных в замыкания;
    • 'extern mod' изменен на 'extern crate';
    • удален 'Freeze' trait;
    • добавлен 'Share' trait для типов которые могут разделяться между потоками;
    • labels в макросах теперь гигиенические;
    • вызовы макросов теперь могут ограничиваться через '{}';
    • добавлен возможность перегрузки операторов '*' и '.' через 'Deref' и 'DerefMut' traits;
    • '~Trait' и 'proc' больше не реализуют 'Send' по умолчанию;
    • добавлена поддержка partial type hints через маркер типа '_';
    • введен тип 'Unsafe' для внутренней мутабельности. Преобразование '&T' в '&mut T' без использования 'Unsafe' является неопределенным;
    • реализован атрибут '#[linkage]' для внешних функций;
    • внутренний синтаксис атрибутов изменен с '#[foo];' на '#![foo]';
    • 'Pod' переименован в 'Copy'.
  • Библиотеки:
    • 'libextra' более недоступна. Она была разделена на более мелкие компоненты. Подробности в документации;
    • 'std::condition' удален. Все ошибки I/O передаются через тип 'Result'. Изменена работа макроса 'try!', подробности в #12039;
    • std: модуль 'vec' переименован в 'slice';
    • std: добавлен новый тип 'Vec<T>' для DST. В будущем это будет единственный вектор с изменяемым размером;
    • std: увеличено число публичных reexports 'std::io'. Типы, такие как 'BufferedReader' доступны через 'std::io::BufferedReader' вместо 'std::io::buffered::BufferedReader';
    • std: 'print' и 'println' более не доступны в prelude, используйте вместо них макрос 'println!';
    • std: 'Rc' теперь имеет 'Weak' указатель для прерываемых циклов и больше не пытается статически предотвращать циклы;
    • std: в стандартной поставке используется политика обработки ошибок пользователем вместо падения в библиотеках. Многие функции, такие как 'slice::last()' теперь возвращают 'Option<T>';
    • std: 'fmt::Default' переименован в 'fmt::Show', добавлен новый deriving mode: '#[deriving(Show)]';
    • std: 'ToStr' реализован для всех типов, реализующих 'Show';
    • std: trait для форматированного вывода принимает '&self' вместо '&T';
    • std: метод итераторов 'invert()' был переименован в 'rev()';
    • std: добавлена возможности вывода backtrace при падении task'a, если выставлено значение переменной 'RUST_BACKTRACE';
    • std: стандартизованы соглашения по наименованию для итераторов. Подробнее в wiki;
    • std: 'eof()' удален из 'Reader';
    • std: сетевые типы (networking types) теперь cloneable, разрешено одновременное чтение/запись;
    • std: 'assert_approx_eq!' удален;
    • std: добавлены спецификаторы форматирования 'e' и 'E' для вывода чисел с плавающей точкой в экспоненциальном формате;
    • std: удален 'Times';
    • std: добавлен тип 'std::kinds::marker' для выборочного вывода встроенных привязок (bounds);
    • std: 'hash' был переписан, 'IterBytes' удален, доступен '#[deriving(Hash)]';
    • std: 'SharedChan' был удален, 'Sender' теперь cloneable;
    • std: 'Chan' и 'Port' были переименованы в 'Sender' и 'Receiver';
    • std: 'Chan::new' заменен на 'channel()';
    • std: реализован новый тип синхронных каналов;
    • std: макрос 'select!' доступен для выбора 'Receiver'-ов;
    • std: 'hashmap' и 'trie' были перемещены в 'libcollections';
    • std: 'run' перемещен в 'io::process';
    • std: 'assert_eq!' теперь использует '{}' вместо '{:?}';
    • std: реорганизованы механизмы сравнения и проверки на равенство trait-ов;
    • std: 'rand' перемещен в 'librand';
    • std: 'to_{lower,upper}case' реализован для 'char';
    • std: функциональность логгирования перенесена в 'liblog';
    • collections: 'HashMap' переписана для увеличения производительности и уменьшения потребления памяти;
    • native: в качестве рантайма по умолчанию используется 'libnative'. 'libgreen' доступен для загрузки вручную, подробнее в документации;
    • native: реализована весь I/O функционал, за исключением сигналов;
    • green: оптимизировано создание task-ов в 'libgreen';
    • green: task-и, создаваемые через 'libgreen' используют unmapped guard page;
    • sync: модуль 'extra::sunc' был обновлен на современный rust, перемещен в библиотеку 'sync';
    • sync: добавлен новый тип 'Barrier';
    • sync: реализованы эффективные мьютексы для нативных и зеленых task-ов;
    • serialize: улучшен модуль 'base64';
    • fourcc: добавлен макрос 'fourcc!';
    • hexfloat: реализован макрос 'hexfloat!';
  • Инструментарий
    • 'rustpkg' объявлен устаревшим и удален из основного репозитория. Его замена ('cargo') в разработке;
    • доступны ночные сборки;
    • значительно улучшено использование памяти 'rustc';
    • отключена поддержка rpath для rustc в процессе сборки;
    • улучшен механизм кодогенерации;
    • восстановлена совместимость debuginfo с lldb на OSX;
    • флаги вывода централизованы в один флаг '--emit';
    • флаги crate типов централизованы в один флаг '--crate-type';
    • флаги кодогенерации объединены через флаг '-C';
    • улучшены сообщения об ошибках возникающих при линковке с устаревшими crates;
    • сообщения об ошибках с временем жизни теперь часто показывают как объявить функцию чтобы исправить ошибки;
    • значительно расширена документация;
    • улучшения в 'rustdoc':
      • подсветка синтаксиса и блоки кода;
      • генерация standalone markdown файлов;
      • флаг '--test' проверяет все блоки кода по умолчанию;
      • отображение экспортированных макросов;
      • reexported типы имеют встроенную документацию в месте первого reexport;
      • результаты работы по поиску в crate-ах теперь генерируется в выходную директорию.

>>> Подробности

★★★★★

Проверено: JB ()

Ответ на: комментарий от anonymous

А я про то и говорю, что одинаковый.

Тогда кто и зачем будет изобретать libuv? Люди будут писать на стандартном Rust и выбирать тот рантайм, который им подходит.

Надеюсь, что в каком-то виде поддержка асинхронного ввода-вывода появится до того, как 1.0 вылупится

Не припомню в rust-dev@ особых планов относительно асинхронности. Насколько я понимаю, в Rust принята модель Erlang - куча дешевых блокирующихся процессов (задач Rust).

tailgunner ★★★★★ ()
Ответ на: комментарий от anonymous

на фоне Go Rust выглядит несостоятельно

А Go уже запускается на микроконтроллере? Да хотя бы на bare iron? Модули ядра на нем уже пишут?

tailgunner ★★★★★ ()
Ответ на: комментарий от tailgunner

в Rust принята модель Erlang - куча дешевых блокирующихся процессов (задач Rust)

А процессы насколько дешёвые остались? Они же выпилили segmented stacks, значит как минимум по потреблению памяти libgreen нифига не green выходит.

anonymous ()
Ответ на: комментарий от tailgunner

А Go уже запускается на микроконтроллере?

Да кому это нужно. Ну ок, во всяком случае не мне

Модули ядра на нем уже пишут?

Пишут

anonymous ()
Ответ на: комментарий от Manhunt

Эти идеи сами по себе не связаны с ООП. А то у тебя и в Haskell ООП появится с таким подходом. ООП бывает, очень грубо говоря, двух видов - с наследованием(или множественным или одиночным, разбавленным интерфейсами с миксинами) и с прототипами. Разницу между статическими и динамическими подходами к проверке типизации в данном случае можно опустить. То, что почти в любом языке можно писать в ОО-стиле не означает, что ООП поддерживается в языке или, тем более, что язык является ОО.

anonymous ()
Ответ на: комментарий от Manhunt

golang.org/doc/faq#Is_Go_an_object-oriented_language

Rust чем-то сильно отличается в этом плане от Go? Кстати, в документации по rust не нашёл ничего про ООП. Наверное, плохо искал.

anonymous ()
Ответ на: комментарий от Manhunt

static.rust-lang.org/doc/0.10/complement-lang-faq.html#is-it-oo?-how-do-i-do-this-thing-i-normally-do-in-an-oo-language?

0.3 Is it OO? How do I do this thing I normally do in an OO language?

It is multi-paradigm. Not everything is shoe-horned into a single abstraction. Many things you can do in OO languages you can do in Rust, but not everything, and not always using the same abstraction you're accustomed to.

Ещё вопросы?

anonymous ()
Ответ на: комментарий от tailgunner

Я знал, что плюсовики в конце концов скажут «хотим Тьюринг-полные шаблоны».

Причём сдесь Тьюринг-полнота? Все те извращения (как бы «метапрограммирование»), что на шаблонах делают, в идеале делать лучше на специальном инструменте - (нормальных) макросах. Правда не знаю, что из себя они в Расте представляют.

Я несколько про другое. В С# (и джаве, вроде) в генериках можно писать код, который должен быть валиден для ВСЕХ типов. В С++ - нет, в итоге обобщённое программирование гораздо удобнее.

Но нужно быть до конца честными: «Хотим всё, как в Си++, только лучше» %)

Не отказался бы. Впрочем, вариант «совсем не так, но не хуже» тоже подходит.

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

DarkEld3r ★★★★★ ()
Ответ на: комментарий от ozkriff

Если ты в обобщенной функции хочешь использовать какой-то метод для объекта типа T, ты ты должен указать трэйт с таким методом (Shape, в данном случае).

То есть подсунуть в метод «что-то» с таким методом, но без данного трейта не получится?

В С++ можно и в этом есть свои преимущества. В D можно даже именно наличие метода проверять. Чем подход раста отличается от обычных интерфейсов мне не очень понятно.

Чего плохого в отсылках к документации?

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

DarkEld3r ★★★★★ ()
Ответ на: комментарий от anonymous

It is multi-paradigm. Not everything is shoe-horned into a single abstraction. Many things you can do in OO languages you can do in Rust, but not everything, and not always using the same abstraction you're accustomed to.

Ещё вопросы?

Ага. Вот посмотри, что тут пишут: http://stackoverflow.com/questions/3498730/why-is-c-not-an-object-oriented-la...

C++ is usually considered a «multi-paradigm» language. That is, you can use it for object-oriented, procedural, and even functional programming. It is certainly true that C++ isn't OO to the same extent as Smalltalk, Ruby, Self, etc. are, but it is definitely an effective OO language by most standards.

Так что оба языка отступают от канонов фанатичного труЪ ООП. И Rust в плане поддержки ООП ничуть не хуже C++: в нём есть все средства и сахар для того, чтобы писать программы в терминах объектов.

Manhunt ★★★★★ ()
Ответ на: комментарий от anonymous

Так что оба языка отступают от канонов фанатичного труЪ ООП

Ну это просто частное мнение. У C++ есть явная поддержка ООП

Это «частное мнение» разделяет и сам создатель языка С++ — Бьёрн Страуструп. Например, вот тут он явно противопоставляет «True OO» и «C++»: http://www.youtube.com/watch?v=YQs6IC-vgmo#t=390

Manhunt ★★★★★ ()
Последнее исправление: Manhunt (всего исправлений: 1)
Ответ на: комментарий от anonymous

А Go уже запускается на микроконтроллере?

Да кому это нужно

Значит, не запускается.

Модули ядра на нем уже пишут?

Пишут

Пруфлинк?

tailgunner ★★★★★ ()
Ответ на: комментарий от anonymous

Они же выпилили segmented stacks, значит как минимум по потреблению памяти libgreen нифига не green выходит.

Смотря насколько green является Ъ-green. Насколько я понял, выпиливание (возможно, временное) сегментированных стеков только увеличивает начальный размер стека в несколько раз (с сотен байт до страницы). Накладные расходы ядра на green task не увеличились.

tailgunner ★★★★★ ()
Ответ на: комментарий от DarkEld3r

В С# (и джаве, вроде) в генериках можно писать код, который должен быть валиден для ВСЕХ типов

Ы? Имеется в виду SFINAE или что?

tailgunner ★★★★★ ()
Ответ на: комментарий от tailgunner

(с сотен байт до страницы)

Пока страница 4KB, это ещё нормально. Но уже сейчас на серверах с очень много RAM HugePages используют, дабы TLB не насиловать. Там уже страница 2MB. Как дела в Windows и OS X обстоят я не знаю, не интересовался никогда. Получается, что в настоящий момент libgreen очень сильно завязан не только на ОС, но ещё и на особенности настройки этой ОС. libnative — это хорошо и правильно. Но мне лично очень хотелось бы, чтобы Rust мог работать как статически типизированный Erlang, ещё и без VM работающий. А они ещё возьмут и вообще M:N модель выпилят :)

anonymous ()
Ответ на: комментарий от nanoolinux

Да что ты говоришь. А в Red Hat не знали, и в RHEL 6 Transparent Huge Pages есть. Другой вопрос в том, что есть проблемы с производительностью в том же Oracle и есть рекомендация настраивать huge pages вручную. Однако вектор движения ясен. 4KB для текущих объёмов RAM _уже_ мало, в будущем TLB вообще колом встанет со страницами такого размера.

И как это отменяет тот факт, что libgreen очень сильно завязан на особенности ОС? Не должно быть этого.

anonymous ()
Ответ на: комментарий от anonymous

в RHEL 6 Transparent Huge Pages есть

И их можно использовать для того, чтобы стеки нитей росли сразу на 2М? %)

И как это отменяет тот факт, что libgreen очень сильно завязан на особенности ОС?

А с каких пор это стало фактом?

tailgunner ★★★★★ ()
Ответ на: комментарий от tailgunner

И их можно использовать для того, чтобы стеки нитей росли сразу на 2М? %)

Это было ответом на то, что без поддержки со стороны софта huge pages вообще никак нельзя задействовать. Можно, но работает оно пока что хреново :P

А с каких пор это стало фактом?

С тех пор, как в Rust решили всё спихнуть на ОС, которая пусть сама страницами рулит? При странице в 4KB и в 2MB можно таки разное число задач заспаунить при такой схеме, какими бы лёгкими сами задачи ни были. Это уже особенность, зависящая от конкретной настройки конкретной ОС.

anonymous ()
Ответ на: комментарий от anonymous

При странице в 4KB и в 2MB

Под кроватью нет монстров. Монстры существуют, кровать есть, а вот монстров под ней нет.

tailgunner ★★★★★ ()
Ответ на: комментарий от Manhunt

Ты вырываешь из контекста. Открой его книги по C++ и сам все поймешь :) Тут же он с теоретиками спорит.

anonymous ()
Ответ на: комментарий от tailgunner

Ы? Имеется в виду SFINAE или что?

Имеется в виду, что если нужных «constraint»-ов не завезли, то облом. Например, «+» в генерике не вызвать.

DarkEld3r ★★★★★ ()
Ответ на: комментарий от DarkEld3r

если нужных «constraint»-ов не завезли, то облом. Например, «+» в генерике не вызвать

А Си++ умеет волшебным образом находить «+»? В общем, пример бы.

tailgunner ★★★★★ ()
Ответ на: комментарий от tailgunner

А Си++ умеет волшебным образом находить «+»?

Шаблоны раскрываются на этапе компиляции (думаю ты это и так знаешь), соответственно когда типы подставляются, то да - компилятор может посмотреть есть ли для них плюс. Если нет, то будет ошибка компиляции. В случае вложенных шаблонов ошибка будет многословная - за это С++ часто ругают.

Явные ограничения (контракты) часто были бы удобны (может и будут).

В С# следующее просто не скомпилится. «Потому что нельзя».

static T generic_add<T>(T a, T b)
{
  return a + b;
}

Ну и просто список ограничений генериков можно посмотреть.

DarkEld3r ★★★★★ ()
Ответ на: комментарий от DarkEld3r

Мне вопрос про дженерики в Ржавчине и шаблоны в С++ чем-то напоминает древние срачи про неконтролируемое использование goto vs нормальное структурное программирование.

ozkriff ()
Ответ на: комментарий от ozkriff

Мне вопрос про дженерики в Ржавчине и шаблоны в С++ чем-то напоминает древние срачи про неконтролируемое использование goto vs нормальное структурное программирование.

это было бы так, если б шаблоны С++ не были бы таки более продвинутыми, вот, например, есть ли в rust аналог variadic templates?

wota ★★ ()
Ответ на: комментарий от wota

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

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

ozkriff ()
Ответ на: комментарий от ozkriff

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

так это же описание goto ;)

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

ну вот, например, мне для тестов нужно было генерировать бинарное представление произвольных данных, завел такой класс (убрал «лишний» код для примера):

/**********************************************************************************************/
struct blob_factory
{
    template<class... Args>
    blob_factory( Args... tail )
    {
        add( tail... );
    }

    template<class T>
    void add( T value )
    {
        size_t sz = buf_.size();
        buf_.resize( sz + sizeof(T) );

        *((T*) &buf_[ sz ]) = value;
    }

    void add( item_type t )
    {
        buf_.push_back( (char) t );
    }

    void add( const char* value )
    {
        while( *value )
            buf_.push_back( *value++ );
    }

    void add( const char16_t* value )
    {
        while( *value )
            add( *value++ );
    }

    template<class T, class... Args>
    void add(
        T       value,
        Args... tail )
    {
        add( value );
        add( tail... );
    }

    std::vector<char> buf_;
};

использую так:

blob_factory(
    '\0',
    item_type::object,
        int32_t( 4 ), u"benv",
        int32_t( 3 ), u"bdc",
        item_type::list, int32_t( 2 ),
            item_type::boolean, (char) false,
            item_type::integer, int64_t( 1 ) )

покажи пример на макросах rust, ну или без них

wota ★★ ()
Последнее исправление: wota (всего исправлений: 1)

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

anonymous ()
Ответ на: комментарий от wota

Хм, т.е. нужен серелизатор в бинарный формат? Есть пример для ebml, но он несколько громосткий (стандартная бмлиотека, все-таки, а не домашний костыль): https://github.com/mozilla/rust/blob/master/src/libserialize/ebml.rs

Вызывается так же, как json-серелизатор: http://static.rust-lang.org/doc/master/serialize/json/index.html#using-autose...

ozkriff ()
Ответ на: комментарий от wota

Если тебе интересно, то как будет время, попробую расковырять libserialize/ebml.rs и написать чего-то копактное и более близкое к твоему коду на плюсах.

ozkriff ()
Ответ на: комментарий от ozkriff

Хм, т.е. нужен серелизатор в бинарный формат?

а как на rust будет выглядеть вызов:

blob_factory(
    '\0',
    item_type::object,
        int32_t( 4 ), u"benv",
        int32_t( 3 ), u"bdc",
        item_type::list, int32_t( 2 ),
            item_type::boolean, (char) false,
            item_type::integer, int64_t( 1 ) )

?

wota ★★ ()

И на этом кусочке фекали пишут этот ваш servo… Сильные ребята.

Если этот язчишка о чём-то и говорит, то ни о чём.

anonymous ()
Ответ на: комментарий от wota

Допустим, вот такой вариант:

$ cat test.rs
#![feature(macro_rules)]
#![feature(phase)]

trait ToBin {
    fn to_bin(&self, v: &mut Vec<u8>);
}

impl ToBin for u8 {
    fn to_bin(&self, v: &mut Vec<u8>) {
        v.push(*self);
    }
}

impl ToBin for char {
    fn to_bin(&self, v: &mut Vec<u8>) {
        v.push(*self as u8);
    }
}

impl<'a> ToBin for &'a [u8] {
    fn to_bin(&self, v: &mut Vec<u8>) {
        for c in self.iter() {
            v.push(*c as u8);
        }
    }
}

impl<'a> ToBin for &'a str {
    fn to_bin(&self, v: &mut Vec<u8>) {
        for c in self.as_bytes().iter() {
            v.push(*c as u8);
        }
    }
}

macro_rules! to_blob(
    ($($obj:expr),*) => ({
        let mut v = Vec::new();
        $($obj.to_bin(&mut v);)*
        v
    })
)

fn main() {
    {
        let mut v = Vec::new();
        0u8.to_bin(&mut v);
        'a'.to_bin(&mut v);
        "abcABC".to_bin(&mut v);
        [4, 0, 4].to_bin(&mut v);
        println!("1: {}", v);
    }
    {
        let v = to_blob!(
            0, 'a', "abcABC", [4, 0, 4]);
        println!("2: {}", v);
    }
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
$ rustc test.rs && ./test
1: [0, 97, 97, 98, 99, 65, 66, 67, 4, 0, 4]
2: [0, 97, 97, 98, 99, 65, 66, 67, 4, 0, 4]
$ 
ozkriff ()
Ответ на: комментарий от ozkriff

?

Ну а в шарп не завезли «трейты» для арифметических операций. И тут дело в том, что в С++ тебе они и не нужны. Точно так же как с обычным полиморфизмом - функция ожидает интерфейс и ты передаёшь туда что-то. Если переданный обьект не реализует нужный интерфейс, то просто не скомпилится. И С++ шаблоны ведут себя так же.

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

DarkEld3r ★★★★★ ()
Ответ на: комментарий от DarkEld3r

Я тут, кстати, на статейку наткнулся, которую недавно накидал Брендан Забарускас, который явно намного лучше меня знает Ржавчину:

https://gist.github.com/bjz/9220415#file-cpp-templates-vs-rust-generics-md

ты же ярый противник исключений

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

ozkriff ()
Ответ на: комментарий от wota

Это пример без макроса, а ниже аналогичный пример с макросом to_blob!, который копипасту и скрывает. Или я тебя не понял.

ozkriff ()
Ответ на: комментарий от ozkriff

а ниже аналогичный пример с макросом to_blob!, который копипасту и скрывает

точно, сорри, читаю иногда наискосок и вполглаза, вобщем буду ждать версию rust постабильней, чтоб попробовать

wota ★★ ()
Ответ на: комментарий от ozkriff

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

Отсюда и твое же не понимание разницы концептов и ограничений на дженерик-параметры в расте. Концепты накладывают ограничения на тип, ограничения дженериков в расте - на объект типа. Та же принципиальная разница между концептами и ОО/go интерфейсами.

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

anonymous ()
Ответ на: комментарий от wota

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

anonymous ()
Ответ на: комментарий от ozkriff

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

В чем принципиальная разница между питоновскими и плюсовыми исключениями?

anonymous ()
Ответ на: комментарий от anonymous

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

Дженерики тоже являются «средством генерации». Не таким гибким, но вполне средством.

Концепты накладывают ограничения на тип, ограничения дженериков в расте - на объект типа.

Type bound в Rust- это ограничения именно на тип.

Кстати, дженерики дороговаты для системного языка

Чем же? То, что дженерики умеют, они умеют насктолько же эффективно, насколько и шаблоны.

tailgunner ★★★★★ ()
Ответ на: комментарий от tailgunner

Дженерики тоже являются «средством генерации». Не таким гибким, но вполне средством.

Нет, не являются. Это параметрический полиморфизм. При описании generic-типа задается ровно один тип(поэтому никакой генерации нет), в отличие от шаблонов, где задается именно шаблон типа, по которому компилятор генерирует тип и его составные части(например, в C++ методы шаблонного типа генерируются отдельно, только те, что нужны, а не сразу все при инстанцировании типа).

Type bound в Rust- это ограничения именно на тип.

Только синтаксически. Фактически ты описываешь свойства, связанные с объектом, а не типом. Так, ты не сможешь сказать в bound'е, что тип должен иметь нужный вложенный тип, например. В концептах - можешь.

Чем же? То, что дженерики умеют, они умеют насктолько же эффективно, насколько и шаблоны.

Ссылочностью. По шаблону компилятор создает код для каждого типа, дженерик же работает с ссылкой и пр. В .NET для встроенных типов и структур jit делает тоже самое, кстати. Нативный язык это сделать не сможет, а llvm о дженериках ничего не знает.

anonymous ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.