Pull to refresh

Comments 26

let x: &'static u32 = &0;

Rust с каждой версией все более и более уродским становится.

Вот хороший пример читаемости синтаксисов:
Go:
func typeList(arch *TFile,
      offset uint32, parseDecl bool) []BStr {

C++
std::vector<std::string> typeList(TFile* arch,
        off_t offset, bool parseDecl) {


Rust:
fn typeList<'a>(arch: &'a TFile<'a>,
      offset: u32, parseDecl: bool) -> Vec<&'a bstr> {


D:
string[] typeList(File arch, size_t offset, bool parseDecl) {
Rust с каждой версией все более и более уродским становится.

А в чем отличие читаемости rust 1.21 от 1.20?


Вот хороший пример читаемости синтаксисов:

О.о Теплое с мягким.

>А в чем отличие читаемости rust 1.21 от 1.20?
Да ничем. Она отсутствует.

Вообще-то, в Rust приведенная вами строчка при желании сохранить читаемость пишется как let x = &0;. Но даже в таком виде она на самом деле является бессмысленной, так никто не пишет; в реальности эта фича нужна при применении каких-нибудь обобщенных алгоритмов к примитивам.

Вам на ЛОРе уже писали что сравнение неверное, эквивалентный код будет


fn typeList(arch: &TFile, offset: u32, parseDecl: bool) -> Vec<String> {

Но даже если действительно нужно воспользоваться лайфтаймами, то все равно код будет короче, потому что треугольные скобки указывать в данном случае не обязательно:


fn typeList<'a>(arch: &'a TFile, offset: u32, parseDecl: bool) -> Vec<&'a str> {
Вам на ЛОРе уже писали что сравнение неверное, эквивалентный код будет

Не верно. На лоре в первых же сообщениях пример был изменён.

Но даже если действительно нужно воспользоваться лайфтаймами, то все равно код будет короче, потому что треугольные скобки указывать в данном случае не обязательно:

Манипуляция. А так будет ещё короче:

fn typeList<'a>(a: &'a TFile, b: u32, c: bool) -> Vec<&'a str> {

И?

То, что мы нормальные имена заменили на a и назвали это «нормальным» — это ничего не меняет. А если туда добавить generics? А если добавить ещё один лайфтайм? Во что превратиться это?

Не верно. На лоре в первых же сообщениях пример был изменён.

А можно тогда привести пример этого исправленного адекватного сравнения?


А если туда добавить generics? А если добавить ещё один лайфтайм? Во что превратиться это?

А синтаксис ржавчины тут причем? В любом языке при добавлении качественно отличающейся информации размер сигнатуры функции (да и любой другой записи) будет увеличиваться.


Я так понимаю что придирка сводится к тому что ржавчина умеет явно выражать ВЖ, а большинство других языков — нет? Тогда, надо выбрать победителем питон и успокоиться.

А можно тогда привести пример этого исправленного адекватного сравнения?

Зачем вы пытаетесь создавать себе «пути к отступлению» вводя какие-то непонятные критерии, которых ранее не было?

Подтверждение моим словам есть — www.linux.org.ru/forum/development/13699421#comment-13699478

А синтаксис ржавчины тут причем?

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

Не верно. В расте это дополнительный ахтунг, которого в другом языке(без лайвтаймов) не будет.

Я так понимаю что придирка сводится к тому что ржавчина умеет явно выражать ВЖ, а большинство других языков — нет?

Это не придирка. Раст ввёл в язык некую новую сущность, которая не бесплатна с т.з. читаемости и ой как не бесплатна. Да и синтаксис очень спорен — это как минимум.

А люди почему-то выдают её за бесплатную. В этом и есть проблема.

Тогда, надо выбрать победителем питон и успокоиться.

Это глупость. И почему — ниже так же объяснили на том же лоре.

И ваш пример крайне показателен. Вы не спорите с тем, что явная типизация не бесплатна, а в ситуации с растом это не так. Тип — это свойство переменной, который не указывается явно в питоне. Точно так же лайвтайм — это такое же дополнительное свойство. Т.е. ситуация аналогичная, но в случае с растом у нас «всё так же»( что явно неправда), а в случае с питоном всё не так же.

Таким образом питон < С++ < раст. Критерий ясен и понятен. С питоне только имя, в С++ имя и тип, в расте имя + тип + лайвтайм.

Это явная манипуляция о которой я и говорил.
Зачем вы пытаетесь создавать себе «пути к отступлению» вводя какие-то непонятные критерии, которых ранее не было?

Потому что сравнение в первом комментарии этой темы очевидно бессмысленно — третьесортный толстый троллинг с лора — и тратить время на анализ подобного не хочется.


А люди почему-то выдают её за бесплатную. В этом и есть проблема.
И ваш пример крайне показателен. Вы не спорите с тем, что явная типизация не бесплатна, а в ситуации с растом это не так.

Я не вижу что бы кто-то в этой теме заявлял о полной бесплатности ВЖ для читателя кода. Явные ВЖ усложняют типы, только я считаю что это окупается более выразительной формальной семантикой — так и сам код понимать проще, и оптимизации дополнительные можно провести, и от кучи ошибок с памятью автоматически защищает.


Первый комментарий был про уродство ржавого синтаксиса — вот с этим я не согласен, я уверен что это просто вопрос привычки.


Да и синтаксис очень спорен

Обсуждений было много, лучше так никто и не предложил.


В расте это дополнительный ахтунг, которого в другом языке(без лайвтаймов) не будет.

… И там нет возможности выразить эту полезную в некоторых ситуациях информацию, разве нет?

Потому что сравнение в первом комментарии этой темы очевидно бессмысленно — третьесортный толстый троллинг с лора — и тратить время на анализ подобного не хочется.

Для вас всё неудобное троллинг. Очень удобно, не спорю.

Я не вижу что бы кто-то в этой теме заявлял о полной бесплатности ВЖ для читателя кода.

Выше, пожалуйста. Никто из ваших оппонентов не обязан что-то знать про ваш «язык». Приводят примеры и если что-то в них немного неверно написано, то их этого ничего не следует. Это ваша обязанность адаптировать примеры.

А то получается как «будет то же самое» и всё очень удобное — можно посмеяться над автором, но суть примера не в этом. Об этом в том треде сообщили и я вам тут сообщил, что вы, благополучно, проигнорировали. Очень удобно, повторю.

>> Явные ВЖ усложняют типы, только я считаю что это окупается более выразительной формальной семантикой — так и сам код понимать проще, и оптимизации дополнительные можно провести, и от кучи ошибок с памятью автоматически защищает.
Вся эта «более выразительная» — ничего общего с объективностью не имеет. Это итак ясно из контекста.

Наличие подобно в расте лишь следствие слабости компилятора и не более того. А все эти рассуждения об каких-то мистических оптимизациях ничего так же не стоят без примеров. Я их не видел, вы их не показали. Нет никаких оснований вам верить. Всё просто.

Первый комментарий был про уродство ржавого синтаксиса — вот с этим я не согласен, я уверен что это просто вопрос привычки.

Этим можно оправдать всё что угодно. Следует ли из этого что-то? Нет. Ваши слова значат не более чем его, либо чем мои. Никаких объективных свидетельств нету.

Обсуждений было много, лучше так никто и не предложил.

Из этого так же ничего не следует. Отсутствие предложения в какой-то определённой тусе мало что значит. Да и какое там могло быть обсуждение, если это просто рандомный символ на подобии *&. Что там остаётся? #@'? По мне так ' самое глупое из них. По причине 'a' ~= 'a.

Да и странно как-то обсуждалось всё это. Был ГЦ, был другой синтаксис. Потом вдруг бам. ГЦ не стало, ГЦ стал не моден. Идеальный синтаксис выпилили и взяли крестовый.

>>… И там нет возможности выразить эту полезную в некоторых ситуациях информацию, разве нет?
Ещё раз. Она там только по причине слабости компилятора. Никакой новой информации она не даёт — она итак выводится из контекста.

То же самое с автоматическим выводом типов. Оно не теряет типы. И нужно не для какой-то там неведомой «полезной информации», а чисто для ограничений, либо кастов всяких литералов в нужный тип.

Если у меня есть функция (a) -> b {return c{a};}, где с хранит ссылку a, но при этом это компилятор сам вывести не может — это никакой новой информации мне не даёт, да и вообще не даёт.
UFO just landed and posted this here

'a в данном случае никакого собственного смысла не несёт, единственная его функция — указать одинаковость времён жизни arch и возвращаемого значения. Поэтому нет никакого смысла придумывать для него длинное имя.


Для сравнения, в Haskell аннотации типов обычно тоже однобуквенные: (a -> b) -> a -> b. Потому что нет никакого смысла писать (любойтип1 -> любойтип2) -> любойтип1 -> любойтип2. Так и здесь нет никакого смысла писать 'любое_подходящее_время_жизни_1

'a в данном случае никакого собственного смысла не несёт, единственная его функция — указать одинаковость времён жизни arch и возвращаемого значения.

Никакого собственного смысла имя типа в шаблонах не несёт, единственная его функция — указать одинаковость типов…

Никакого собственного смысла переменная не несёт, единственная её функция — указать одинаковость значений…

Ну и ключевое слово «в данном случае». А не в данном?

>>Для сравнения, в Haskell аннотации типов обычно тоже однобуквенные
И? Что же из этого следует? Т.е. вы мне предлагаете писать так: а<A, 'a, B, C>(arg0: &'a A, arg1: &'a B) -> &'a B? Либо как там у вас будет? Нет, спасибо.

Потому что нет никакого смысла писать (любойтип1 -> любойтип2)

Т.е. вместо (Container, Value) -> Iterator мне надо писать (a, b) -> c? Нет, спасибо. Проблема в том, что там не любой тип — любой тип никому не нужен.

Для сравнения, в Haskell аннотации типов обычно тоже однобуквенные

Что же из этого следует?

Из этого следует, что не стоит напрягаться и придумывать описание для вещей, которые в описании не нуждаются. Переменные обычно связаны с семантикой выполняемых функцией действий, поэтому имеет смысл называть их так, чтобы семантика функции становилась яснее. Функции аннотаций времен жизни — связывание времен жизни различных переменных отношением равенства и задание отношения "живёт-дольше-чем" между двумя временами жизни. Как ни назови 'a, его значение будет "ссылка X живет столько же сколько ссылка Y", а это и так видно из кода.


Требовать назвать время жизни осмысленней, примерно то же самое, что отказываться решать уравнение 2*x+4=0, пока вместо x не поставят "неизвестное_количество_яблок" или что-то в этом роде.


Т.е. вместо (Container, Value) -> Iterator мне надо писать (a, b) -> c? Нет, спасибо. Проблема в том, что там не любой тип — любой тип никому не нужен.

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


В C++ это будет template<a,b,c> c func(std::pair<a,b> val){...} и Iterator func(std::pair<Container, Value> val) — разные вещи, в общем.


Кстати, функция с сигнатурой (a,b) -> c довольно бессмысленна, так как может возвращать только bottom. Но это уже к обсуждению не относится.

Требовать назвать время жизни осмысленней, примерно то же самое, что отказываться решать уравнение 2*x+4=0, пока вместо x не поставят «неизвестное_количество_яблок» или что-то в этом роде.


Переменные обычно связаны с семантикой выполняемых функцией действий, поэтому имеет смысл называть их так, чтобы семантика функции становилась яснее.


Явное противоречие. Вы уж определитесь с тем — нужно ли вводить ассоциацию между значением и тем, что оно выражает, либо нет. А то в одном случае смысла нет, а в другом есть.

Как ни назови 'a, его значение будет «ссылка X живет столько же сколько ссылка Y», а это и так видно из кода.

Я уже давал вам вариации на тему, которые вы, благополучно, проигнорировали. Как не назови A, его значение будет «тип ссылки X является тем же, что у типа ссылки Y».

Я могу попытаться найти какое-то рациональное зерно в ваших рассуждения и сформулировать его. Переменные — это отображение неких сущностей из реальной мира, либо каких-то внешних моделей. Есть модель тех же уравнений — там у x есть чёткое определение, только оно определённо где-то в рамках этой модели. И записывая 2x+4=0 вы просто используете x как экспорт из этой модели. И уже каждый знает что такое x.

А вот если вы там напишите 2*g+4=0, то вы получите фейл. Т.к. вы привели банальный подлог.

Поэтому, если мы считаем яблоки, то у нас и название переменных будут яблоки, а не x — x это некая обобщённая форма неизвестной. Как то же value. И использовать везде abc вместо яблок — это моветон.

Тут имеет смысл только ссылка на то, что лайвтаймы — это про отношения ссылок/сущностей внутри самого языка. Мы не экспортируем что-то явно, либо по умолчанию( как в примере с x), а именно определяем их в определённом контексте.

Но опять же — это тупиковый путь. open_file(string a); — почему подобное является моветоном? Ведь контекст явно определён. file, да и тип string из которого мы сразу узнаём искомое свойство файла, но. Это некрасиво, это глупо.

Поэтому да, явно видно к чему привязан лайвтайм, но. Явно видно и то, что a = x * y. Но что дальше? По мне так лучше это назвать xy, пусть мы итак видим, что это x * y. Явно видно, что string a = file.name; Но что из этого следует? Да ничего, кроме того, что это явная глупость.

То же самое с лайвтаймами. Смотря на 'a — я не понимаю что это и откуда взялось. Мне надо смотреть на полный контекст, который может быть не таким примитивным. Зачем? А незачем. И причину я уже описал выше. А далее я делаю вывод, что вы используете это потому, что лайвтаймы — это введённые для компилятора кастыли. Вы итак видите продление времени жизни объекта — это вам не нужно. Именно поэтому вы и пытаетесь их писать write-only и после — игнорировать. Иначе подобное поведение не описать.

Таким образом это что-то типа. let a; a = b; c = a; — т.е. у меня есть a', которое никак и ни к чему не привязано. Оно болтается в воздухе. Далее, оно неизвестно где и неизвестно как привязывается ко времени жизни одного и второго(и далее) объекта как-бы уравнивая время их жизни. И ты никак из этого 'a не узнаешь что это, зачем это и почему.

Какой смысл в этом по сравнению с (a, b) -> c {return c{move(a)};} — я не вижу.

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

Я уже заранее ответил на это, но вы почему-то это проигнорировали. Никакие «любые типы» НИКОМУ и НИКОГДА не нужны. Это очень и очень редкий кейс.

В C++ это будет template<a,b,c> c func(std::pair<a,b> val){...} и Iterator func(std::pair<Container, Value> val) — разные вещи, в общем.

Это вещи идентичные. Либо вы не понимаете, что это шаблонные типы?

template<Container, Value, Iterator> Iterator func(std::pair<Container, Value> val); А не то, что вы написали.

Здесь у нас есть некий обобщённый(упрощённый) тип контейнера, который подразумевает контейнер, а не хрен пойми что. Некий обобщённый тип значения и некий обобщённый тип итератора. Т.е. имя наделяет переменную дополнительными свойствами, которых не на уровне языка. Но не только.

Существует нотации для определения свойств уровня языка в переменных. Кто-то их считается осмысленными и нужными. Да и много есть кейсов, где имя удобнее.

Т.е. даже если у меня есть механизмы внутри самого языка ограничить множество типов в a только контейнерами, то мне проще использовать Container, а не смотреть что там и как определенно. Особенно если это тонна лапши. Это лишь дополнительная строгость уровня языка…

Кстати, функция с сигнатурой (a,b) -> c довольно бессмысленна, так как может возвращать только bottom. Но это уже к обсуждению не относится.

Что? В этом и проблема, что вы уже запутались. А если бы вы посмотрели на имена — вы бы сразу там увидели банальную сигнатуру find(a, b) -> c.

Нетривиальной функции template<Container, Value, Iterator> Iterator func(std::pair<Container, Value> val); которая бы делала что-то осмысленное в языке С++ существовать не может. Дальше думайте сами.

Слив засчитан.

Нетривиальной функции template<Container, Value, Iterator> Iterator func(std::pair<Container, Value> val); которая бы делала что-то осмысленное в языке С++ существовать не может.

Что это за бредни? Во-первых откуда там взялся pair? Во-вторых — я уже назвал пример.

В любом случае — исход был заранее определён. Вы очень часто путаете ваши мечты и ваши возможности. Ваши возможности ограничены минусом «в крысу». В следующий раз не надо это путать. Остальные вон не перепутали.
Вообще-то это была цитата из вашего же комментария. Слив засчитан :-)
UFO just landed and posted this here
Я не случайно написал что функция должна делать что-то осмысленное.
UFO just landed and posted this here

Независимо от того что она делает на самом деле, Iterator следует убрать из параметров шаблона и заменить на Container::iterator

Вот хороший пример читаемости синтаксисов

кстати, по этой логике победителем должен быть питон, почему его (или еще какой скриптоты) даже в списке нет :(?


def typeList(arch, offset, parseDecl):


(это я тонко намекаю на потерю информации)

>> То есть 5 будет положено в стек или возможно в регистры, а x будет ссылкой на него
Можно ли точно знать куда будет положено значение (в стек или же в регистр) или здесь нет четкого правила?

Зависит от того, сможет ли оптимизатор кода заинлайнить его до такой степени что ссылка станет не нужна. Если сможет — то значение будет кандидатом на передачу через регистр, если вообще останется после всех оптимизаций. Если не сможет — то конечно же оно попадет в стек, потому что на регистр ссылку передать нельзя.

На уровне языка, насколько я знаю — нельзя.


Но если очень надо, можно, как и в других системных языках, для конкретного приложения на конкретной архитектуре дизасм посмотреть и попытаться подогнать код так, что бы оптимизатор затолкал что нам там надо в регистр. Только с этим, конечно, надо быть осторожным и много раз перепроверить что в итоге вышла реально оптимизация — а то LLVM умный, его не так-то легко перехитрить руками обычно.

Sign up to leave a comment.

Articles

Change theme settings