Хаскель мне нравится, но не вижу причин отказываться от zero cost абстракций, возвращать GC и в целом отказываться от производительности, ограничивая диапазон применений языка
Вот пример из C++ my_func(std::move(s)); my_func(std::move(s)); Тут так же можно задать вопрос: почему переменная сгорает? В C++ кстати, это просто скорее всего приведёт к багу, так как мы будем использовать объект после его мува. Раст же честно скажет: тут что-то не так с кодом, может тебе нужно значение скопировать/склонировать?
Что касается копирования, да, в C++ можно написать так my_func(s); my_func(s); и это будет работать. Только этот код будет неявно копировать весь s. А что если s это какой-то сложный объект? Например строка, что аллоцируется в куче? Тогда придётся всю строку переаллоцировать - это вносит в код нетривиальные и неожиданные расходы. В расте это поведение просто явное: хочешь расходы на копирование строки? Хорошо, напиши это явно: my_func(s.clone()); my_func(s);
В целом это обычная мув семантика, ничего сверхсложного тут нет. Опять же, хочешь ссылки - передаёшь по ссылке
Язык который не позволяет сделать простые вещи просто - тупиковая ветвь
Согласен. Но было бы неплохо побольше примеров, какие именно простые вещи в расте сложно реализуются
Раст для меня всегда был как раз таким языком, когда можно простое сделать просто. Например вместо того чтобы городить полиморфизм через наследование и писать кучу абстракций, я пишу один простой enum со всеми нужными вариантами и данными и работаю с ним. Или вместо того чтобы создавать полноценный тип который делает какую-то полезную работу, просто пишу функцию. Вместо того чтобы сложно менеджить приватность полей, прописывать friend мемберы, просто обращаюсь к чему надо напрямую в рамках модуля. В расте нет наследования, что так же упрощает код и не позволяет нагромождать кучу абстракций ради абстракций - вместо этого используешь что-то по-проще вроде композиции. В расте нет разделения на struct/class (как в C#) или на типы значения/ссылочные типы - вместо этого есть просто тип. Нужно на хипе аллокнуть? Ок - создаёшь Box и готово. Хочешь статик полиморфизм? Юзаешь просто женерик и всё. Хочешь динамик? Создаёшь dyn и готово. Хочешь Option? Сделай, а не как обычно когда нужно наоборот следить чтобы null/None нигде не было. Опять же, упрощает код там, где None не нужен - убирает лишние проверки. В итоге как раз и получается что ты делаешь именно то, что нужно и минимально думаешь о второстепеных вещах
Да, какие-то вещи в расте действительно могут на первый взгляд быть сложными. Те же лайфтаймы и борроу чеккеры. Опять же, с опытом в них ничего концептуально сложного нет. Обычно я представляю себе что и откуда заимствуется, со временем даже научился давать лайфтаймам осмысленные имена. В целом, процесс мышления такой же как и при работе с указателями в Си. Только своё мышление, что и откуда заимствуется, ты должен рассказать компилятору
Раст печально известен своим сложным асинком. Но асинк замыкания это настоящий геймченджер, с ними писать асинк код намного проще и вообще не нужно иметь дел с лайфтаймами, боксингом и всяческими хаками в духе `move || { state.clone(); async move { state.await } }` - которые к тому же менее оптимально работают. Теперь же всё просто и работает при этом максимально эффективно - прекрасное решение в духе самого раста
Легко быть фаном того, что отлично работает. Вот чтобы быть преданным фаном плюсов и старательно игнорировать раст - вот тут уже по истине нужно быть фанатичным
Хорошо. Какая там сигнатура у
my_func
будет?Как объявить
my_func(s)
чтобы s всегда автоматически мувалась?Хаскель мне нравится, но не вижу причин отказываться от zero cost абстракций, возвращать GC и в целом отказываться от производительности, ограничивая диапазон применений языка
Вот пример из C++
my_func(std::move(s)); my_func(std::move(s));
Тут так же можно задать вопрос: почему переменная сгорает?
В C++ кстати, это просто скорее всего приведёт к багу, так как мы будем использовать объект после его мува. Раст же честно скажет: тут что-то не так с кодом, может тебе нужно значение скопировать/склонировать?
Что касается копирования, да, в C++ можно написать так
my_func(s); my_func(s);
и это будет работать. Только этот код будет неявно копировать весь s. А что если s это какой-то сложный объект? Например строка, что аллоцируется в куче? Тогда придётся всю строку переаллоцировать - это вносит в код нетривиальные и неожиданные расходы. В расте это поведение просто явное: хочешь расходы на копирование строки? Хорошо, напиши это явно:my_func(s.clone()); my_func(s);
В целом это обычная мув семантика, ничего сверхсложного тут нет. Опять же, хочешь ссылки - передаёшь по ссылке
Как насчёт
dbg!(myvar)
?Согласен. Но было бы неплохо побольше примеров, какие именно простые вещи в расте сложно реализуются
Раст для меня всегда был как раз таким языком, когда можно простое сделать просто. Например вместо того чтобы городить полиморфизм через наследование и писать кучу абстракций, я пишу один простой enum со всеми нужными вариантами и данными и работаю с ним. Или вместо того чтобы создавать полноценный тип который делает какую-то полезную работу, просто пишу функцию. Вместо того чтобы сложно менеджить приватность полей, прописывать friend мемберы, просто обращаюсь к чему надо напрямую в рамках модуля. В расте нет наследования, что так же упрощает код и не позволяет нагромождать кучу абстракций ради абстракций - вместо этого используешь что-то по-проще вроде композиции. В расте нет разделения на struct/class (как в C#) или на типы значения/ссылочные типы - вместо этого есть просто тип. Нужно на хипе аллокнуть? Ок - создаёшь Box и готово. Хочешь статик полиморфизм? Юзаешь просто женерик и всё. Хочешь динамик? Создаёшь dyn и готово. Хочешь Option? Сделай, а не как обычно когда нужно наоборот следить чтобы null/None нигде не было. Опять же, упрощает код там, где None не нужен - убирает лишние проверки. В итоге как раз и получается что ты делаешь именно то, что нужно и минимально думаешь о второстепеных вещах
Да, какие-то вещи в расте действительно могут на первый взгляд быть сложными. Те же лайфтаймы и борроу чеккеры. Опять же, с опытом в них ничего концептуально сложного нет. Обычно я представляю себе что и откуда заимствуется, со временем даже научился давать лайфтаймам осмысленные имена. В целом, процесс мышления такой же как и при работе с указателями в Си. Только своё мышление, что и откуда заимствуется, ты должен рассказать компилятору
Раст печально известен своим сложным асинком. Но асинк замыкания это настоящий геймченджер, с ними писать асинк код намного проще и вообще не нужно иметь дел с лайфтаймами, боксингом и всяческими хаками в духе `move || { state.clone(); async move { state.await } }` - которые к тому же менее оптимально работают. Теперь же всё просто и работает при этом максимально эффективно - прекрасное решение в духе самого раста
Зачем тут вообще два или более потока?
Проверил, отлично работает. tokio тут в зависимости вообще не нужен. У автора кривые руки, лучше бы на Го писал
Легко быть фаном того, что отлично работает. Вот чтобы быть преданным фаном плюсов и старательно игнорировать раст - вот тут уже по истине нужно быть фанатичным