ARK>Почему же, один выход проще, чем несколько. Вообще, ретурны, рассеянные где попало в теле функции — это нехорошо. Мешает рассуждениям о программе
Наоборот, помогает
ARK> часто является признаком говнокода.
Нет, не часто
C>>Угу, причём без всякого понимания того, что они таки пишут. Если речь идёт о реальном программировании, то отсутствие generic'ов убивает все эти дервья и списки. C>>Нету generic'ов.
ARK>А что насчет Golang? В нем отсутствие генериков не является препятствием реальному программированию? Но зато в паскале отсутствие генериков сразу ставит крест на обучении. Верно?
В Golang во-первых, есть множество вещей, которых в Паскале нет. Во-вторых, отсутсвие generic'ов таки мешает.
Здравствуйте, Mr.Delphist, Вы писали:
C>>Синтаксис не строгий. MD>Тогда давайте пример production-языка с действительно строгим синтаксисом.
Go, Rust, даже JavaScript.
C>>Не строгая. MD>Эммм... А можно тогда пример действительно строгой типизации? В каком языке? Ну, не считая адской экзотики. Ибо вот чего-чего, а строгости типов Паскаля мне время от времени не хватало во всех этих Си-подобных.
Из современных — Go, Rust, Elm.
MD>На всякий случай, напомню, что в Паскале: https://ideone.com/nYueOe MD>
MD>var a: array[1..10] of integer;
MD>var b: array[1..10] of integer;
MD>...
MD>a := b; { не скомпилируется }
MD>
И где тут строгость? Просто идиотское ограничение — оба массива идентичны.
Здравствуйте, Cyberax, Вы писали:
C>>>Синтаксис не строгий. MD>>Тогда давайте пример production-языка с действительно строгим синтаксисом. C>Go, Rust, даже JavaScript.
Почему в паскале синтаксис не строгий, а в Go, Rust и JavaScript — строгий?
C>>>Не строгая. MD>>Эммм... А можно тогда пример действительно строгой типизации? В каком языке? Ну, не считая адской экзотики. Ибо вот чего-чего, а строгости типов Паскаля мне время от времени не хватало во всех этих Си-подобных. C>Из современных — Go, Rust, Elm.
Почему в паскале типизация не строгая, а в Go и Rust — строгая?
Здравствуйте, SergeyIT, Вы писали:
MD>>>На всякий случай, напомню, что в Паскале: https://ideone.com/nYueOe MD>>>
MD>>>var a: array[1..10] of integer;
MD>>>var b: array[1..10] of integer;
MD>>>...
MD>>>a := b; { не скомпилируется }
MD>>>
C>>И где тут строгость? Просто идиотское ограничение — оба массива идентичны.
SIT>Придет какой-нибудь новатор и поправит, например SIT>var b: array[1..9] of integer; SIT>И что будет, без этой строгости?
Массивы будут неидентичны, и поэтому и присвоение не пройдёт.
Здравствуйте, AlexRK, Вы писали:
ARK>>>Это тоже верно, но я сейчас говорю про текущую ситуацию — с чистотой функций никто не заморачивается (очень зря), но деление все равно есть из-за псевдотипа void, не позволяющего работать однотипно с произвольными функциями. N>>А чем он так мешает? Ну, присвоить результат нельзя. Так и при не-void его присваивать необязательно. ARK>Речь не о том, мешает или не мешает, а о том, что функции делятся на два мира — нельзя использовать void в обобщенном коде.
Ну это только потому, что никто не хотел доработать C++ в эту сторону. Хотели бы — придумали, обёрток такого рода начиная с C++11 "вагон и маленькая тележка".
ARK>>>Я не большой знаток C++ , но не помню, что в нем это "есть". Чтобы использовать пары и туплы для комбинирования, надо, чтобы их не только возвращали, но и принимали входными параметрами, разве нет? Или можно НАПРЯМУЮ сунуть тупл (2, "test") в функцию "void Func(int a, string b)", т.е. вызвать как "Func(myTuple);"?
N>>Можно.
ARK>Не конпелируется что-то: https://ideone.com/Q3TtwD
А, я криво прочитал. Напрямую не получится, нужно, чтобы и аргумент был tuple<>.
Но косвенно такое построить можно, на variadic templates. std::function, например, оборачивает лямбды как раз через такие фокусы.
N>>Даже в штатной библиотеке какой-нибудь std::map::insert принимает std::pair<> как аргумент. ARK>Это и в паскале можно.
Здравствуйте, netch80, Вы писали:
N>- ABI: большинство современных соглашений по вызову предусматривают несколько аргументов (первые — в регистрах, дальше — на стеке), но только одно возвращаемое значение (с поправкой на спецслучаи типа "complex — возвращаем в xmm0 и xmm1"). Например, тут. Дополнительная передача через стек => затраты на запись и чтение, хотя можно было бы для входных параметров и результатов выделить один и тот же набор регистров. Зачем их разделять? Например, для x86-64 SysV — входы в rdi, rsi, rdx, rcx, r8, r9, результат в rax. А нормально было бы — те же 7 регистров и на входе, и на выходе.
И какие предложения? В связи с обсуждаемым разработать новые ABI и срочно их внедрить?
N>Это как раз пример, что ещё недавно из-за замшелой мысленной традиции никто не думал про возврат нескольких значений (фактически, это только сейчас взломано и начинают думать, как это решать).
А точно возврат нескольких значений это настолько революционно, а главное необходимо? Единственное место (из тех, что трогал), где не обойти это Go, но там специфические соглашения об обработке ошибок и оно понапихано в каждой строчке.
N>- Для языков типа C++ может возникнуть проблема цены и принципиальной возможности дополнительного перемещения значения (сначала в структуру возврата, потом из неё в целевую переменную). N>Сейчас есть штатная экономия такого рода (начиная с C++11): если функция объявляет тип возврата string (например; вообще любой тип годится), локально результат кладётся тоже в string и он возвращается, компилятор может сэкономить на одном копировании или даже двух, просто передав адрес целевой строки. Возврат структуры — мешает этому.
Получается, что кругом они проблемы.
Здравствуйте, Cyberax, Вы писали:
C>Организация памяти — это скорее изучение математики с теории множеств и арифметики Пеано.
Это если углубляться, где школьникам делать действительно нечего — виртуальную память, страничную и, прости господи, сегментную организацию памяти. Но если уж решили учить программированию, то сказать что ОП это последовательность пронумерованных байт придется.
C>Да, организация памяти — это очень базовая вещь, но её тупо можно пропустить.
Так можно все, что угодно пропустить, но мы возвращаемся к исходному, для чего этот предмет и что там нужно изучать
Здравствуйте, pagid, Вы писали:
N>>- ABI: большинство современных соглашений по вызову предусматривают несколько аргументов (первые — в регистрах, дальше — на стеке), но только одно возвращаемое значение (с поправкой на спецслучаи типа "complex — возвращаем в xmm0 и xmm1"). Например, тут. Дополнительная передача через стек => затраты на запись и чтение, хотя можно было бы для входных параметров и результатов выделить один и тот же набор регистров. Зачем их разделять? Например, для x86-64 SysV — входы в rdi, rsi, rdx, rcx, r8, r9, результат в rax. А нормально было бы — те же 7 регистров и на входе, и на выходе. P>И какие предложения? В связи с обсуждаемым разработать новые ABI и срочно их внедрить?
Да. С учётом того, что "срочно" в данной области это 10-15 лет.
N>>Это как раз пример, что ещё недавно из-за замшелой мысленной традиции никто не думал про возврат нескольких значений (фактически, это только сейчас взломано и начинают думать, как это решать). P>А точно возврат нескольких значений это настолько революционно, а главное необходимо? Единственное место (из тех, что трогал), где не обойти это Go, но там специфические соглашения об обработке ошибок и оно понапихано в каждой строчке.
Вообще-то это любому языку давно нужно, кроме совсем уж для песочницы.
Всё равно все это делают, только по-разному.
Например, берём Unix API:
int open(аргументы);
реально два значения — дескриптор и код ошибки (который поступает в errno).
В Rust, Erlang и аналогах это честно передают как {ok, Value} | {error, Error}.
int pipe(int fildes[2]);
три значения — два дескриптора и код ошибки.
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
три выходных — код ошибки, сокет и адрес.
И так далее.
Windows? То же самое: у до чёрта функций код ошибки передаётся боковым каналом, его надо доставать через GetLastError(). И аналог такого accept() есть, и многое другое.
Просто C API без учёта ОС — те же пляски с errno на стандартной библиотеке (да хоть strtol); div(), возвращающая структуру.
Да, похоже на то, как Go возвращает ошибки. Но это потому, что они возвращаются явно, в то время как в C их скрывают. А зачем скрывать? Явно — выгоднее и полезнее.
Кстати, именно Go это при текущем ABI всё равно не помогает: почему-то у них до сих пор передачи через регистр нет в принципе. И аргументы, и возвращаемые значения — все на стеке.
N>>- Для языков типа C++ может возникнуть проблема цены и принципиальной возможности дополнительного перемещения значения (сначала в структуру возврата, потом из неё в целевую переменную). N>>Сейчас есть штатная экономия такого рода (начиная с C++11): если функция объявляет тип возврата string (например; вообще любой тип годится), локально результат кладётся тоже в string и он возвращается, компилятор может сэкономить на одном копировании или даже двух, просто передав адрес целевой строки. Возврат структуры — мешает этому. P>Получается, что кругом они проблемы.
Здравствуйте, SergeyIT, Вы писали:
C>>И где тут строгость? Просто идиотское ограничение — оба массива идентичны. SIT>Придет какой-нибудь новатор и поправит, например SIT>var b: array[1..9] of integer; SIT>И что будет, без этой строгости?
Ну вот когда поправит — тогда и выдавать ошибку компиляции.
Здравствуйте, pagid, Вы писали:
C>>Организация памяти — это скорее изучение математики с теории множеств и арифметики Пеано. P>Это если углубляться, где школьникам делать действительно нечего — виртуальную память, страничную и, прости господи, сегментную организацию памяти. Но если уж решили учить программированию, то сказать что ОП это последовательность пронумерованных байт придется.
Ну да, рассказать можно и даже нужно, в качестве заметки на полурока. Заниматься разборами представления чисел в памяти — в базовом курсе не нужно.
C>>Да, организация памяти — это очень базовая вещь, но её тупо можно пропустить. P>Так можно все, что угодно пропустить, но мы возвращаемся к исходному, для чего этот предмет и что там нужно изучать
Есть мнение, что так и надо делать.
Я знаю людей (не программистов), которые ничерта не понимают в основах программирования, но пишут вполне неплохие скрипты на Питоне или Matlab. Так что я не вижу никаких проблем в том, что будет больше упор на практические стороны.
Здравствуйте, AlexRK, Вы писали:
C>>Go, Rust, даже JavaScript. ARK>Почему в паскале синтаксис не строгий, а в Go, Rust и JavaScript — строгий?
Потому, что в Паскале в нём нет стройной логики — куча непонятных исключений и ограничений. В Rust/Go/JS есть логика, хотя в случае JS она слегка наркоманская.
MD>>>Эммм... А можно тогда пример действительно строгой типизации? В каком языке? Ну, не считая адской экзотики. Ибо вот чего-чего, а строгости типов Паскаля мне время от времени не хватало во всех этих Си-подобных. C>>Из современных — Go, Rust, Elm. ARK>Почему в паскале типизация не строгая, а в Go и Rust — строгая?
Ну начнём с того, что в Паскале в принципе нет generic'ов. Т.е. реальный код не сможет использовать обобщённые алгоритмы и контейнеры.
Но даже если на это закрыть глаза, то в стандартном Паскале нет проверки численных переполнений, хотя есть ограниченные типы. В некоторых реализациях эти проверки таки добавили.
Здравствуйте, AlexRK, Вы писали:
MD>>>1) Для новичка эти идеи типа "один вход — один выход" очень даже полезные. C>>Ничем оно не полезное, вообще. ARK>Почему же, один выход проще, чем несколько. Вообще, ретурны, рассеянные где попало в теле функции — это нехорошо. Мешает рассуждениям о программе и часто является признаком говнокода.
Рассуждениям часто мешают множественные вложенные if'ы и флаги вида "needExit", которые появляются в противном случае.
C>>Да, так как от паскалистов в итоге ноль софта осталось. ARK>Total Commander!
Так оно померло...
ARK>А что насчет Golang? В нем отсутствие генериков не является препятствием реальному программированию? Но зато в паскале отсутствие генериков сразу ставит крест на обучении. Верно?
В Golang есть генерики — стандартные векторы и карты. Этим часто можно обойтись. Но да, ждём настоящих generic'ов.
Здравствуйте, Cyberax, Вы писали:
ARK>>Почему в паскале синтаксис не строгий, а в Go, Rust и JavaScript — строгий? C>Потому, что в Паскале в нём нет стройной логики — куча непонятных исключений и ограничений. В Rust/Go/JS есть логика, хотя в случае JS она слегка наркоманская.
Не придирки ради, а токмо интереса для: какие, например, исключения и ограничения в паскале (а в Rust/Go их нет)? Определения переменных в секции "var"?
ARK>>Почему в паскале типизация не строгая, а в Go и Rust — строгая? C>Ну начнём с того, что в Паскале в принципе нет generic'ов. Т.е. реальный код не сможет использовать обобщённые алгоритмы и контейнеры.
Но в Go тоже нет генериков, при этом он заявлен как пример строгой типизации.
C>Но даже если на это закрыть глаза, то в стандартном Паскале нет проверки численных переполнений, хотя есть ограниченные типы. В некоторых реализациях эти проверки таки добавили.
По-моему, это было только в самой первой версии. ИМХО, когда сейчас говорят о паскале, имеют в виду что-то более современное (хотя бы трубопаскаль, или фри).
Здравствуйте, AlexRK, Вы писали:
ARK>Почему же, один выход проще, чем несколько. Вообще, ретурны, рассеянные где попало в теле функции — это нехорошо. Мешает рассуждениям о программе и часто является признаком говнокода.
Вот только когда вместо дополнительного ретурна из двух циклов сразу вместо этого фигачат переменную флаг, и ее постоянно проверяют на каждой итерации цикла — это на порядок больший говнокод, чем несколько возвратов. Ибо лишний код на ровном месте, куча уровней вложенности на ровном месте и раздувание сложности на ровном месте. Вот к таким флагам студенты и школьники привыкают и к логике на дополнительных if с уровнями вложенности, потом хрен отучишь. Да, действительно от множества return в коде желательно избавляться. Но совсем не теми средствами, которые де факто стандарт в паскале. И это не догма, есть случаи, когда дополнительный return наоборот добавляем читаемости.
Здравствуйте, AlexRK, Вы писали:
ARK>По-моему, это было только в самой первой версии. ИМХО, когда сейчас говорят о паскале, имеют в виду что-то более современное (хотя бы трубопаскаль, или фри).
В школе используют почти первоначальное подмножество. Разумеется на нем ничего "промышленного" не написать, и даже вряд ли можно написать что-то полезное выходящее за пределы учебных целей.
Здравствуйте, Cyberax, Вы писали:
C>Но даже если на это закрыть глаза, то в стандартном Паскале нет проверки численных переполнений, хотя есть ограниченные типы. В некоторых реализациях эти проверки таки добавили.
Скорее всего оно просто не определяется как часть языка и в языке не предусмотрена возможность обработки этой ситуации.
Здравствуйте, Cyberax, Вы писали:
C>Ну да, рассказать можно и даже нужно, в качестве заметки на полурока. Заниматься разборами представления чисел в памяти — в базовом курсе не нужно.
А в углубленном?
Ну или вот такое дело, в курсе информатики весьма подробно рассматривается представление чисел в разных системах счисления, когда в двоичной или шестнадцатеричной это уже представление в памяти? или представление в памяти это рассмотрение представления чисел с плавающей точкой в соответствии с IEEE 754 с учетом всяких там правил нормализации и тому подобного? Это точно не нужно, а вот показать, что разрядность и точность для дробных в машинном представлении ограничена полезно или даже необходимо.
C>Есть мнение, что так и надо делать.
Как?
C>Я знаю людей (не программистов), которые ничерта не понимают в основах программирования, но пишут вполне неплохие скрипты на Питоне или Matlab. Так что я не вижу никаких проблем в том, что будет больше упор на практические стороны.
То есть на уроках информатики должны учить писать скрипты на Питоне, Matlab и наверно пользоваться Excel'ем?
Ну может и так Хотя Питон в такой раскладке я бы из списка выбросил, Excel там чуток и так изучают, что там с Matlab и нужен ли он не знаю.
Здравствуйте, Cyberax, Вы писали:
C>Нету generic'ов.
Это да, согласен.
C>Во всех современных языках управление зависимостями, если не в самом языке, то в стандартной библиотеке.
Имя, сестра! Имя! (ц)
Как именно управляется зависимость в C++ STL? Как это делается в дотнетах? (устану перечислять количество либ для этого, и все нестандартные). Тогда, может быть, Джа? Наверняка в Весенней куче пара-тройка кунштюков для этого — осталось лишь назначить какой-то из них стандартынм
Здравствуйте, Cyberax, Вы писали:
C>Здравствуйте, Mr.Delphist, Вы писали:
C>>>Синтаксис не строгий. MD>>Тогда давайте пример production-языка с действительно строгим синтаксисом. C>Go, Rust, даже JavaScript.
Go — основан на duck-typing (ещё бы, наследования-то не завезли), и это Строгая Типизация? Лол, рофл, что там далее по списку.
Rust — очень академичный язык, и, как бы смешно ни звучало, у меня он ассоциируется с ролью "Паскаля нашего времени". Пока что Rust оправдывает это ожидание, болтаясь где-то около нуля на индустриальной шкале.
E... простите, ЧТО? А, гугл подсказывает, что это препроцессор для JS, который используют все три компании, которые про него слышали. Потрясающий production!
C>И где тут строгость? Просто идиотское ограничение — оба массива идентичны.
Похоже, насчёт строгой типизации нам говорить ещё рано