Программирование: введение в профессию. Том IV: парадигмы

image of the cover

Аннотация

Четвёртый том книги «Программирование: введение в профессию» составляют части IX–XII.

Часть IX посвящена парадигмам программирования как общему явлению; примеры рассматриваются на языках, уже известных читателю, в основном это язык Си. Здесь стоит особенно выделить параграф, посвящённый концептуальным различиям между Паскалем и Си (см. 9.3.2, стр. 69).

В части X рассматривается язык Си++ и поддержанные в нём парадигмы объектно-ориентированного программирования и абстрактных типов данных. В основном эта часть сформирована из текста, ранее публиковавшегося отдельной книжкой (Введение в язык Си++), но содержит несколько глав, в той книжке отсутствовавших; в том числе здесь имеется глава, посвящённая графическим пользовательским интерфейсам и их созданию с помощью библиотеки FLTK.

Часть XI отдана экзотическим языкам программирования; здесь рассмотрены Лисп, Scheme, Пролог, а для демонстрации ленивых вычислений привлечён Хоуп (Hope).

Основной целью последней, XII части была демонстрация интерпретации и компиляции как самостоятельных парадигм программирования. Часть начинается с рассмотрения языка Tcl, интерпретируемая сущность которого вряд ли может хоть у кого-нибудь вызвать сомнения. Для полноты картины рассмотрена также библиотека Tcl/Tk, позволяющая очень быстро создавать оконные приложения с GUI. Остаток части содержит обзор концептуальных особенностей интерпретации и компиляции; в самом конце делается попытка сформулировать требования к гипотетическому «чистому компилятору», полностью лишённому каких-либо элементов интерпретации.

Публикация в бумажном варианте

Опубликовано издательством МАКС Пресс (Москва) в 2020 году. ISBN 978-5-317-06379-5.

Электронная версия

Электронная версия, идентичная печатному изданию, доступна здесь: http://www.stolyarov.info/books/pdf/progintro_vol4.pdf

Статус бумажной версии

Имеется в свободной продаже.

Архив примеров программ

Архив, содержащий примеры программ из всех четырёх томов, можно скачать здесь: http://www.stolyarov.info/books/extra/progintro_examples.tgz

Напоминаем, что раскрыть этот архив можно командой

   tar -xzf progintro_examples.tgz

Chicken Scheme

Здравствуйте! Вероятно, на с. 393 ошибка. При использовании флага -postlude "(main ())" список параметров main не защищен от вычисления. Если заменить на -postlude "(main '())", компилятор перестает на это ругаться, но и эффекта от этого ключа никакого нет. Проще самому это всё в конец файла добавить. Также этот флаг не работает и в варианте, где функция main использует свои параметры. Версия csc - 5.1.0, может на более ранних версиях все работало правильно.

admin аватар

С пустым

С пустым списком без квотирования — это я погорячился, конечно, вот они лисповские привычки. По поводу "если использует" — в пятой версии для функции command-line-arguments нужно подключать какой-то модуль, не помню какой. У меня пятой Chicken Scheme под рукой нет, к сожалению — да и вообще, судя по тому, в каком направлении она начала дрейфовать (т.е. по вот этой разнице между 4.* и 5.*), нужно будет рассматривать какую-нибудь другую реализацию Scheme (не знаю, какую именно; надо будет с ними поковыряться).

Но вот по поводу "проще в конец файла добавить" — там суть примера как раз в том, чтобы скрипт (работающий как скрипт) откомпилировать без изменений, а если это всё в файл добавить, то как скрипт оно уже работать не будет.

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

Этот модуль

Этот модуль подключается при помощи (import (chicken process-context)), однако ключу -postlude от этого ни горячо, ни холодно :(

А еще на с.316 на 12 строке с конца GCL моноширинным шрифтом набран, но это так, чтоб не потерялось.

Может после выхода 2-го издания начать errata вести? Считать, что остальные огрехи найдены, а это упомянуть на странице 2-го издания, как с книгой по latex'у.

admin аватар

Эх :(

Эх :(

С версиями вопрос сложный, а вот GCL не тем шрифтом так во второе издание и пролезло, увы.

Про эррату — вообще это мысль, с самого начала все найденные ошибки фиксировать, чтобы не требовалось, как это было с первым изданием, на создание эрраты выделять кучу времени (его так и не нашлось, что вполне ожидаемо, но теперь есть второе издание).

А почему

А почему животные с обложки бегают по безе данных?

Рабочие процессы "совремнного" IT

У автора иллюстрации получился добротный стёб над процессами, происходящими в "современном" IT.
Внешний вид животных характеризует "архитектуру" "софта", создаваемого адептами "разработки" на пайтонах, жабаскрипте и прочей дичи.
Сама сцена (в художественном смысле) напоминает дедлайн в какой-нибудь аутсорсной "компании", где под видом разработки "программисты" копаются в тоннах индусского жаба-кода, рефакторят PHP4-"проект", а в особо запущенных случаях "программируют" в браузере на жабаскрипте.

admin аватар

Честно говоря,

Честно говоря, в таком разрезе я это совершенно не представлял, ну да ладно.

Лишнее

Лишнее подтверждение того, что книги как инструмент пропаганды - штука спорная... Это к ролику, некогда вышедшему на http://infoviolence.org/ru/vblog/video002.html

И того, что совы

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

admin аватар

Гы, и вправду :-)

А я и не заметил.

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

Впрочем, в условиях современного IT по базам данных и не такое бегает.

такие два блина

такие два блина друг на друге оказались наиболее подходящими
Хм, так это не стилизованный бубен? А я-то думал...

admin аватар

Мы такого не

Мы такого не предполагали, но идея мне, несомненно, нравится :-)

Базы данных

Андрей Викторович, не могли бы вы человеку, который только краем уха что-то слышал про базы данных и какой-то там SQL, сказать, стоят ли эти вещи изучения (например, в дополнение к вашей книге) или же эти вещи не случайно не рассматриваются в книге?

admin аватар

Когда

Когда потребуется — изучите. В самом SQL ничего особо сложного нет, а всерьёз изучать реляционную алгебру, нормальные формы вплоть до седьмой и вот это вот всё вы всё равно вряд ли станете.

Но раз уж спросили моего совета, добавлю один момент: если у вас предполагается в этой вашей базе жалкая сотня тысяч записей и жалкие пара десятков запросов в секунду (а то и того меньше), никакой SQL вам не нужен.

Fltk library

Для таких же тупорылых как и я...
Строка для компилятора при дефолтных путях установки библиотеки FLTK на ubuntu будет:
g++ -I/usr/local/include -L/usr/local/lib hello.cpp -lfltk -lX11 -lm

admin аватар

Заметим, если

Заметим, если бы вы её не сами из сорцов собирали, а взяли пакет из убунтовских репов средствами убунтовского же пакетного манагера, то все эти пляски вам бы не потребовались. Оно бы встало в /usr, а не в /usr/local, а /usr компилятор и так знает. Кстати, а -lm зачем? :)

Опять не могу в библиотеку =(

/usr/bin/ld: /tmp/ccQOsohk.o: in function `main':
/home/yuri/Downloads/progintro_examples/fltk/hello.cpp:7: undefined reference to `Fl_Window::Fl_Window(int, int, char const*)'
/usr/bin/ld: /home/yuri/Downloads/progintro_examples/fltk/hello.cpp:8: undefined reference to `Fl_Box::Fl_Box(int, int, int, int, char const*)'
/usr/bin/ld: /home/yuri/Downloads/progintro_examples/fltk/hello.cpp:10: undefined reference to `Fl_Group::end()'
/usr/bin/ld: /home/yuri/Downloads/progintro_examples/fltk/hello.cpp:12: undefined reference to `Fl::run()'
Спасибо за ответ, Андрей Викторович!
Теперь я застрял здесь. Версию библиотеки надо подбирать? Пробовал 1.3.5 и 1.3.4. часа полтора потратил...

admin аватар

Флаг -l не

Флаг -l (в этот раз это эль-маленькая) не забыли компилятору сказать?

g++ -Wall -g hello.cpp -lfltk -o hello

Если скажет, что не нашёл fltk -- то перед -l надо будет ещё -L /where/the/hell/lies/libfltk.a (или .so) <-- указывается путь к директории, где лежит libfltk.a (а собственно её подключение -- это как раз -lfltk)

Вообще мне вот что непонятно, вы, случайно, не начали книгу прямо с десятой части, пропустив первые девять? :-) А ещё, судя по Downloads в путях, вы склонны позволять компьютеру быть сильнее вас. С таким подходом ни хрена вы его не одолеете.

Fltk library

hello.cpp:1:10: fatal error: FL/Fl.H: No such file or directory
1 | #include
| ^~~~~~~~~
Провобовал всевозможные варианты установки библиотеки предложенные гуглом, но так и не допер как решить. Скорее всего многоуважаемый автор укажет , что я полный чайник, но мне все равно, я в отчаянии =)

admin аватар

Здесь дело не в

Здесь дело не в установке, а в отсутствии нужного ключа -I в командной строке компилятора. Найдите, где у вас после установки библиотеки оказался файл Fl.H, он окажется в директории FL (обе заглавные), а сама она — где-то; вот это "где-то" нужно упомянуть в параметре ключа -I, причём раньше имён исходников.

На всякий случай: -I - тут заглавная I (ай), от слова include. Это не во всяком шрифте видно.

Рекурсия высшего порядка

В конце 9.2.2 вводится понятие "рекурсия высшего порядка". Пример с функцией Аккермана далее отбрасывается как бесполезный, после чего предлагается проиллюстрировать это понятие с помощью функции свёртки. Но какое отношение свёртка имеет к этому понятию? Ведь свёртка -- это пример простой рекурсии (хвостовой или "головной", если можно так выразиться), т.к. для вычисления параметров рекурсивного вызова не нужно вызывать функцию свёртки. Что имелось в виду?

admin аватар

Для вычисления

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

fold(...) {
   ... f( ... fold(...f...)  ...) ...
}

и даже можно сказать, что это вот fold(...f...) — это косвенный вызов f, но находимся-то мы при этом в теле fold, а не f. То есть никак не лезет.

Осталось понять, чтО же привести в качестве примера hi-order recursion (аккермана не предлагать).

Листинг bintree.c

На стр.42 в листинге /*bintree.c*/ при выделении памяти
*bp = malloc(sizeof(*bp));
кажется, что указатель bp в первом случае зря разыменован.
Ведь malloc возвращает переменную адресного типа.
Должно быть:
bp = malloc(sizeof(*bp));

admin аватар

Вы абсолютно

Вы абсолютно правы, спасибо. Самое интересное, что этот же пример есть во втором томе в части про язык Си, и там ровно тот же косяк. А в оригинале (в bintree.c, который есть в архиве примеров) было так:

struct backpath *bp = malloc(sizeof(*bp));
struct backpath *t;

Потом я решил убрать вызов malloc из инициализатора, ну и получилось, что получилось -- забыл звёздочку.

Всё-таки Си --

Всё-таки Си -- ужасный язык. В том же Паскале, например, допустить такую ошибку было бы просто невозможно.

Здорово было бы попасть в параллельную вселенную, где мир захватил не Си, а Паскаль. Ну или та же Модула-2, например. Помню, с каким удовольствием в конце 90-х я сдавал лабы по численным методам (сказали, "пиши на чём хочешь") с помощью прекрасного компилятора TopSpeed Modula-2.

admin аватар

Ой да ладно

Си "захватил мир" по совершенно объективной причине: это единственный язык, от которого совершенно штатно и без приключений отрывается ко всем чертям его библиотека. Ну, ещё ассемблеры есть, там вообще нет библиотеки.

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

А что вы имеете

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

Или речь не об этом?

admin аватар

Я уже не помню

Я уже не помню подробностей, но когда-то давно в ходе моей единственной попытки разобраться с Модулой мне этот язык чем-то крайне резко не понравился.

Импорт там действительно явный, вопрос в том, управляет ли этот импорт реалько линковкой или только видимостью символов. Рантайм -- на то и рантайм. что его вообще-то не видно. Но в принципе да, надо смотреть, это может зависеть от реализаций.

Сноски

Доброго здравия! Не могли бы Вы при переиздании сделать так, чтобы все сноски полностью присутствовали на одной странице? На некоторых страницах присутстует только часть сноски, вторая часть располагается на следующей. Как пример, на странице 198 тома IV сноска разбита на две части. В других томах я также видел такие сноски

admin аватар

Странная проблема

Это делается, как мы понимаем, автоматически, когда альтернативой будет довольно большое (4-5 строк по высоте) пустое место внизу страницы.

В целом сносок в новом издании будет меньше, я многие из них перенёс в основной текст. Но специально бороться с переносом сносок на следующие страницы я не планировал.

Здравствуйте!

Здравствуйте! Похоже, на странице 200 опечатка. Там, где ptr = new Square(...,...,0xff0000, 10.0) перепутаны double a и int color

admin аватар

Факт.

Факт, спасибо.

А долго эта ошибка держалась, надо сказать. Сейчас посмотрел самую первую версию Введения в Си++, так там она уже есть. А это 2008 год, та книжка пять изданий выдержала, общее количество проданных экземпляров — больше пятисот. Невнимательный нынче читатель пошёл.

В общем, спасибо ещё раз — за внимательность.

this это

this это указатель? Вопрос возник из-за сложности восприятия *this в функциях вида A& func(/*...*/) {/*...*/; return *this;}. Проблема в типах A& и this

admin аватар

this

this — указатель, A& — ссылка. А в чём проблема-то?

В том, что this -

В том, что this - указатель, а *this, получается, ссылка. Разыменованный указатель - ссылка. Это несколько трудно воспринимать, поэтому на всякий случай спросил

admin аватар

Ссылка

Ссылка семантически эквивалентна тому, на что она ссылается. А разыменование — это переход от адреса к тому, на что адрес указывает. Так что всё вроде бы штатно.

А вы уверены, что не рано за Си++ схватились?

Благодарю за

Благодарю за ответ.

Возможно, немного раньше, чем хотелось бы. Я хотел перечитать первые два тома (и, возможно, ещё третий дочитать), но до конца семестра времени не будет, так как силы брошены только на Си++ и другие предметы (учёба, к сожалению, требует)

admin аватар

Что я могу

Что я могу сказать, берегите мозг.

Пример с разверткой однонапр. списка

Добрый день!
На стр.59-60 в примере по развертке однонапр. списка с накопительным параметром - явно глюки с копипастой произошли.
В функции reverse_list вместо res нужен NULL, а в хелпере reverse_list_do опечатка в имени при рекурсивном вызове, и параметры, похоже, перевернуты

admin аватар

Спасибо!

Спасибо, этих опечаток ещё никто не заметил. Про "_to" вместо "_do" и res вместо NULL согласен. Про перевёрнутость параметров — по-моему там всё-таки всё правильно, lst при входе в функцию указывает на первый элемент остатка списка, который ещё надо переворачивать, его оттуда изымают, в поле next заносят адрес первого элемента того списка, который уже перевёрнут, так что lst становится началом новой версии перевёрнутого списка, а это как раз второй параметр.

Отсечение

Не работает пример в прологе. А именно - процедура del_all_cut не решает проблем процедуры del_all. Попытки найти ошибку у себя успехом не увенчались.
Код:

yuri@KAKTYC:~/Jura/prog/prolog$ cat delall.pl
del_all(_, [], []).
del_all(Elem, [Elem|Tail], Res) :- del_all(Elem, Tail, Res).
del_all(Elem, [X|Tail], [X|NewT]) :- X \= Elem, del_all(Elem, Tail, NewT).

del_all_cut(_, [], []) :- !.
del_all_cut(Elem, [Elem|Tail], Res) :- !, del_all_cut(Elem, Tail, Res).
del_all_cut(Elem, [X|Tail], [X|NewT]) :- del_all_cut(Elem, Tail, NewT).
yuri@KAKTYC:~/Jura/prog/prolog$ swipl -s delall.pl
<Приветствие интерпретатора>
?- del_all(X, [1,2], [1]).
false.

?- del_all_cut(X, [1,2], [1]).
false.

?-

admin аватар

В книге нигде и

В книге нигде и не утверждается, что del_all_cut будет корректно инвертироваться. Напротив, утверждается прямо противоположное, см. последний абзац на стр. 458.

Операции преобразования типа

Здравствуйте, Андрей Викторович. В параграфе, посвященном операциям приведения типа в C++ (и в 4 томе, и во "Введении в C++"), Вы указываете, что reinterpret_cast эквивалентна " сишной" операции преобразования типа. Это, всё же, не совсем так: reinterpret_cast не может снимать и устанавливать модификаторы const и volatile, что заставляет использовать её в паре с const_cast в некоторых случаях, если строго следовать "плюсовой" традиции.

admin аватар

Похоже на

Похоже на правду. Поправлю во втором издании.

Возврат двух и более значений из функций

Довольно часто из функций приходится возвращать не одно значение. В некоторых языках делать это удобно, в других -- нет. Я сейчас имею дело с C++, и варианты решения здесь обычно следующие:
1. Передавать указатель в качестве параметра, и по этому адресу записывать значения. Неудобно, потому что по профилю функции почти никогда не очевидно, какие параметры -- реально параметры, а в какие записываются результаты.
2. Для каждого случая создавать отдельную структуру данных. Но если таких функций много, то и структур будет много, и они будут загромождать текст программы.
3. Предусмотреть шаблон с двумя (или больше) типами-параметрами для пары значений произвольных типов, и таскать его по всей программе.

Из трёх решений относительно приемлемым выглядит третье, но всё равно оно довольно громоздкое. Как вы считаете, какой способ наиболее правильный?

admin аватар

Приемлем

Приемлем только один способ — первый. Если не хватает возможностей самопоясняющего кода (первое, что в голову приходит — назвать параметры с использованием слова out, что-нибудь вроде val1_out, val2_out), то не брезгуйте писать комментарии.

Второй способ приемлем только в случае, если для данной конкретной структуры функция не одна (и лучше не две). Однако это было приемлемо в чистом Си, что же касается Си++, то при виде такого решения возникает вопрос, почему используются функции и структура, а не класс с методами.

Третий способ неприемлем вообще. Он свидетельствует об STLе головного мозга в тяжёлой форме.

Сорри, не заметил, что форматировать можно.

Т.е. что-то типа

std::tuple<int, bool, std::error_code> getCoolIntValue();
/* ... */
auto [val, ok, errorCode] = getCoolIntValue();

даже не рассматривается?

admin аватар

Рассматривается

Рассматривается исключительно как повод набить морду. И выгнать с работы.

Ибо тут не просто STL, а ещё и C++14, если не ошибаюсь. Людям, которые согласны что-то подобное применять, следует категорически запретить подходить к компьютерам. А поскольку создатели стандартов C++ — это особо опасные международные террористы, всех, кто их использует, следует рассматривать, соответственно, как пособников особо опасных международных террористов.

Вот уж что точно вы сделали зря -- так это зря вы на мой сайт забрели. Пойдите ещё куда-нибудь.

Ибо тут не

Ибо тут не просто STL, а ещё и C++14, если не ошибаюсь.
Хуже, C++17. Структурными привязками (structured bindings) именуется воспаленных мозгов стандартизаторов детище сие непотребное.

admin аватар

Тут, чтобы

Тут, чтобы автора вышеприведённого фрагмента однозначно дисквалифицировать, достаточно даже того, что к C++17 не относится. Если мне склероз не изменяет, "автоматический вывод типов переменных" — старое ключевое слово auto в новой ипостаси — появилось ещё в С++11. Так вот его одного достаточно, чтоб руки оторвать за такую писанину. А ещё оторвать голову за то, что в эту голову такие идеи приходят. Я, в принципе, комментировал уже этот момент.

Понятно,

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

P.S. Можно не отвечать, и даже не публиковать, я не обижусь. Работаю в индустрии авионики. Не только российской.

А ведь Ваши

А ведь Ваши книги советуют... причём не только из геймдев-индустрии
Любопытно, что же такого представители современной геймдев-индустрии (читай "любители жабаскрипта, питончика, Unity с C#, WebGL, STL и т.д.") смогли разглядеть в книгах Столярова, что аж советовать кинулись? Консольную "игрушку" с мотающейся по экрану звездочкой? Мне казалось, для подобной публики эти книги, как святая вода для чертей...

Ну уж... Не

Ну уж... Не обижайте разработчиков почем зря - в геймдеве концентрация людей с мозгами как раз очень велика, специфика области того требует. Нынешние геймеры весьма требовательны, им подавай виртуальные миры все "графонистей" и реалистичней. Даже если очень грубо прикинуть: при частоте кадров в 60Гц в вашем распоряжении всего 1/60Гц = ~17мс для обсчета физики, рендера красивой картинки с тенями/отражениями/вот этим вот всем и "пропихивания" потока данных в высоком разрешении через интерфейс. "Алгоритмы компьютерной графики" - дисциплина даже такая есть в ВУЗах (с весьма продвинутой математикой, надо сказать). Это если не начинать вспоминать, что есть в игре еще и куча других подсистем, громе графической. Впрочем, "любители жабаскрипта, питончика, Unity с C#, WebGL, STL и т.д.", конечно, тоже существуют, но, в основном, мозолят всем глаза на каком-нибудь Тюбике со своими "уроками" типа "Пишем игру на Python за час!", "Давим муравьев на экране в WebGL", "Тыкаем вилкой свинье в пятак на Unity" и т.д. К серьезному геймдеву они, понятное дело, относятся примерно никак, там основной инструмент - C++, местами весьма близкий к описанному в 4 томе "Введения в профессию" подмножеству. Есть, кстати, в этой области и "сишники". Так что не стоит кажущуюся несерьезность игр проецировать на их создателей.

admin аватар

Сдаётся мне,

Сдаётся мне, как раз в серьёзных игрушках неизбежно требуется умение писать эффективно — а для этого надо понимать, что делаешь. Т.е. там, в отличие от веба, вменяемые люди ещё встречаются.

admin аватар

Ух ты ж ё

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

Реально, видимо, в индустрии всё совсем плохо, если таких людей допускают к авионике. Мне уже давно на "современных" самолётах летать стрёмно, теперь ещё стремнее будет; но, во всяком случае, я теперь не буду удивляться, что боинги падают из-за косяков встроенного в них софта.

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

Насчет кода для

Насчет кода для авионики и авто - есть такой стандарт MISRA (https://www.perforce.com/resources/qac/misra-c-cpp), там вроде кое-что предусмотрели чтобы уменьшить вероятность всякого рода недопоняток, и вроде как он почти обязателен в некоторых отраслях.
Мне не довелось поиграться с компилятором, но если бы компания закупила - с удовольствием прогнал бы все свои проекты (медицина) через него.

admin аватар

MISRA -- не про

MISRA — не про то, чтобы сделать код надёжным, она про то, как разводить на бабки и выкидывать с рынка независимых разработчиков. А ещё она про чувство ложной безопасности (которое, как известно, крайне вредно само по себе).

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

Спасибо!

Спасибо, что выложили тома этой книги!

admin аватар

Это не мне

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

Отложенная обработка событий

На страницах 88-89 при обсуждении событийно-ориентированного программирования утверждается, что автомат не должен каким бы то ни было образом пытаться управлять потоком внешних событий, в ответ на которые происходят шаги. На практике это правило иногда нарушается, например, при разработке GUI есть очень распространённый приём, когда при обработке события вместо выполнения действия "здесь и сейчас", в конец очереди добавляется новое событие, и действия выполняются только когда это до этого нового события дойдёт очередь. Речь идёт о функциях наподобие postEvent в библиотеке Qt.

admin аватар

Вы путаете две

Вы путаете две парадигмы, которые, хотя и обсуждаются в одном параграфе, и даже друг на дружку довольно похожи, всё-таки совершенно не одно и то же. В событийно-ориентированном программировании порождение нового события изнутри обработчика события — явление хотя и сомнительное, но действительно довольно часто встречающееся, но это не есть программирование в терминах явных состояний (fsm-based, если угодно).

Андрей

Андрей Викторович, а чем мотивировано отсутствие в части о С++, ООП и АТД упоминания о "пороге входа" в ООП (количество написанного кода и т.п.)?
спасибо.

admin аватар

В предисловии к

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

§ 12.1Добавим,

§ 12.1

Добавим, что возможности скриптового программирования на Bourne Shell мы рассмотрели далеко не полностью. В этом языке помимо простых переменных присутствуют ещё массивы;

В Bourne Shell нет массивов. Массивы притащили в bash (Bourne-Again Shell).

Это замечание очень существенно потому, что не знающие этого программисты начинают использовать массивы (и прочие башизмы) в коде, озаглавленном #!/bin/sh. И у них это работает, поскольку /bin/sh у них всего лишь линк на /bin/bash. Но потом они отдают этот код кому-то ещё и этот кто-то вынужден, матерясь, исправлять #!/bin/sh на #!/usr/local/bin/bash и устанавливать себе bash в систему. Ну или вынужден, опять же, матерясь, вычищать башизмы из кода.

А код, озаглавленный #!/bin/sh, просто обязан выполняться на любом POSIX-совместимом шелле.

admin аватар

Да, похоже на

Да, похоже на правду. Пора мне переползать на *BSD, а то что-то разбаловался я на попсовых линуксообразных системах.

Досадно, блин

И кто бы мог подумать лет нцать назад, что слова "линукс" и "попсовый" окажется возможным употреблять в одном предложении...

Да нет, тут как

Да нет, тут как раз ничего удивительного. Линукс всегда был самой попсовой из юниксо-подобных систем, что сейчас, что 20 лет назад. Есть даже известная сентенция по этому поводу:
BSD is what you get when a bunch of Unix hackers sit down to try to port a Unix system to the PC.
Linux is what you get when a bunch of PC hackers sit down and try to write a Unix system for the PC.

И действительно, в сложившейся вокруг линукса культуре чувствовался привкус PC-культуры времён DOS'а, каковая культура от UNIX-культуры довольно сильно отличается. Ну да, впрочем, это всё дела минувших дней.

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

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

опечатка?

Стр.69, внизу:
ясное и изящное решение, написанное на Си, явно проигрывает паскалевскому
Должно быть "выигрывает у"?

admin аватар

Ой как досадно

Конечно, выигрывает. Вот что значит замыленный взгляд.

Спасибо за выявление этого косяка, я его в своём экземпляре пометил -- в следующее издание он не пройдёт.

Нельзя ли и на

Нельзя ли и на сайте pdf-ку поправить? :-)

admin аватар

Я не исправляю

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

errata?

А если просто актуальный список опечаток на страничке рядом с самой книгой держать?

admin аватар

Идея давно

Идея давно известная и очень хорошая, ещё бы времени найти на эту errata. Уже три с лишним года собираюсь.

Стр. 433, внизу:

Стр. 433, внизу: "списов кодов".

admin аватар

Спасибо

Да, корректоры не всемогущи

-lstdc++

здравствуйте. на стр. 261 компиляция командой gcc -Wall -g hello.cpp -lfltk -o hello выдает:
"/usr/bin/ld: /tmp/cchw9A7e.o: undefined reference to symbol '__gxx_personality_v0@@CXXABI_1.3'
//usr/lib/x86_64-linux-gnu/libstdc++.so.6: error adding symbols: DSO missing from command line collect2: error: ld returned 1 exit status".

решается это, по всей видимости, подключением стандартной библиотеки c++ (-lstdc++).
спасибо.

admin аватар

Я думаю, есть

Я думаю, есть более, как бы это сказать, общепринятый вариант решения: вызывать компилятор по имени, корректному для Си++, т.е. g++, а не gcc :-) Библиотеку libstdc++ он тогда подхватит сам.

UPD: Да, на стр. 261 косяк — должно быть g++, а не gcc.

CVS в архиве

В архив примеров попали директории CVS:

$ find progintro_examples -name CVS
progintro_examples/no_libc/CVS
progintro_examples/fltk/CVS
progintro_examples/gettext/CVS
progintro_examples/cpp_chat/CVS
progintro_examples/asmgreet/CVS
progintro_examples/asmcopy/CVS

Ничего критичного, конечно. Просто даю знать.

admin аватар

Спасибо,

Спасибо, поправил

Андрей

Андрей Викторович, позвольте небольшое уточнение (с. 623):
для Windows это .NET, для Android - Java Virtual Machine
Android не использует JVM (как имя собственное - часть исполняющей системы Java). Ранее там использовался Dalvik, сейчас ART. Формально, конечно, они не перестают быть Java Virtual Machine в смысле виртуальной машины, исполняющей байт-код, полученный из Java, но бинарно и архитектурно с с "традиционной" JVM они несовместимы.

admin аватар

Спасибо

Спасибо, учту это при переиздании, если до него дело дойдёт.

Настройки просмотра комментариев

Выберите нужный метод показа комментариев и нажмите "Сохранить установки".

Отправить комментарий

Содержание этого поля является приватным и не предназначено к показу.
  • Адреса страниц и электронной почты автоматически преобразуются в ссылки.
  • Доступны HTML теги: <a> <em> <strong> <ins> <del> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <pre>
  • Строки и параграфы переносятся автоматически.

Подробнее о форматировании

CAPTCHA
Проверка на бота
Image CAPTCHA
Copy the characters (respecting upper/lower case) from the image.