Довелось читать != прочел целиком и освоил. Сегодня одно, завтра другое. За последние три года прочел только две трети плюсового стандарта (в отличие от того же ES, который я полностью прочел и осознал где-то за пол-года, так как меня заставили^W^W мне нужно было его реализовать). Многие вещи из стандартной библиотеки я даже не трогал. Как понадобится — выделю время. А понадобится либо при затыке, либо при необходимости лезть в компилятор плюсов/стандартную библиотеку. Однако, структура документа мне понятна, к языку (не программирования, а документа) я уже более-менее привык, так что найти что-либо можно будет буквально на несколько минут.
Кстати, вы в курсе, почему нельзя начинать суффикс user-defined-literal'а с чего-либо кроме знака подчеркивания (для действительно пользовательских литералов, а не стандартных)? Ибо хотя грамматика в 2.14.18 говорит, что ud-suffix = identifier, если пройти по ссылке на 17.6.4.3.5, то там буржуйским по белому пишут: «начинать только с '_'», и в 2.14.18 добавляют — ill-formed. На это я наткнулся, когда написал код типа
#define str «thing»
cout << «some»str << endl; // имелась ввиду конкатенация литералов из 2.14.5(13)
а компилятор дал мне отлуп. Говорит, это нифига не допустимый ud-literal.
И да, вы правы, плюсовый стандарт — это один из самых замудренных документов, которые я только читал. Есть там и простые вещи, типа «If during the evaluation of an expression, the result is not mathematically defined or not in the range of representable values for its type, the behavior is undefined.», так и сложные, типа «Before being substituted, each argument’s preprocessing tokens are completely macro replaced as if they formed the rest of the preprocessing file; no other preprocessing tokens are available.».
Но стоит отдать должное, фортрановский стандарт еще никто не смог перегнать по концентрации мути, например, чего только стоит воистину гениальное «Execution of a CONTINUE statement has no effect.» и с трудом понимаемое «Blanks may be inserted freely between tokens to improve readability; for example, blanks may occur between the tokens that form a complex literal constant.» Ну, про пробелы в фортране, я надеюсь, вы наслышаны.
По поводу рода занятий. Все дело в том, что занимаюсь в основном разработкой компиляторов (конечно, пол-года-год назад я участвовал в разработке интерпретатора, но отличий в плане следования стандартам до последней запятой, уж поверьте мне, никаких). Не могу, к сожалению, сказать, что именно я разрабатываю, что принимаю на вход и что генерю на выходе. NDA, сами понимаете.
Но, ИМХО, самая засада это не зубрежка уставов^W стандартов, а ситуация, когда два стандарта пересекаются. Например, OpenACC не описывает взаимодествие с фортрановским кодом не 2003-го стандарта. А мне нужно было добавить поддержку в компилятор, который поддерживает 2008-й стандарт. Разумеется, Самый Простой И Правильный Способ (СПИПС) это дать отлут на такой код. Но голова же дана не только чтобы форменный головной убор носить^W^W^W^W в нее есть, но и для того, чтобы найти Сложный Способ, Который Правильнее СПИПС. Я его, кстати, так и не нашел. До того, как я решил проблему с PARALLEL FOR, меня перекинули на другой проект. Теперь в GCC используется СПИПС.
По поводу начинающего программиста. Если коротко, то профессионально (за деньги) я программирую уже пять лет. До этого еще десять готовил себя к этому. Однако, ИМХО, в компиляторстве я навсегда останусь новичком, ибо сколько бы уставов я не зазубрил, сколько бы оптимизаций не реализовал, сколько бы новых оптимизаций не изобрел, всегда найдется хитрый нюанс, который я не учел, и мой компилятор будет генерировать некоректный код. Если это произойдет завтра, то это выльется милиардными убытками (буквально) для Корпорации, в которой я сейчас работаю, через пол-года. Зато и удовольствие получаешь огромное от работы и удовлетворение. Заказчики — сплошь программисты, требования закреплены и не изменятся, разве что выйдет новая версия стандарта или новый процессор. Ну не вхожу я в ту элиту, которая кидается реализовывать все изменения после очередного драфта. Мне бы свои баги, которые живут годами, поправить.
Существует способ очистить некоторые самсунговские телефоны от предустановленного дерьма без рута. Вроде как работает на S6 и не работает на S5. Всякое региональное дерьмо и игры в некоторых телефонах лежат на data партицие. Следовательно, сразу при покупке телефона можно почистить этот data партишн и, если телефон не новый, то потерять все данные.
Проверьте, что это действительно так (приложения лежат в /data/app/ и /data/priv-app/)
Повторяю ВСЕ ДАННЫЕ БУДУТ ПОТЕРЯНЫ. Делайте бекапы уже, наконец.
Итак, по шагам.
1) Шторку вниз
2) Настройки
3) О телефоне
4) 8 раз тапаем на «Номер сборки»
5) Назад
6) Параметры разработчика
7) Включить отладку USB.
8) На компе в консоли пишите «adb reboot recovery»
9) 3 раза громкость вниз (wipe data partition) и кнопку включения
10) 7 раз громкость вниз (Yes) и кнопку включения
11) Кнопку включения (Reboot now)
Получаем девственно чистый телефон (планшет).
Вот тут вы неправы. Хотя я являюсь начинающим программистом, я не считаю, что скилл программиста зависит от знания языка программирования, даже если это С++, тем более если это С++. Или от знания алгоритмов. Это все базовые знания, которые программист усваивает в ВУЗе, до начала своей профессиональной карьеры. И даже при смене языка, хотя бы структуру спецификации или стандарта _крайне_ желательно усвоить, чтобы в случае чего подглядеть, что там да как.
И я ни слова не сказал о скиллах, я лишь говорил о том, что документацию надо знать (вне зависимости от скиллов), по ней надо уметь искать, её надо перечитывать время от времени, в конце концов. Только для того, чтобы не удивляться, когда замена function foo(){} на var foo = function(){} ломает скрипт. Или перенос выражения после return на новую строку ломает скрипт. Или [выберите свой любимый способ выстрелить в ногу]
И да, для тех, кто не знает языка вероятного противника, доступен перевод (про качество перевода не скажу ничего, ибо не читал) es5.javascript.ru Правда, ES6, насколько я знаю, не переведен.
Кроме того, как я уже говорил, стандарт ES очень хорошо написан. Простым и последовательным языком. Прочесть его можно за неделю по вечерам и выходным. Понять? Ну, поэтому я и говорю «перечитывать время от времени». Сколько времени это сыкономит на отладке «за несколько лет работы»? Я не знаю, ибо «документацию надо знать». И если какая-то фигна описана в документации, а программист ее не знает, то ему нужно сказать RTFM и, желательно, раздел, где эта фигня описана.
Но это не всегда спасает от нубских ошибок. Например, попытка изменения строкового литерала, который находится в .rodata. Куда копать при SIGSEGV'e? Ясное дело, надо программисту обьяснить, что такое ELF, что такое Special Segments, что такое .rodata и кинуть в него ссылкой на ELF Format Specification. Ибо не все описано в стандарте С.
Вот что меня поражает, так это то, что, имхо, нормальная ситуация, когда сишники и плюсовики у нас на работе (а других у нас и не водится) свободно объяснят тонкости языка (например, integer promotion (да, это базовое знание С, но никто не гонит ссанными тряпками)), часто с ссылками на разделы стандарта, по вашему мнению, просто немыслима. Это не наезд, а опять же отсылка к RTFM.
Да, я допускаю, что это во мне говорит юношеский максимализм, помноженный на профессиональную деформацию. Мне просто по работе нужно знать и изучать кучу всего, начиная от языка, на котором я программирую, продолжая через знания конкретной архитектуры процессора, для которой моя программа генерирует код (это, естественно, включает в себя знания ассемблера), а также языка программирования, с которого моя программа генерирует код. Кроме того, без знания ядра и системных вызовов мне нечего делать. И я не говорю о оптимизациях, которые, к слову, совсем не просты, хотя и обязательны, ибо «компилятор должен в первую очередь генерировать коректный код, а во вторую — эффективный». И для всего этого есть документация, и чем она полнее, тем лучше для меня. Поэтому стандарты и спецификации для меня на вес золота. И, честно говоря, я обожаю читать и перечитывать плюсовый стандарт перед сном. Так засыпается лучше. Правда, иногда кошмары снятся, но это ничего, терпимо.
Знаете, мне довелось читать много стандартов языков программирования (С, С++, Fortran, EcmaScript, OpenMP, OpenACC, Posix). Из них ES 5.1 самый, имхо, простой для прочтения и (тут никакого сарказма) увлекательный. Поэтому я, не написавший ни одной продашн строчки на JS, с недоумением читал статью. Какого, простите, хрена нарушать нулевое правило программирования (RTFM)? Поэтому ваш сарказм здесь неуместен. И меня поражает сообщество, которое минусует в ответ на RTFM.
Из того, что мне запомнилось из работы над Jerry (https://github.com/Samsung/jerryscript) (Скажу честно — до сих пор жалею, что согласился на уговоры присоединиться к разработке и всей душой желаю смерти этому монстру):
1) BlockStatement очень похож на ObjectLiteral (да-да, тот самый WAT {} + [] !== [] + {})
2) Keywords не являются ключевыми словами, если используются в качестве ключей ObjectLiteral (PropertyName). Например, var a = {for: 1, var: 2}. Более того, следующая конструкция также валидна: a.for + a.var. Вот это действительно WAT! Keyword не является keyword!
3) Ну и конечно hoisting добавил мне пару седых волос на моей юной голове.
Такое ощущение, что автору дали задание портировать башевский скрипт на cmd, и он, следуя завету «проще портировать шелл, чем шелл-скритп» начал потихоньку портировать.
Раз уж заговорили про костыли, позвольте мне рассказать небольшую историю про эти самые костыли.
Давайте вернемся в те времена, когда компьютеры были большими, а памяти было мало. Когда еще не было формата ELF, а (единственный) компилятор Си не был оптимизирующим. Когда еще не было стандарта Си, а тоненькая книжка за авторством Ритчи и Кернигана еще даже не была написана.
Представьте, что вам надо скомпилировать ядро Юникса. Практически в каждом исходном файле описаны используемые функции и количество их параметров, возможно, даже с именами (без типов, ибо, как мы помним, АНСИ Си еще не существует) и глобальные переменные, которые, в свою очередь экспортятся из других исходных файлов. Так как памяти у нас мало, мы создаем т. н. объектные файлы, которые потом объединяются в один большой исполняемый файл редактором связей, линковщиком. Этот линковщик — хитроумный костыль, придуманный для того, чтобы не тратить кучу памяти для хранения внутренних данных компилятора, что произошло бы, если бы мы компилировали всю программу целиком и сразу. Более того, это положение сохранилось до сих пор, костыль прижился и даже схема компиляции по файлам была стандартизирована и сегодня каждый компилятор, даже в том случае, если ему хватает памяти на компиляцию всей программы сразу, компилирует отдельные Compilation Unit'ы.
К слову, чтобы не писать каждый раз обьявления используемых функций, примерно в то же время придумали заголовочные файлы и их включение в Compilation Unit. Этот костыль тоже дожил до наших дней. Но весь этот абзац был только к слову — речь о редакторе связей нано же.
Так вот, Linking Time Optimization — это костыль, который позволяет оптизировать всю программу целиком, а не по отдельным Compilation Unit'ам. Другими словами — это костыль, скрывающий другой костыль. Кстати говоря, последние версии GCC по умолчанию собираются с включеным флагом -flto, который, как уже пояснили выше, включает этот костыль.
Однако, обнаружилась проблемка с этим ключом: дело в том, что GNU make умеет запускать несколько процессов GCC для компиляции нескольких исходников одновременно. Это назвали паралельной сборкой. И эта возможность напрямую следует из архитектуры make и не является костылем. Линковщик же однопоточный. В результате, время компиляции увеличилось, так как парсинг и кодогенерация — это дешевые операции по сравнению с оптимизацией (тем более, всей программы).
Как же GCC собираются решить эту проблему? Костылем! Дело в том, что можно линковать два объектника и на выходе получить еще один объектник. И эти проженные инженеры собираются использовать возможности того же make для параллельной линковки.
А теперь пару слов о том, как же выглядит процесс компиляции программы с использованием LTO. Компилятор генерирует промежуточное преставление и вместо того, чтобы оптимизировать, сразу дампит его в отдельную секцию ELF файла. А оптимизатор запускается линковщиком.
И даже на этом этапе обнаружились проблемы — получаемые после компилятора объектные файлы оказались просто огромными из-за, по сути, не нужного бинарного кода, который все равно будет выкинут и заменен оптимизированным. А просто так выкинуть этот код нельзя — на него завязаны утилиты ar и nm. Что же делать? Хачить! И после этих костылей, вставленых в эти две утилиты, стало возможным уменьшить размер объектников, без потери возможности использовать статические библиотеки и смотреть список символов, определенных а объектнике.
Сколько костылей из-за линкера насчитали? Вот-вот, а выкинуть его нельзя, ибо эта инфраструктура копилась годами, и потребуются годы, чтобы ее заменить. А так — работает же, хоть и раз в пару лет надо еще одну подпорку поставить.
В сторону: а некоторые считают Autotools одним из самых больших нагромождений костылей на костылях.
Вот это мне и нравится в gcc! Чего-то не хватает? Добавь ключик! Кстати, остались еще ключики -fparallelize-tree, -fopenmp и -fopenacc (два последних требуют прагму поставить).
Innovative Language 101 (http://www.innovativelanguage.com/online-language-courses) — Подкасты для изучения разных языков. Лично я использую японский подкаст.
Anki (ankisrs.net) — Прога для интервального повторения слов и фраз.
Это я понимаю. Я не понимаю, почему нельзя проверить, что невалидная ссылка _действительно_ используется? И ругаться только в этом случае? В результате, следующий говнокод без проверок и прочего не компилируется: pastebin.com/DjjVcHB5 Я попробую его причесать и прислать позже (вечером). Но думаю, основная идея понятна.
1) Про это я в курсе. И про то, что extend быстрее.
2) Нет. it — это val y вас (чертова kotlin'овская привычка). Я наткнулся на это недоразумение когда писал сканнер. Стандартный способ — peek/match/next. Для исправления кода нужно использовать .by_ref(), либо loop{}, что, имхо, костыль.
Rust, эх Rust, я в него влюбился с первого вгляда. Но стоило немного копнуть, как сразу видны некоторые детские болезни:
1) Несмотря на то, что язык уже зарелизился, до исх пор есть нестабильное АПИ. Например, vec1.push_all(vec2.as_slice()) дает сразу две ошибки о нестабильных функциях.
2) Есть ошибки в borrowing механизме, например,
while let Some(it) = iter.peek() {
println!("{}", it.next());
}
приводит к ошибке.
3) Скудная документация, например, как мне определить обобщенную функцию, которая принимает mutable peekable iteroator of chars?
fn func<I: Iterator>(iter: &mut Peekable) -> String
Так?
fn func(iter: &mut Peekable) where (I: Iterator) -> String
Или так?
Причем в документации нигде не написано про where.
Кстати, вы в курсе, почему нельзя начинать суффикс user-defined-literal'а с чего-либо кроме знака подчеркивания (для действительно пользовательских литералов, а не стандартных)? Ибо хотя грамматика в 2.14.18 говорит, что ud-suffix = identifier, если пройти по ссылке на 17.6.4.3.5, то там буржуйским по белому пишут: «начинать только с '_'», и в 2.14.18 добавляют — ill-formed. На это я наткнулся, когда написал код типа
#define str «thing»
cout << «some»str << endl; // имелась ввиду конкатенация литералов из 2.14.5(13)
а компилятор дал мне отлуп. Говорит, это нифига не допустимый ud-literal.
И да, вы правы, плюсовый стандарт — это один из самых замудренных документов, которые я только читал. Есть там и простые вещи, типа «If during the evaluation of an expression, the result is not mathematically defined or not in the range of representable values for its type, the behavior is undefined.», так и сложные, типа «Before being substituted, each argument’s preprocessing tokens are completely macro replaced as if they formed the rest of the preprocessing file; no other preprocessing tokens are available.».
Но стоит отдать должное, фортрановский стандарт еще никто не смог перегнать по концентрации мути, например, чего только стоит воистину гениальное «Execution of a CONTINUE statement has no effect.» и с трудом понимаемое «Blanks may be inserted freely between tokens to improve readability; for example, blanks may occur between the tokens that form a complex literal constant.» Ну, про пробелы в фортране, я надеюсь, вы наслышаны.
По поводу рода занятий. Все дело в том, что занимаюсь в основном разработкой компиляторов (конечно, пол-года-год назад я участвовал в разработке интерпретатора, но отличий в плане следования стандартам до последней запятой, уж поверьте мне, никаких). Не могу, к сожалению, сказать, что именно я разрабатываю, что принимаю на вход и что генерю на выходе. NDA, сами понимаете.
Но, ИМХО, самая засада это не зубрежка уставов^W стандартов, а ситуация, когда два стандарта пересекаются. Например, OpenACC не описывает взаимодествие с фортрановским кодом не 2003-го стандарта. А мне нужно было добавить поддержку в компилятор, который поддерживает 2008-й стандарт. Разумеется, Самый Простой И Правильный Способ (СПИПС) это дать отлут на такой код. Но голова же дана не только чтобы форменный головной убор носить^W^W^W^W в нее есть, но и для того, чтобы найти Сложный Способ, Который Правильнее СПИПС. Я его, кстати, так и не нашел. До того, как я решил проблему с PARALLEL FOR, меня перекинули на другой проект. Теперь в GCC используется СПИПС.
По поводу начинающего программиста. Если коротко, то профессионально (за деньги) я программирую уже пять лет. До этого еще десять готовил себя к этому. Однако, ИМХО, в компиляторстве я навсегда останусь новичком, ибо сколько бы уставов я не зазубрил, сколько бы оптимизаций не реализовал, сколько бы новых оптимизаций не изобрел, всегда найдется хитрый нюанс, который я не учел, и мой компилятор будет генерировать некоректный код. Если это произойдет завтра, то это выльется милиардными убытками (буквально) для Корпорации, в которой я сейчас работаю, через пол-года. Зато и удовольствие получаешь огромное от работы и удовлетворение. Заказчики — сплошь программисты, требования закреплены и не изменятся, разве что выйдет новая версия стандарта или новый процессор. Ну не вхожу я в ту элиту, которая кидается реализовывать все изменения после очередного драфта. Мне бы свои баги, которые живут годами, поправить.
Проверьте, что это действительно так (приложения лежат в /data/app/ и /data/priv-app/)
Повторяю ВСЕ ДАННЫЕ БУДУТ ПОТЕРЯНЫ. Делайте бекапы уже, наконец.
Итак, по шагам.
1) Шторку вниз
2) Настройки
3) О телефоне
4) 8 раз тапаем на «Номер сборки»
5) Назад
6) Параметры разработчика
7) Включить отладку USB.
8) На компе в консоли пишите «adb reboot recovery»
9) 3 раза громкость вниз (wipe data partition) и кнопку включения
10) 7 раз громкость вниз (Yes) и кнопку включения
11) Кнопку включения (Reboot now)
Получаем девственно чистый телефон (планшет).
И я ни слова не сказал о скиллах, я лишь говорил о том, что документацию надо знать (вне зависимости от скиллов), по ней надо уметь искать, её надо перечитывать время от времени, в конце концов. Только для того, чтобы не удивляться, когда замена function foo(){} на var foo = function(){} ломает скрипт. Или перенос выражения после return на новую строку ломает скрипт. Или [выберите свой любимый способ выстрелить в ногу]
И да, для тех, кто не знает языка вероятного противника, доступен перевод (про качество перевода не скажу ничего, ибо не читал) es5.javascript.ru Правда, ES6, насколько я знаю, не переведен.
Кроме того, как я уже говорил, стандарт ES очень хорошо написан. Простым и последовательным языком. Прочесть его можно за неделю по вечерам и выходным. Понять? Ну, поэтому я и говорю «перечитывать время от времени». Сколько времени это сыкономит на отладке «за несколько лет работы»? Я не знаю, ибо «документацию надо знать». И если какая-то фигна описана в документации, а программист ее не знает, то ему нужно сказать RTFM и, желательно, раздел, где эта фигня описана.
Но это не всегда спасает от нубских ошибок. Например, попытка изменения строкового литерала, который находится в .rodata. Куда копать при SIGSEGV'e? Ясное дело, надо программисту обьяснить, что такое ELF, что такое Special Segments, что такое .rodata и кинуть в него ссылкой на ELF Format Specification. Ибо не все описано в стандарте С.
Вот что меня поражает, так это то, что, имхо, нормальная ситуация, когда сишники и плюсовики у нас на работе (а других у нас и не водится) свободно объяснят тонкости языка (например, integer promotion (да, это базовое знание С, но никто не гонит ссанными тряпками)), часто с ссылками на разделы стандарта, по вашему мнению, просто немыслима. Это не наезд, а опять же отсылка к RTFM.
Да, я допускаю, что это во мне говорит юношеский максимализм, помноженный на профессиональную деформацию. Мне просто по работе нужно знать и изучать кучу всего, начиная от языка, на котором я программирую, продолжая через знания конкретной архитектуры процессора, для которой моя программа генерирует код (это, естественно, включает в себя знания ассемблера), а также языка программирования, с которого моя программа генерирует код. Кроме того, без знания ядра и системных вызовов мне нечего делать. И я не говорю о оптимизациях, которые, к слову, совсем не просты, хотя и обязательны, ибо «компилятор должен в первую очередь генерировать коректный код, а во вторую — эффективный». И для всего этого есть документация, и чем она полнее, тем лучше для меня. Поэтому стандарты и спецификации для меня на вес золота. И, честно говоря, я обожаю читать и перечитывать плюсовый стандарт перед сном. Так засыпается лучше. Правда, иногда кошмары снятся, но это ничего, терпимо.
Из того, что мне запомнилось из работы над Jerry (https://github.com/Samsung/jerryscript) (Скажу честно — до сих пор жалею, что согласился на уговоры присоединиться к разработке и всей душой желаю смерти этому монстру):
1) BlockStatement очень похож на ObjectLiteral (да-да, тот самый WAT {} + [] !== [] + {})
2) Keywords не являются ключевыми словами, если используются в качестве ключей ObjectLiteral (PropertyName). Например, var a = {for: 1, var: 2}. Более того, следующая конструкция также валидна: a.for + a.var. Вот это действительно WAT! Keyword не является keyword!
3) Ну и конечно hoisting добавил мне пару седых волос на моей юной голове.
Давайте вернемся в те времена, когда компьютеры были большими, а памяти было мало. Когда еще не было формата ELF, а (единственный) компилятор Си не был оптимизирующим. Когда еще не было стандарта Си, а тоненькая книжка за авторством Ритчи и Кернигана еще даже не была написана.
Представьте, что вам надо скомпилировать ядро Юникса. Практически в каждом исходном файле описаны используемые функции и количество их параметров, возможно, даже с именами (без типов, ибо, как мы помним, АНСИ Си еще не существует) и глобальные переменные, которые, в свою очередь экспортятся из других исходных файлов. Так как памяти у нас мало, мы создаем т. н. объектные файлы, которые потом объединяются в один большой исполняемый файл редактором связей, линковщиком. Этот линковщик — хитроумный костыль, придуманный для того, чтобы не тратить кучу памяти для хранения внутренних данных компилятора, что произошло бы, если бы мы компилировали всю программу целиком и сразу. Более того, это положение сохранилось до сих пор, костыль прижился и даже схема компиляции по файлам была стандартизирована и сегодня каждый компилятор, даже в том случае, если ему хватает памяти на компиляцию всей программы сразу, компилирует отдельные Compilation Unit'ы.
К слову, чтобы не писать каждый раз обьявления используемых функций, примерно в то же время придумали заголовочные файлы и их включение в Compilation Unit. Этот костыль тоже дожил до наших дней. Но весь этот абзац был только к слову — речь о редакторе связей нано же.
Так вот, Linking Time Optimization — это костыль, который позволяет оптизировать всю программу целиком, а не по отдельным Compilation Unit'ам. Другими словами — это костыль, скрывающий другой костыль. Кстати говоря, последние версии GCC по умолчанию собираются с включеным флагом -flto, который, как уже пояснили выше, включает этот костыль.
Однако, обнаружилась проблемка с этим ключом: дело в том, что GNU make умеет запускать несколько процессов GCC для компиляции нескольких исходников одновременно. Это назвали паралельной сборкой. И эта возможность напрямую следует из архитектуры make и не является костылем. Линковщик же однопоточный. В результате, время компиляции увеличилось, так как парсинг и кодогенерация — это дешевые операции по сравнению с оптимизацией (тем более, всей программы).
Как же GCC собираются решить эту проблему? Костылем! Дело в том, что можно линковать два объектника и на выходе получить еще один объектник. И эти проженные инженеры собираются использовать возможности того же make для параллельной линковки.
А теперь пару слов о том, как же выглядит процесс компиляции программы с использованием LTO. Компилятор генерирует промежуточное преставление и вместо того, чтобы оптимизировать, сразу дампит его в отдельную секцию ELF файла. А оптимизатор запускается линковщиком.
И даже на этом этапе обнаружились проблемы — получаемые после компилятора объектные файлы оказались просто огромными из-за, по сути, не нужного бинарного кода, который все равно будет выкинут и заменен оптимизированным. А просто так выкинуть этот код нельзя — на него завязаны утилиты ar и nm. Что же делать? Хачить! И после этих костылей, вставленых в эти две утилиты, стало возможным уменьшить размер объектников, без потери возможности использовать статические библиотеки и смотреть список символов, определенных а объектнике.
Сколько костылей из-за линкера насчитали? Вот-вот, а выкинуть его нельзя, ибо эта инфраструктура копилась годами, и потребуются годы, чтобы ее заменить. А так — работает же, хоть и раз в пару лет надо еще одну подпорку поставить.
В сторону: а некоторые считают Autotools одним из самых больших нагромождений костылей на костылях.
18.8 Exception handling
The header [exception] defines several types and functions related to the handling of exceptions in a C++ program.
Anki (ankisrs.net) — Прога для интервального повторения слов и фраз.
Не-не, scanner в смысле lexer. Например, stackoverflow.com/questions/23969191/using-the-same-iterator-multiple-times-in-rust
2) Нет. it — это val y вас (чертова kotlin'овская привычка). Я наткнулся на это недоразумение когда писал сканнер. Стандартный способ — peek/match/next. Для исправления кода нужно использовать .by_ref(), либо loop{}, что, имхо, костыль.
3) Спасибо за ссылку!
1) Несмотря на то, что язык уже зарелизился, до исх пор есть нестабильное АПИ. Например, vec1.push_all(vec2.as_slice()) дает сразу две ошибки о нестабильных функциях.
2) Есть ошибки в borrowing механизме, например,
while let Some(it) = iter.peek() {
println!("{}", it.next());
}
приводит к ошибке.
3) Скудная документация, например, как мне определить обобщенную функцию, которая принимает mutable peekable iteroator of chars?
fn func<I: Iterator>(iter: &mut Peekable) -> String
Так?
fn func(iter: &mut Peekable) where (I: Iterator) -> String
Или так?
Причем в документации нигде не написано про where.