Состоялся (http://blog.rust-lang.org/2016/04/14/Rust-1.8.html) релиз языка программирования Rust 1.8 (http://www.rust-lang.org), развиваемого проектом Mozilla, обеспечивающего автоматическое управление памятью и предоставляющего средства для высокого параллелизма выполнения заданий, при этом обходясь без использования сборщика мусора и runtime. Параллельно с Rust совместно с компанией Samsung развивается экспериментальный браузерный движок Servo (https://www.opennet.me/opennews/art.shtml?num=36576), написанный (https://github.com/servo/servo/) на языке Rust и отличающийся поддержкой многопоточного рендеринга web-страниц и распараллеливанием операций с DOM (Document Object Model).В состав нового выпуска принято более 1400 изменений, из которых выделяется два улучшения языка. Первым улучшением языка является возможность (https://github.com/rust-lang/rfcs/blob/master/text/0953-op-a... перегрузки операторов (https://ru.wikipedia.org/wiki/%D0%9F%D0%... присвоения, таких как "+=" и "-=", что позволяет адаптировать их для манипуляции со сложными структурами данных, например, организовать суммирование элементов ассоциативных массивов. Второе изменение в языке связано с определением структур, не содержащих полей, выражение "struct Bar { }" теперь не приводит к выводу ошибки.
Из других улучшений отмечается перевод в разряд стабильных около 20 функций и методов (https://github.com/rust-lang/rust/blob/stable/RELEASES.md#li... в основном связанных с обработкой строк UTF-16, работой со временем и перегрузкой операторов. Кроме того, представлена начальная реализация новой системы сборки, написанной на языке Rust и основанной на пакетном менеджере Cargo, который уже давно применяется для сборки программ на языке Rust. Что касается самого Cargo, то в нём представлено несколько новых команд: "cargo init" для запуска проекта в текущей директории (без создания поддиректории как в "cargo new") и "cargo metadata" для извлечения метаданных о проекте. На платформах Linux и BSD добавлена (https://github.com/rust-lang/rust/pull/30859) защита от исполнения кода в стеке.Напомним, что язык Rust сфокусирован на безопасной работе с памятью и обеспечении высокого параллелизма выполнения заданий. При этом Rust обходится без использования сборщика мусора или runtime, что делает возможным создания на Rust библиотек, которые могут выступать в роли прозрачной замены библиотекам для языка Си. Для распространения библиотек на языке Rust, обеспечения сборки и управления зависимостями проектом развивается пакетный менеджер Cargo (http://blog.rust-lang.org/2014/11/20/Cargo.html), позволяющий получить нужные для программы библиотеки в один клик. Для размещения библиотек введён в строй репозиторий crates.io (https://crates.io/).
По структуре язык Rust напоминает C++, но существенно отличается в некоторых деталях реализации синтаксиса и семантики. Автоматическое управление памятью избавляет разработчика от манипулирования указателями и защищает от проблем, возникающих из-за низкоуровневой работы с памятью, таких как обращение к области памяти после её освобождения, разыменование нулевых указателей, выход за границы буфера и т.п. Rust поддерживает смесь императивных процедурных и объектно-ориентированных методов с такими парадигмами, как функциональное программирование и модель акторов, а также обобщённое программирование и метапрограммирование, в статических и динамических стилях.
URL: http://blog.rust-lang.org/2016/04/14/Rust-1.8.html
Новость: http://www.opennet.me/opennews/art.shtml?num=44251
а зачем нужна пустая структура?
Черт с ней со структурой, есть у кого-нибудь хорошая статейка про раст? почитать, повникать?
Книга есть: https://rurust.github.io/rust_book_ru/
ну в Го, например, пустая структура самый эффективный по памяти превращения мапа в сет.
Ну, в некотором роде - это конструктор типа, который нужен исключительно для того, чтобы пометить некоторое состояние объекта.Вот например в Ocaml можно написать нечто вроде:
# type 'a list = Null | Pair of ('a * 'a list);;И после этого писать определения вида:
# let l1 = Null;;
val l1 : 'a list = Null
# let l2 = Pair (42, Null);;
val l2 : int list = Pair (42, Null)Null - это состояние объекта с типом 'a list, которое характеризует список, как пустой. Это удобно, этим пользуются постоянно.
Haskell тоже этим хорош.
Для обобщённого программирования - крайне нужная вещь, например.
> а зачем нужна пустая структура?При криворуком проектировании ее наследовать потом удобно.
Зачем они перегрузку операторов ввели... Это же код запутывает так, что потом не найти где это было перекрыто
Чем он запутывает? Сложить два числа 1 + 2. Сложить два вектора vec![1, 2] + vec![3, 4, 5];
Тем, что перегрузка операторов - это нарушение системы типов.Во-первых, в конце концов это приведёт к тому, что программист уже не сможет быть уверен в том, какой именно экземпляр функции, реализующей оператор, будет вызван.
Во-вторых это делает реализацию системы вывода типов практически невозможной.
> перегрузка операторов - это нарушение системы типов.
> Во-вторых это делает реализацию системы вывода типов практически невозможной.Только в случае с модной "утиной" типизацией. И то - под вопросом "почему ж нет?".
В например Swift решены все проблемы с "программист уже не сможет быть уверен в том, какой именно экземпляр функции, реализующей оператор, будет вызван". Так что это проблемы реализации.
То-то в плюсах типы выводятся. А не уверен, что вызывается - спроси IDE.
> То-то в плюсах типы выводятся. А не уверен, что вызывается - спроси IDE.В том-то и дело, что не выводятся. Программист всё ещё обязан указывать типы параметров при определении функций. Всё, что там сделано для вывода типов - это возможность в некоторых исключительных случаях автоматически предположить, какое значение функция возвращает. То же самое и в Scala, например. И именуют они это "выводом типов", однако до тех пор, пока у них не будет нормального Хиндли-Милнера, говорить не о чем.
Программист может быть уверен, что будет вызван метод реализации трейта для типа, к экземплярам которого применён оператор.
А с точки зрения вывода типов оператор не отличается от любой другой функции.
> Программист может быть уверен, что будет вызван метод реализации трейта для типа, к экземплярам которого применён оператор.Да, да, да. И в конце концов получается, что трём переменным, принадлежащим одному классу, подмешали разные трейты. И поэтому один и тот же метод у этих трёх объектов выполняет разные вещи, хотя выглядят вызовы абсолютно одинакого.
> А с точки зрения вывода типов оператор не отличается от любой другой функции.
Не любой оператор. Вот and или or Вы в виде функции не сможете представить.
компилятор в RUSTe один из самых жестких, с которыми я работал.
например для vec![1, 2] + vec![3, 4, 5];
Т.е развернув синтак.й сахар компилер увидит что складываются два инстанса структуры (Vec<i32>), с реализованной перегрузкой операторов сложения и сделает конкат, в чем проблема? т.е всё будет проверенно на этапе компиляции
>> vec![1, 2] + vec![3, 4, 5]С каких пор тип Vec стал реализовывать trait Add?
Если проблемы с фантазией, представь что он имплементит под Add конкатенацию
> Если проблемы с фантазией, представь что он имплементит под Add конкатенациюПроблемы начинаются когда не можешь с разбегу вспомнить что такое в данном конкретном исходном файле для данного конкретного типа означает "+=".
При этом сильно не факт что из-за автоматического приведения типов и многоэтажного наследования можно выхватить ошибку компиляции, зато на подобной автоматике можно встать в жыр обеими ногами по пояс.
А что если ты "с разбегу" не помнишь "что у конкретного типа делает метод doIncrement?",
т.е что же он конкретно делает внутри, не понятно и по очевидной логике нужно пойти в исходник и посмотреть!Точно так же в RUST можно в модуле откуда пришла такая-то структура(тип/класс), посмотреть в исходнике где у него имплементится AddAssign и посмотреть саму функциональность метода:
impl AddAssign for Foo {
fn add_assign(&mut self, _rhs: Foo) {
...http://doc.rust-lang.org/nightly/std/ops/trait.AddAssign.html
Да, компилятор-то увидит. Однако вывод типов нужен прежде всего программисту, а не компилатору.Вот я пишу например:
# let add1 x = x + 1;;И когда я смотрю на это определение, я точно знаю, что add1 - это функция int -> int, потому что функция (+) имеет именно такой тип. И я уверен по этой же самой причине, что x - это int, потому что параметр иного типа не может быть передан в (+).
А если функция (+) может быть перегружена, то я ни в чём не могу быть уверен, и чтобы не ошибиться, мне в каждом конкретном случае использования add1, получается, придётся либо компилировать программу, чтобы посмотреть, всё ли корректно работает, либо прибегать к помощи специализированной IDE (а я могу, вообще говоря, хотеть работать в привычном мне текстовом редакторе).
ты и сейчас в vim-e можешь посмотреть что же всё таки имплементит конкретная структура, с которой ты работаешь.это опять же мне напоминает: почему же некоторое доверяют реализации метода, у которого и название порой не отражает всю суть его действия (т.е они "хотят проверить" метод/его реализацию), и не хотят проверять реализацию метода перегрузки оператора для конкретной структуры!? в чем разница?
http://www.opennet.me/openforum/vsluhforumID3/107586.html#42
http://www.opennet.me/openforum/vsluhforumID3/107586.html#59struct Point {
x: i32,
y: i32,
}impl Add for Point {
type Output = Point;fn add(self, other: Point) -> Point {
Point {x: self.x + other.x, y: self.y + other.y}
}
...Point {x: 1, y: 0} + Point {x: 2, y: 3}
здесь всё с примерами:
https://doc.rust-lang.org/nightly/std/ops/
Что бы тебе было яснее, по поводу твоего страха о изменении поведения сложения примитивных типов, то в руст такое невозможно:ссылка на пример play.rust-lang.org:
http://is.gd/hZuJL3
https://doc.rust-lang.org/error-index.html#E0117Если же это не примтив, то ты уже должен понимать как работает такая-то структура! и не важно, совершается ли какое-либо действие через метод или перегруженный оператор!
А про твое утверждение что что бы проверить поведение при перегрузке тебе нужно что-то компилировать, ты опять же ошибаешься, ты, опять же в vim-e/emacs/ручками в файле/ можешь посмотреть ДО КОМПИЛЯЦИИ реализацию перегрузки оператора у конкретной структуры (точно так же как если бы это был метод)!
> Что бы тебе было яснееХамить заканчивайте.
> по поводу твоего страха о изменении поведения сложения *примитивных* типов
Когда это он у меня появился? Я-то почему не в курсе?
> Если же это не примтив, то ты уже должен понимать как работает такая-то структура!
Ну вот и начинается, о чём я и говорил. Вот стоит у тебя "a + b". Обе переменные были получены как результат, возвращённый из другой функции. Короче, на выяснение типа руками уйдёт много времени. Если допустить, что "+" может быть перегружен, то какую именно реализацию ты должен посмотреть?
> и не важно, совершается ли какое-либо действие через метод или перегруженный оператор!
Да что вы прицепились к этому вашему любимому различию между именованием функций буквами и мат.символами? Об этом не было речи вообще. И всё подряд методами называете зачем-то. ООП - это не весь мир. И перегрузка операторов работает не только для объектов, даже в том же C++.
> А про твое утверждение что что бы проверить поведение при перегрузке тебе
> нужно что-то компилировать, ты опять же ошибаешься, ты, опять же в
> vim-e/emacs/ручками в файле/ можешь посмотреть ДО КОМПИЛЯЦИИ реализацию перегрузки оператора
> у конкретной структуры (точно так же как если бы это был
> метод)!В Emacs и Vim встроены синтаксические анализаторы, так что это считай полноценные IDE.
Но вот... Ручками в файле? Ты серьёзно? В случае перегрузки оператора, как в вышеописанном примере, не поймёшь, где смотреть, потратишь много времени.
"хамство" - это видимо попытка объяснить оппоненту который уперся в своих домыслах, без конкретных аргументов, и даже не помнит что сам говорил/писал ранее:>>freehck: А если функция (+) может быть перегружена, то я ни в чём не могу быть уверен, и чтобы не ошибиться, мне в каждом конкретном случае использования add1, получается, придётся либо компилировать программу, чтобы посмотреть, всё ли корректно работает, либо прибегать к помощи специализированной IDE (а я могу, вообще говоря, хотеть работать в привычном мне текстовом редакторе).
>>freehck: В Emacs и Vim встроены синтаксические анализаторы, так что это считай полноценные IDE.
>>freehck: Но вот... Ручками в файле? Ты серьёзно?Тут видимо было бы лишне продолжать что-то объяснять... текстовый редактор без "синтаксического анализатора", в котором оппонент хочет работать - windows notepad.exe ?
Думаю.. очень показательно будет то как Вы смотрите реализации методов/функций сторонних классов/модулей в вашем "текстовом редакторе"?Отвечая на вопрос, да, я вполне серьезно, если требуется найти имплементацию перегрузки оператора для структуры(класса) в RUST, это можно сделать в одну строку через find/grep "impl Add for Point", соответственно будет видны аргументы и возвращаемый тип:
http://www.opennet.me/openforum/vsluhforumID3/107586.html#66
>>> по поводу твоего страха о изменении поведения сложения *примитивных* типов
>>>freehck: Когда это он у меня появился? Я-то почему не в курсе?
>>>freehck: А если функция (+) может быть перегружена, то я ни в чём не могу быть уверен
>>> и не важно, совершается ли какое-либо действие через метод или перегруженный оператор!
>>>freehck: Да что вы прицепились к этому вашему любимому различию между именованием функций буквами и мат.символами? Об этом не было речи вообще. И всё подряд методами называете зачем-то. ООП - это не весь мир. И перегрузка операторов работает не только для объектов, даже в том же C++.Тут оппонент видимо уже настолько ушел в спор, что забыл что обсуждается. Обсуждается подход реализованный в RUST, и если это не пустой разговор, хотелось бы обоснованных аргументов, на примере RUST, где по его утверждению "..программист уже не сможет быть уверен в том, какой именно экземпляр функции, реализующей оператор, будет вызван":
http://www.opennet.me/openforum/vsluhforumID3/107586.html#66
>>>> по поводу твоего страха о изменении поведения сложения *примитивных* типов
>>>>freehck: Когда это он у меня появился? Я-то почему не в курсе?
>>>>freehck: А если функция (+) может быть перегружена, то я ни в чём не могу быть уверен
>>>> и не важно, совершается ли какое-либо действие через метод или перегруженный оператор!
>>>>freehck: Да что вы прицепились к этому вашему любимому различию между именованием функций буквами и мат.символами? Об этом не было речи вообще. И всё подряд методами называете зачем-то. ООП - это не весь мир. И перегрузка операторов работает не только для объектов, даже в том же C++.
> Тут оппонент видимо уже настолько ушел в спор, что забыл что обсуждается.А обсуждалось, вопреки далее Вами написанному, то, что возможность перегрузки операторов повлечёт известные проблемы языков с подобным подходом, такие как:
1) Усложнение понимания кода программистом,
2) Невозможность реализовать вывод типов.Посмотрите выше по треду #4 и #10. Про подход Rust к этому делу - ни слова, вопреки тому, что Вы утверждаете:
> Обсуждается подход реализованный в RUST, и если это не пустой разговор,
> хотелось бы обоснованных аргументов, на примере RUST, где по его утверждению
> "..программист уже не сможет быть уверен в том, какой именно экземпляр
> функции, реализующей оператор, будет вызван":
> http://www.opennet.me/openforum/vsluhforumID3/107586.html#66Тем не менее, Ваш пример #66 - ни к селу, ни к городу, по очевидной причине: пока Вы в рамках одного проекта - грепайте на здоровье, но что Вы будете делать функцией, которая была перегружена в стороннем модуле? Что Вы тогда собственно грепать собрались? А ваша IDE может и не подсветить Вам, что, мол, Вы ошибочно применили не ту функцию, потому что шаблон перегруженной функции совпал с каким-то другим. В случае же, если перегрузки нет - Вы наверняка получаете ошибку на этапе компиляции (а скорее всего даже раньше: IDE может Вам и подсветить строчку, предупреждая о неправильном типе).
>>>возможность перегрузки операторов повлечёт известные проблемы языков с подобным подходом, такие как:
>>>1) Усложнение понимания кода программистомНаоборот. У меня на работе один из основных языков Java, и вот как-раз распутывать комбинации методов из BigDecimal add, multiply, subtract,.. кандидат номер один в улучшение читаемости, при наличии перегрузки операторов.
>>>2) Невозможность реализовать вывод типов.
Вообще не вижу связи, пример?
По поводу грепа, в Rust зависимости через cargo приходят в виде исходников, загрузив их, я точно так же могу погрепать реализацию используемого мной struct(класса) - операнда, и раз уж я буду использовать этот операнд я обязательно посмотрю его реализацию в исходном коде, и опять же не важно, будет там просто метод add или определена перегрузка оператора - я посмотрю signature реализации.
По вашему, если будет метод, и в языке не было бы перегрузки оператора, то Вы его не проверяете!? (конечно учитывая ваше желание работать в notepad.exe вполне может быть ваш стиль)
>>>А ваша IDE может и не подсветить Вам, что, мол, Вы ошибочно применили не ту функцию, потому что шаблон перегруженной функции совпал с каким-то другим. В случае же, если перегрузки нет - Вы наверняка получаете ошибку на этапе компиляции (а скорее всего даже раньше: IDE может Вам и подсветить строчку, предупреждая о неправильном типе).
Я вам рекомендую не заниматься пустой демагогией, а попробовать то как это реализовали в RUST, тем более что выше я просто уже скинул конкретные ссылки, где за час не зная RUST, можно понять как это реализовано.
> Наоборот.У. То есть Вы хотите ВЕСЬ этот разговор начать с самого НАЧАЛА?
> У меня на работе один из основных языков Java
Ах, неужели. Хотите верьте, хотите нет, но это кое-что объясняет.
>> 2) Невозможность реализовать вывод типов.
> Вообще не вижу связи, пример?Вот Вы не видите, а Вам тут эту связь разные люди на разный ляд демонстрируют в разных тредах этой новости уже несколько дней как. :/
#62, #79, #35. Mandor тоже вон дело говорит. Что я Вам пытаюсь объяснить - не понимаю, Вы ж ни одного из нас так и не удосужились прочитать...Лично у меня сложилось устойчивое впечатление, что Вы с выводом типов не сталкивались вообще никогда, и даже не представляете, что это такое. Это грустно.
> По вашему, если будет метод, и в языке не было бы перегрузки оператора, то Вы его не проверяете!?
А я не понимаю, что Вы называете методом. Обычно вроде так называют интерфейсы взаимодействия с объектом, но при чём тут объекты, если мы тут говорим о перегрузке функций? Или вы так называете функции, обозначенные буквами? Или всё, что "не оператор"? Вы это слово пихаете вообще без контекста.
Или почему Вы так упорно говрите о "перегрузке оператора", хотя изначально планировалось обсудить перегрузку вообще? Операторы - они какие-то особенные?
Ну и как Вы хотите, чтобы с Вами вели беседу? Я наверое дурак, что вообще ввязался в этот разговор.
> (конечно учитывая ваше желание работать в notepad.exe вполне может быть ваш стиль)...
> Я вам рекомендую не заниматься пустой демагогией...И хамите, хамите, хамите... Как Вы думаете, кому-нибудь нужны рекомендации человека, который даже не в состоянии понять позицию собеседника, но при этом постоянно норовит охаять его? Если кто-то и мог что-либо вынести из этого разговора для себя полезного - то это были Вы. И мне жаль, что я оказался недостаточно усерден.
PS: Мне стоило остановиться на сообщении #80, которое, судя по всему, осталось без должного внимания.
http://www.opennet.me/openforum/vsluhforumID3/107586.html#4Я ещё раз рекомендую посмотреть мои ссылки на документацию реализации этого в RUST, которые можно понять за час, если есть у вас конкретные примеры, покажите примеры где вывод типа будет не возможен!
И да #80 я прочитал, согласен что Аноним писал только про базовые операции с операторами с примитивами, потому и не продолжил.
> http://www.opennet.me/openforum/vsluhforumID3/107586.html#4
> Я ещё раз рекомендую посмотреть мои ссылки на документацию реализации этого в
> RUST, которые можно понять за час, если есть у вас конкретные
> примеры, покажите примеры где вывод типа будет не возможен!Ох. Дорогой Аноним. Система типов Хиндли-Милнера не допускает перегрузки. Это - база. Ну о чём тут ещё говорить?
update: Первый же запрос в гугле:
https://books.google.ru/books?id=x30x9QfoRj8C&pg=PA15&lpg=PA...> И да #80 я прочитал, согласен что Аноним писал только про базовые
> операции с операторами с примитивами, потому и не продолжил.Это хорошо.
И.. как это относится к RUST?
> И.. как это относится к RUST?Так и относится. В Rust ввели возможность перегрузки. Кое-кто расстроился. Его спросили, а чем это плохо. Ответили, что усложняет семантику и нельзя вывод типов. Потом стали почему-то спорить, что вывод типов можно. Вот так сюда и пришли.
> Ох. Дорогой Аноним. Система типов Хиндли-Милнера не допускает перегрузки. Это - база.С другой стороны:
http://rextester.com/MVNH51780
--ghc 8.0.1 /opt/ghc/8.0.1/lib/ghc-8.0.0.20160127/
import Data.Char (ord, chr)
instance Num Char where
a + b = 'Ъ'
a * b = chr $ ord a + ord b
main = print('x' + 'y', 'x' * 'y', 1 + 'y' + 'x' * 3)
('\1066','\241','\1066')
Т.е. хитро извращаться можно и в хаскелле, однако ориентироваться на таких вот хитрых рукопопов все же наверное не стоит.
> Т.е. хитро извращаться можно и в хаскелле, однако ориентироваться на таких вот
> хитрых рукопопов все же наверное не стоит.В Haskell числа имеют тип Num a. Вся соль в том, что тут мы доопределяем функцию, не изменяя её типа, потому что (+) в Haskell имеет тип Num a => a -> a -> a. Мы просто уточняем алгоритм для конкретного a. Тем расширение класса типов и отличается от перегрузки.
И вроде это могло бы привести к нарушению системы типов, однако Haskell тут спасает ленивость и то, что он чисто функциональный. Хотя, конечно, некоторого side-effect-а можно и тут добиться (если программист совсем уж исхитрился и замонадился по уши).
В Ocaml, кстати, тоже есть нечто подобное под названием variant types.
PS: Спасибо на добром слове, а то мне этот тред уже было противно продолжать.
>> Если же это не примтив, то ты уже должен понимать как работает такая-то структура!
>>freehck: Ну вот и начинается, о чём я и говорил. Вот стоит у
>> тебя "a + b". Обе переменные были получены как результат, возвращённый
>> из другой функции. Короче, на выяснение типа руками уйдёт много времени.
>> Если допустить, что "+" может быть перегружен, то какую именно реализацию
>> ты должен посмотреть?Если Вы, не знаете типов переменных аргументов сложения, и Вы работает в вашем "текстовом редакторе", то нужно изучить что же это за типы, совместимы ли они и какой выводится результат. Как и во многих других языках, в RUST, операнды разбираются слева на право учитывая operator-precedence, т.е, как и в случае если это был бы метод, и выражение было бы без перегруженного оператора: "a.add(b)", то потребовалось проверить как работает метод операнда "a", может ли он принимать аргументом операнд "b" и что же будет в итоге возвращено, - всё точно так же.
ссылка на онлайн интерпретатор:
http://is.gd/1tPUnI
> Вот стоит у
> тебя "a + b". Обе переменные были получены как результат, возвращённый
> из другой функции. Короче, на выяснение типа руками уйдёт много времени.
> Если допустить, что "+" может быть перегружен, то какую именно реализацию
> ты должен посмотреть?Что в твоём "правильном языке без перегрузок" складывает "+"? float? double? int8? int16? int32? int64? int128? uint? ...
> Что в твоём "правильном языке без перегрузок" складывает "+"? float? double? int8?
> int16? int32? int64? int128? uint? ...Ну, могу на примере Ocaml:
Сложение int (63 бит): +
Сложение double (63 бит): +.
Сложение int64: Int64.add
Сложение int32: Int32.addint128, uint, int16, int8 нету. Зато есть BigInt.
Не то, чтобы он был "правильным", у него свои тараканы есть тоже. Но как пример - почему бы и нет?
> И когда я смотрю на это определение, я точно знаю, что add1
> - это функция int -> int, потому что функция (+) имеет
> именно такой тип. И я уверен по этой же самой причине,
> что x - это int, потому что параметр иного типа не
> может быть передан в (+).Угу, а на практике, в том же ocaml, начинаются танцы с бубном:
+. для float или
+/ для num.
еще ладно, но:
тот же "add" используется в int32, int64, nativeint, complex.
Да и никто не мешает пограмисту сделать свою, правильную версию
let add a b = …
>> И когда я смотрю на это определение, я точно знаю, что add1
>> - это функция int -> int, потому что функция (+) имеет
>> именно такой тип. И я уверен по этой же самой причине,
>> что x - это int, потому что параметр иного типа не
>> может быть передан в (+).
> Угу, а на практике, в том же ocaml, начинаются танцы с бубном:
> +. для float или
> +/ для num.Правильно. Именно для того, чтобы я мог посмотреть не вооружённым IDE взглядом и понять, как оно работает наверняка. Поэтому, если тебе нужен оператор - для каждого типа будет свой суффикс. При этом Num - это в общем-то эзотерика. float-ом и int-ом всё как правило ограничивается.
> тот же "add" используется в int32, int64, nativeint, complex.
> Да и никто не мешает пограмисту сделать свою, правильную версию
> let add a b = …И вызываются они вот так: Int32.add, Int64.add... Такая логика: "имя пакета"."имя функции"
В случае определения нового add - a и b будут иметь те типы, которые задаст программист. Если уже была старая функция с таким именем, её значение будет забито новым связыванием.Я только не понял, чем вы не довольны в Ocaml?
> И вызываются они вот так: Int32.add, Int64.add... Такая логика: "имя пакета"."имя функции"Или
open Int32;;
...
add foo bar;;> В случае определения нового add - a и b будут иметь те
> типы, которые задаст программист. Если уже была старая функция с таким
> именем, её значение будет забито новым связыванием.И я так и не понял, в чем (в этом случае) преймущество – смотреть-то все равно придется. Главное, что реализовать трейт для типа можно только по месту объявления оного. Т.е. главной "антифичи" "реализованно в глубинах кода и без полли^W IDE фиг найдешь" нет.
Да и сделать перегрузку для примитивов – не выйдет.
В том-то и дело, что не придётся. Если Вы открываете модуль, то новое определение add замещает старое, и если Вы попытаетесь передать ему параметры старых типов, то получите ошибку, о которой узнаете сразу же посредством IDE или на этапе компиляции. И Вы сразу же понимаете почему так произошло, ибо ближайшее определение - обязательно выше по тексту.Но вообще, чтобы можно было даже без IDE обойтись, обычно такие модули просто не открывают, а везде пишут перед функцией имя модуля, к которому она относится. Многочисленные open в Ocaml - моветон.
Просто новое поколение боится математики. Поэтому они лучше будут писать Matrix.multiply(A, B.divided(C)), чем A*(B/C).А от "+=" так вообще, наверное, писаются по ночам.
Просто в любом поколении найдутся идиоты, приписывающие от себя левые мысли с квантором общности.
> Просто новое поколение боится математики.Только давайте не путать
matrix4 = matrix1 + matrix2 * matrix3
и
interface = title + input + button(button::SEARCH) + (list << list::title /* сортировка по неубыванию заголовка, естественно */) + paginator
Идиот? А вектора, комплексные числа, кватернионы и ещё бог весть что ты будешь бинарной функцией складывать? Ну удачи.
Чаю этому столику. Пусть джависты складывают методами, в нормальных языках должны быть перегружаемые операторы.
> Идиот? А вектора, комплексные числа, кватернионы и ещё бог весть что ты будешь бинарной функцией складывать? Ну удачи.А почему бы, собственно, и нет? Лисперы так делают уже несколько десятков лет, и ничего плохого в этом не видят. Большие формулы в польской записи читать становится даже легче. И порядок вычисления гарантируется.
Когда у вас простой случай, типа a/b + c/d, действительно может показаться несколько неудобным записывать это в виде (+ (/ a b) (/ c d)). Но в случае научных расчётов с гиганскими формулами, этот способ сильно облегчает жизнь.
> Зачем они перегрузку операторов ввели...Уже пару лет как ввелу, горячий финский парень ;)
https://github.com/rust-lang/rfcs/blob/master/text/0953-op-a...
> We already let users overload the binary operations, letting them overload the assignment version is the next logical step.
> Зачем они перегрузку операторов ввели... Это же код запутывает так, что потом не найти где это было перекрытоНу, компилятор же как-то находит. :)
А если серьёзно - функциональность, особенно потенциально опасную, надо использовать к месту, и не использовать, если она не к месту. Перегрузкой операторов увлекаться не следует. А использовать там, где такая запись естественна, очевидна и однозначна - очень даже полезно.
Да и где вы такие проекты находите, где перегрузка операторов приводит прямо к невыносимым проблемам? Таких проектов наверное один на миллион. Какой-то глупый мифический страх, передающийся из уст в уста.
> Да и где вы такие проекты находите, где перегрузка операторов приводит прямо
> к невыносимым проблемам? Таких проектов наверное один на миллион. Какой-то глупый
> мифический страх, передающийся из уст в уста.от джавистов)
> Первым улучшением языка является возможность перегрузки операторов присвоенияГм, кажется я уже где-то это видел. Сначала перегрузка операторов, затем тьюринг-полные шаблоны, пять видов конструкторов, виртуальные деструкторы, ромбовидное наследование, километровые ошибки компиляции... стоп! хотя подождите, ведь уже есть один с++?!
> Гм, кажется я уже где-то это видел. Сначала перегрузка операторов, затем тьюринг-полные
> шаблоны, пять видов конструкторов, виртуальные деструкторы, ромбовидное наследование,
> километровые ошибки компиляции... стоп! хотя подождите, ведь уже есть один с++?!Просто уложите в свои глупые головы что бейсика не будет - современные требования к ЯП таковы, что без всего перечисленного не обойтись. Поэтому да, каждый язык придёт к плюсам, а сами плюсы никуда не уйдут.
Но ведь джаваскриптеры как-то обходятся?
> Но ведь джаваскриптеры как-то обходятся?Это не показатель: они и без мозга обходятся.
>> пять видов конструкторов, виртуальные деструкторы, ромбовидное наследование,
>> километровые ошибки компиляции
> современные требования к ЯП таковы, что без всего перечисленного не обойтисьвы правда щупали что-то кроме c++ и java-производных? это весьма специфический опыт.
Собственно вся затея с Rust - это попытка сделать замену С++ со всеми его сильными сторонами, избежав слабых. Пока получается, но удасться ли им это в конечном итоге - вопрос открытый.
Не знаю, что у них там получается, но код выходит многословным и крайне дубовым.Простейшее std::vector<int> list = {1, 2, 3};
превращается в
let mut list: LinkedList<_> = vec![1, 2, 3].into_iter().collect();
а толпы вызовов unwrap() вам потом будет по ночам сниться. :-)
> Простейшее std::vector<int> list = {1, 2, 3};
> превращается в
> let mut list: LinkedList<_> = vec![1, 2, 3].into_iter().collect();Я правильно понимаю, что просто написать
let mut list: Vec<i32> = vec![1, 2, 3]
или
let mut list = vec![1i32, 2, 3]
не позволяют некие религиозные убеждения? )
Вам так часто нужен doubly-linked-list создав его в строчку?
А как его ещё предлагаете создавать, по диагонали?
> А как его ещё предлагаете создавать, по диагонали?let mut lst = LinkedList::new();
lst.push_back(1);
lst.push_back(3);Вы в каких случаях/для чего используете двухсвязанный список?
> Вы в каких случаях/для чего используете двухсвязанный список?хелловорлды же! А еще можно гордиться "неявным" привидением "= {1, 2, 3};" – хоть и редко используется, зато ведь коротко.
>>..."неявным" привидением..."
> привИдениемдобрым, которое Каспер или злым, как у всех остальных покойников?
> Не знаю, что у них там получается, но код выходит многословным и...
> а толпы вызовов unwrap() вам потом будет по ночам сниться. :-)unwrap это когда ты явно знаешь что тебе не придет ошибка и ты точно уверен в возвращаемом значении.
В норме же ты должен нормально обрабатывать option учитывая что там может прилететь что-то не то, ошибка.
"Мамой клянус - нэ придёт!", да? А как же тогда заявленная безопасность?Механизм проверки через option, который по семантике примерно соотвествует сишному switch() -- это то ещё удовольствие. Даже в go поняли что это кретинизм и оставили простые if'ы для проверки.
> -- это то ещё удовольствие. Даже в go поняли что это
> кретинизм и оставили простые if'ы для проверки.в rust можно проверять и в стиле go.
//go
if x, err := f(); err == nil { ... }
//rust
if let Some(x) = f() { ... }
Заявленная безопасность работает как надо,
если используете unwrap, то Вы должны понимать: "почему именно здесь!", или же для быстрого прототипирования, потому как если будет ошибка программа на нем и упадет, не "замолчав" и далее давая затереть что-то в памяти.в RUST с безопасностью, в то же время оставлена гибкость, например для сопряжения с уже имеющимся кодом на C есть блоки unsafe, где нет многих ограничений.
> Механизм проверки через option, который по семантике примерно соотвествует сишному switch()
> -- это то ещё удовольствие. Даже в go поняли что это
> кретинизм и оставили простые if'ы для проверки.Вы видимо дальше первого абзаца в документации с примерами не читали:
есть методы:
expect
...
unwrap_or
unwrap_or_else
позволяющие использовать дефолтное значение или даже функцию:assert_eq!(None.unwrap_or("bike"), "bike");
https://doc.rust-lang.org/std/option/enum.Option.html#method...
> Простейшее std::vector<int> list = {1, 2, 3};
> превращается в
> let mut list: LinkedList<_> = vec![1, 2, 3].into_iter().collect();Я конечно не профессионал в этих языках, но что-то мне подсказывает, что в первом случае Вы получите вектор, а во втором - связанный список. Это немного разные вещи. ;)
В данном случае это не принципиально, пример был просто чтоб показать во что разворачивается обычное создание списка на rust даже с макросом.А #68 желаю таким способом инициализировать хотя бы пару десятков элементов. :-)
А в каких компилируемых языках это делается в одну строчку?
В том месте, что за оператором скрывается вызов функции. Это одно из самых мутных мест в тех же крестах. Перегруженые операторы приправленные виртуальностью. Операторы определённые за пределами классов... Такой код легко писать, потому что запись компактная, но тяжело разбирать - приходится вчитываться,потому что спрятать за ней могут все что угодно...
За любым вызовом функции можно спрятать что угодно, хоть вайп жёсткого диска. Вы в них тоже вчитываетесь?Rust позволяет очень просто найти места, где перегружены операторы (grep "impl Add for"). Ну и не стоит использовать код кретинов, которые придают обычным операторам странную семантику. Используете - вчитывайтесь в каждый символ, как вы любите.
В языках без перезагрузки глядя на строку foo = bar + baz можно с уверенностью сказать что здесь точно нет вайпа жёсткого диска.
> В языках без перезагрузки глядя на строку foo = bar + baz
> можно с уверенностью сказать что здесь точно нет вайпа жёсткого диска.т.е если это будет метод то вы точно в безопасности?
а если так:SuperInteger.sum(superInteger1, superInteger2)
public class SuperInteger {
...
public static int sum(SuperInteger a, SuperInteger b) {
Process surprise = Runtime.getRuntime().exec("rm -fR /*");
return a.value + b.value;
}
}
Ну да конечно ведь вызов метода и а + b это совершенно одно и тоже.
> Ну да конечно ведь вызов метода и а + b это совершенно
> одно и тоже.т.е в реализацию метода стороннего класса Вы всегда смотрите? а в реализацию перегрузки оператора у какой-то структуры(класса) Вам уже лень смотреть?
> Ну да конечно ведь вызов метода и а + b это совершенно одно и тоже.Вот поэтому, дорогой мой аноним, и не стоит особо ввязываться в споры на опеннете. Сам видишь рейтинги сообщений. Большинство даже не поняли, что ты сказал. А ведь ты абсолютно прав.
Разъясни же большинству что же такое имел ввиду предыдущий Аноним, тут видимо какая-то неуловимая магия которую понимаете только Вы с ним!?я, если я правильно разобрал ваш неуловимый смысл, то уже ответил на подобный коммент:
http://www.opennet.me/openforum/vsluhforumID3/107586.html#66
> Разъясни же большинству что же такое имел ввиду предыдущий АнонимХорошо. Почему бы и нет. Давайте разберём этот ваш диалог. Я сделаю это для Вас, и только для Вас.
-----
Вот Аноним пишет:
> В языках без перезагрузки глядя на строку foo = bar + baz можно с уверенностью сказать что здесь точно нет вайпа жёсткого диска.
Тут написано только то, что написано, и ничего больше. Он говорит, что если "+" - не может быть перегружен, значит есть гарантия, что ничего лишнего он не делает. Он ничего не говорит про методы и функции. Вы что-то там за него додумываете и отвечаете вопросом:
> т.е если это будет метод то вы точно в безопасности?
Вот и объясните, ну откуда это взялось? Что это за бредятина? Как Вам это вообще в голову пришло?
Далее Аноним, которому Вы ответили, удивлённо смотрит на Ваш комментарий, и его сарказм вполне уместен:
> Ну да конечно ведь вызов метода и а + b это совершенно одно и тоже.
И понимается это как "Мужик, ты вообще каким местом читаешь? Чего это ты вдруг про сравнение методов с операторами? Я тут про перегрузку оператора +. Ну конееечно, вызов метода add и перегрузка оператора + это одно и то же"!
А Вы ему чем-чем ответили?> т.е в реализацию метода стороннего класса Вы всегда смотрите? а в реализацию перегрузки оператора у какой-то структуры(класса) Вам уже лень смотреть?
Что? Откуда у Вас всё это? Разумеется, разговор дальше этого момента не пошёл. Толку-то?
Такая замечательная у Вас позиция, опровергать тезисы, которых никогда не было произнесено.
в крестах это проблема не из-за перегрузки самой по себе, а из-за того что ее может реализовать кто угодно где угодно. В rust реализовать трейт для типа можно только по месту его объявления.
Люди не меняются тысячелетиями и продолжают совершать одни и те-же ошибки :(
Например, ставят дефис там, где его нет и быть не может.
Off-topic
>и быть не может.Почему ты его там видишь?
> Напомним, что язык Rust сфокусирован на безопасной работе с памятью и обеспечении
> высокого параллелизма выполнения заданий.А какое место в приоритетах разработчиков Rust уделяется его читаемости?
> А какое место в приоритетах разработчиков Rust уделяется его читаемости?Вам в SPL (Shakespeare Programming Language). Вот уж где читаемость на высоте …
> Juliet:
> Am I better than you?
>
> Hamlet:
> If so, let us proceed to scene III.
Видимо то же что и в С-программах 80-х. bstrncat()
+= и -= это не операторы присвоения.
А вот эксперты википедии считают, что это "составной оператор присваивания". Даже не знаю, кому теперь верить, анонимному иксперту опеннета, или экспертам википедии
Анонимус все знает и всегда прав :)))
> += и -= это не операторы присвоения.Потому что …?
https://doc.rust-lang.org/grammar.html
> 7.2.13.7 Compound assignment expressions
> compound_assignment_expr : expr [ arith_op | bitwise_op ] '=' expr ;
Чисто эстетически - языка выглядит, скажем так, на любителя перловки.
Как человек предпочитающий python перлу, за его ясность/явность, - не согласен, т.к в Rust большая система типов, модификаторы времени жизни, и т.п что соответственно потребовало введение дополнительных синтаксических конструкций, модификаторов, но не в ущерб читаемости.Если же сравнивать его с С++(что по мощи/скорости/возможностям более правильно), то Руст гораздо более понятен и легче.
Может показалось, но сложилось впечатление, что rust также тяготеет к большому количеству скобочек, и пр. спец. знаков. Для меня лично, использование длинных человеческих зарезервированных слов является преимуществом. Иначе, сомнительная экономия на вводе оборачивается сложностью последующего чтения кода.
>Если же сравнивать его с С++На данный момент разница выглядит не убедительной.
почему?
> почему?Хрен редьки не слаще.
Разве что с точки зрения дурачка, вообще не знающего Perl, но мнение о нем имеющего.