Нафталин

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

Четыре старых бумажных пакета с надписями «Нафталин» от разных аптек и складов, с указанием веса, цены и инструкций по применению.
Упаковки из-под нафталина (одна сфотографирована с двух сторон), найденные на чердаке

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

Нафталин ПРИМЕНЯЕТСЯ для предохранения меховых, шерстяных, ковровых изделий, одежды и обуви от ПОРЧИ их МОЛЬЮ.

Вещи необходимо вычистить и просушить, а затем пересыпать нафталином.

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

Можно мешочки с нафталином разложить в шкафах или сундуках.

Ценные вещи вешают на плечики, а мешочки с нафталином кладут в карманы или подшивают к подкладке.

Мелкие шерстяные вещи хранят в наволочке, мешках, коробках, на дно которых насыпают нафталин.

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

Старая помятая бумажная упаковка нафталина с надписью «НАФТАЛИН КРИСТАЛЛИЧЕСКИЙ», весом 100 г, ценой 80 коп. и инструкцией по применению.
Фото в бо́льшем размере — один из пакетиков, где когда-то лежал нафталин, в жизни размером примерно с ладонь

Думаю, в тех количествах, которые применяли для отпугивания моли, он не опасен, хотя и не изучал этот вопрос.

Нафталин — никакая не «химия» (привет натуропатам!), в природе его выделяет один из видов термитов, чтобы защитить свои гнёзда от муравьёв, грибков и нематод. Добывают его, правда, не из термитов, а из каменноугольного дегтя, закалочного масла и другого сырья.

6 комментариев

Выполнение запроса с таймаутом

В продукте, который мы делаем в нашей компании, не используется PDO для соединения с базой данных — так исторически сложилось и вряд ли имеет смысл менять. Причина тому — оптимизации; мы широко используем эскуэль и задействуем диалектные особенности используемой СУБД (в нашем случае это «Постгрес»). То есть универсальность PDO нам ничего бы не дала.

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

Мы долгое время перебирали идеи (вплоть до внешнего процесса с таймером), но ничего не выглядело достаточно хорошо, чтобы помещать это в код. В конечном счёте мой братишка предложил очень простое решение. Ответ лежал в работе с асинхронным АПИ. Обычно это выглядит как-то так:

$con = pg_pconnect("…");
if ($con === false) {
    throw new \RuntimeException('Could not connect');
}
// асинхронно выполняем запрос, в синхронном варианте тут было бы pg_query
if (pg_send_query($conn, "select * from users")) {
    // тут можно делать что угодно, пока мы не будем готовы принять результат
    // …
    // синхронно получаем результат
    var_dump(pg_get_result($conn));
}

Поскольку pg_send_query неблокирующий, то можно было бы попытаться как-то проконтролировать не истёк ли таймаут. Но как это сделать? Вот что он придумал:

function waitForResult($connection, callable $callback, int $timeout): void
{
    $stream = pg_socket($connection);
    while (pg_connection_busy($connection)) {
        $read = [$stream];
        $write = $except = null;

        $numChangedStreams = stream_select($read, $write, $except, 0, $timeout);
        if ($numChangedStreams > 0 || $numChangedStreams === false) {
            break;
        }

        $callback();
    }
}

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

4 комментария

PHP8 и strpos

Мне очень нравится куда двигается язык ПХП в последние годы. Много вещей удалось исправить, и движение в правильную сторону не останавливается. На список изменений восьмой версии приятно смотреть, кроме пресловутой компиляции «на лету», есть очень много других приятных изменений, в том числе, в ключе поднятой темы, буду убраны некоторые архаичные и вредные штуки.

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

The needle argument of strpos(), strrpos(), stripos(), strripos(), strstr(), strchr(), strrchr(), and stristr() will now always be interpreted as a string. Previously non-string needles were interpreted as an ASCII code point. An explicit call to chr() can be used to restore the previous behavior.

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

// объявили строковую переменную и где-то по коду она превратилась в число,
// 49 — это код символа «1»
$needle = (int) "49";

// выдаёт «Есть»
echo @strpos("12349", $needle) === false ? "Нету\n" : "Есть\n";

// Несколько неожиданно выдаёт «Нету», ищется символ с кодом «49» (единица)
echo @strpos("02349", $needle) === false ? "Нету\n" : "Есть\n";

В ПХП8 число будет преобразовано в строку и искаться будет именно строка, то есть оба этих примера выдадут «Есть».

2 комментария

PHP FFI

В ПХП 7.4 предпринята очередная попытка обзавестись интерфейсом к языку Си. Кажется наконец за это расширение взялись по-серьёзному, и его поддержка не исчезнет со временем, как это уже случалось ранее с прошлыми реализациями.

Для интереса посмотрел что за АПИ получилось. В принципе, всё очень просто. Вот как выглядит функция-обёртка вокруг вызова mkdtemp с обработкой ошибок (проверял у себя на «Маке»):

/**
 * @method object mkdtemp(string $template)
 * @method object strerror(int $errnum)
 * @property-read int $errno
 */
$ffi = FFI::cdef('
    // Импортируем функцию создания временного директория
    char *mkdtemp(char *template);

    // Импортируем функцию перевода кодов ошибок в строку
    char *strerror(int errnum);

    // Импортируем переменную, хранящую коды ошибок
    int errno;
');

/**
 * Фунция для создания временных директориев по маске
 * @param string $template Шаблон создания (см. man mkdtemp)
 * @return string Путь до временного директория
 */
$mkdtemp = function (string $template) use ($ffi): string {
    $result = $ffi->mkdtemp($template);

    if ($result === null) {
        $errno = $ffi->errno;
        $errstr = $ffi->strerror($errno);
        throw new RuntimeException(FFI::string($errstr), $errno);
    }

    return FFI::string($result);
};

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

Не знаю заработает ли этот код без изменений под Линуксом и Виндоузом, у кого есть под рукой, посмотрите, пожалуйста.

В этом примере параметры в импортированные функции передаются как обычные типы ПХП, а некоторые возвращаемые значения требуют конвертации. Так char * возвращается как специальный объект, который нужно преобразовывать в строку вызовом метода FFI::string.

Вот тривиальный текстовый пример использования созданной выше функции:

$template = implode(DIRECTORY_SEPARATOR, [sys_get_temp_dir(), 'ffiphp.XXXXXX']);

try {
    $tmp = $mkdtemp($template);
    rmdir($tmp);
    echo $tmp, "\n";
} catch (RuntimeException $e) {
    echo $e->getMessage(), "\n";
}

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

2 комментария

19 февраля 1908 года

Продолжаю разбирать находки с чердаков.

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

Аверс и реверс календарика на 19 февраля 1908 года: вторник, Масленица, апостолы Архипп и Филимон; анекдот «Два живота» и меню на 20 февраля.
Лист отрывного календаря за 19 февраля 1908 года

Анекдот меня не впечатлил, а вот «меню» — да. Как я понимаю, это это идеи того, чем можно было бы побаловать гостей в этот день:

Супъ изъ сушеныхъ вишень.
Рыба жареная.
Суфле изъ муки.

Бросился в глаза «суп из сушеных вишен» — очень необычное блюдо, как по мне, никогда о таком не слышал. Я подумал что это в правду какой-то экзотический суп, но, судя по рецептам в интернете, это скорее какая-то разновидность сладкой подливки.

2 комментария

Коронавирус и рукопожатие

Через несколько дней мы собирались лететь в отпуск в Китай, но из-за истерии с коронавирусом, которым заболели примерно 0,02‰ (две тысячные процента) китайцев, пришлось буквально в последние дни искать другой тур. Успели взять три последних билета во Вьетнам.

Весь этот инфошум здо́рово давит на психику и, чтобы понимать реальное положение дел, мне лучшим подспорьем показался канал доктора Комаровского, где он регулярно и популярно рассказывает о том, что известно на текущий момент.

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

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

Дополнение: рухнула моя теория, друг в комментариях в «Фейсбуке» утверждает, что в азиатских культурах рукопожатие не принято (он живёт в Сингапуре).

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

Программисты-«волшебники»

Про программистов-«волшебников», большая цитата (ниже весь текст не мой).

Хочу высказаться также по триаде «объект — указатель — ссылка».

Изначально в Си (не «++») ссылок не было. Были только объекты и указатели. Любой начинающий сталкивался с указателями, как только ему требовалось впервые изменить в теле функции значение переданного функции параметра:

void func1(int i) { i = 1; }
void func2(int* i) { *i = 1; }

Далее:

int i = 0;
func1(i); // всё ещё i==0
func2(i); // вот теперь i==1

Этот код демонстрирует то свойство Си, из-за которого он называется «высокоуровневым ассемблером». В тексте языка явно указано, что происходит на уровне ассемблера. В func1 в ячейку на стеке, отведённую под параметры функции, кладут целое значение, i — имя этой ячейки. Туда пишется «1». В func2() в ячейку кладётся указатель i, то есть адрес некоторой другой ячейки, где и лежит значение. В теле явно стоит операция разадресации (*i) — «обратимся к той другой ячейке, адрес которой лежит i». Именно в ту ячейку засовываем «1».

Спрашивается, так зачем ещё потребовались ссылки? Ответ таков. В мире существует, не исчезает и даже порой ширится класс «программистов-волшебников», то есть любителей «программирования с волшебными словами». Программисты-волшебники рассуждают так: запись i = 1; хорошая и понятная. «Присвой i единицу». Запись *i = 1; — противная, компьютерная, не для людей. «Положи „1“ в ячейку, адрес которой лежит в i». Фу.

Пусть лучше в теле func2 тоже будет написано по-человечески: i=1. Однако работает пусть всё, как раньше — func1 получает на стек значение, а func2 — указатель. И оператор присваивания, с виду теперь одинаковый, пусть работает по разному. В func1 — обычное присваивание, в func2 — с разадресацией указателя. А чтобы теперь понять, как это работает, мы введём в язык волшебный значок «&». Теперь всё просто:

void func1(int i) { i = 1; }
void func1(int &i){ i = 1; }
int i = 0;
func1(i); // волшебного значка нет, i не изменилось
func2(i); // волшебный значок! i изменилось.

Смотрите, операторы в теле функций одинаковые, а работает по-разному, и всё из-за волшебного значка! При этом можно даже не разбираться, как это работает, даже не знать про какие-то указатели. Как-то само присваивается, из-за чудесного значка.

Программисты Си долго сопротивлялись, но программисты-волшебники победили, и ссылки появились в Си++.

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

Спички Сапожникова

И снова продолжаю разбирать находки с чердаков.

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

Мало что проясняющая для современного обывателя надпись «безъ сѣры и фосфора» означает, что спички производились по шведской технологии — без ядовитого белого фосфора (он заменялся красным), а серу, которая сильно воняла при горении (что породило поговорку «сначала вонь, потом огонь»), заменили воском, стеарином или парафином, пропитав ими головку спички.

Старая коробка спичек с надписью «Безъ серы и фосфора», фирмой, основанной в 1887 г., и логотипом с якорями.
Задник дореволюционной (1888—1905 гг.) коробки спичек Сапожникова, фирма основана в 1887 году

Как и написано на этикетке, фабрика, произведшая коробок, основана в 1887 году. Её основатель — Иван Исаакович Сапожников родился в деревне Барминская Пустошь Бобинской волости Вятского уезда, вблизи станции Вятка, в семье крестьянина. Однажды Иван Исаакович узнал, что в Слободской волости появился новый промысел — спичечное производство, заинтересовался, разузнал подробности и в 50-х годах 19 века организовал производство спичек на дому.

Сначала работала только семья Ивана, но товар пользовался большим спросом, производство ширилось, вскоре пришлось нанять других крестьян в своей деревне, потом задействовать рабочие руки из других сёл. Спрос рос и Иван Исаакович решил построить собственную фабрику. Купил за бесценок землю на болоте и в 1887-м году открыл фирму «Первая паровая спичечная фабрика И. И. Сапожникова с сыновьями».

Дела шли хорошо, продукция стала экспортироваться за рубеж. В 1900 году предприятие Ивана Сапожникова вышло в лидеры губернии: годовой оборот производства составил 260 тысяч рублей, продукция сбывалась в Казанскую, Пермскую, частично в Вятскую губернии, в приволжские города.

Чёрно-белая фотография: мужчина в тёмном костюме сидит слева, женщина в светлом платье стоит справа, её рука на его плече; фон — студийный с радиальным узором.
Сапожников Иван Исаакович с женой, владелец фабрики в д. Сапожнята (бывш. Барминская пустошь)

В мае 1909 года был учреджён торговый дом с названием «Иван Исаакович Сапожников с сыновьями», а 1916 году открылась ещё одна спичечная фабрика близ слободы Дымково.

Но наступила революция, в 1918 году спичечная фабрика Ивана Исааковича была национализирована и в 1920 году получила название «Красная Звезда». Дальнейшая её история мне уже малоинтересна.

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

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

Кто исправит горбатого

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

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

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

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

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

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

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

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

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

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

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

InlineC

Продолжая тему интерфейсов к языку Си, кстати будет упомянуть появившийся недавно модуль inlinec для Пайтона. Он позволяет вставлять в программу на Пайтоне Си-код довольно естественным способом. Вот пример из документации:

# coding: inlinec
from inlinec import inlinec

@inlinec
def Q_rsqrt(number):
    float Q_rsqrt( float number )
    {
        long i;
        float x2, y;
        const float threehalfs = 1.5F;

        x2 = number * 0.5F;
        y  = number;
        i  = * ( long * ) &y;
        i  = 0x5f3759df - ( i >> 1 );
        y  = * ( float * ) &i;
        y  = y * ( threehalfs - ( x2 * y * y ) );

        return y;
    }

print(Q_rsqrt(1.234))

Я проверил, это действительно работает. Тут вычисляется так называемый быстрый обратный квадратный корень от числа 1,234.

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

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

Приём не новый, несколько лет назад я про него уже рассказывал — в Пайтоне в специальном магическом комментарии можно указать кодек, который пропускает через себя текст программы. Обычно он используется для программирования в кодировках, отличных от ЮТФ-8, но ничего не мешает использовать его иначе.

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

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

Вьетнам

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

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

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

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

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

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

7 комментариев

PHP: FFI vs. exec

Нередко отсутствующую в ПХП функциональность наскоро заменяют вызовом утилит командной строки. И мне стало интересно взглянуть на досуге — может ли вызов через ffi (интерфейс к Си, который появился в ПХП 7.4) быть хорошей альтернативой.

Говорят, вызов через ffi работает очень медленно, такова природа этого способа (и мы это видим в других языках), это, конечно, очевидно, но медленно насколько?

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

$mkdtemp = function (string $template): string {
    $cmd = '/usr/bin/mktemp -d '.escapeshellarg($template);
    $dir = exec($cmd, $out, $ret);

    if ($ret === 0) {
        return $dir;
    } else {
        ['message' => $message, 'type' => $type] = error_get_last();
        throw new RuntimeException($message, $type);
    }
};

Весь код был обёрнут в цикл на 10000 итераций и запущен. Я провёл по десять запусков, а результат усреднил.

Создание директория через ffi заняло примерно 0,77 секунд на 10 тысяч итераций, а через утилиту командной строки — примерно 72,62 секунды на те же 10 тысяч итераций.

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

4 комментария

Вьетнамская аптека

За границей иногда сталкиваешься с тем, что привычные понятия означают совсем не то, к чему привык. Мы сейчас во Вьетнаме и у жены очень болит горло — заболело ещё в России. К сожалению, лекарство, которое мы прихватили из дома на такой случай, оказалось перекисью водорода — перепутали похожие пузырьки, поэтому вооружившись
списком латинских веществ, я собрался в аптеку.

Белый внедорожник Toyota на улице перед магазином «МАГАЗИН 1001 АПТЕКА» с вывеской на русском и вьетнамском, под густой сетью проводов; рядом — мотоциклы и дорожные знаки.
Вьетнамская АПТЕКА — не то заведение, куда надо идти, когда болеешь

Аптеку во Вьетнаме узнать просто, да? На ней так и написано — «АПТЕКА», большими привычными зелёными буквами. В нашем туристическом районе таких аптек — пруд-пруди. Потыкавшись в шесть-семь дверей, я стал понимать, что захожу не по адресу — продавцы странно на меня смотрели и смеялись по-аптекарски.

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

Вывеска аптеки «PHARMACY QUẦY THUỐC GPP SỐ 3» компании «CÔNG TY CỔ PHẦN DƯỢC PHẨM KHÁNH HÒA», адрес: 27 Nguyễn Thị Minh Khai.
Фармаси — вот куда стоит идти, здесь продаются лекарства

В первой же попавшейся фармаси, которая оказалась прямо через дорогу, мне продали и chlorhexidine под маркой «Medoral», и вполне узнаваемый «Стрепсилс» во вьетнамской пачке. Инструкцию по применению провизор изобразила пантомимой, моего вьетнамского не хватило, чтобы объяснить, что я уже сталкивался с этим лекарствами.

В общем, если болеете, не проблема, надо только знать куда зайти за лекарством.

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

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

Забавный баг в FFI (PHP 7.4.2)

В последнее время очень заинтересовался FFI в ПХП — интерфейсом к языку Си, появившимся в версии 7.4. Очень полезное, как по мне, нововведение, позволяющее расширять язык, обходясь минимальными знаниями о других языках программирования.

Очевидно, потребность в чём-нибудь таком давно назрела, появлялся даже специальный язык для написания расширений — «Зефир», очень похожий на ПХП, принципиальных отличий нет, порог входа — низкий. При этом он транслируется в Си, благодаря чему достигается почти нативная производительность.

К несчастью, модуль FFI в ПХП только-только появился и содержит по меньшей мере один очень неприятный баг, который может привести к труднопонимаемым ошибкам в программах.

Небольшой код для иллюстрации проблемы:

const IRRELEVANT = "Hello ";

echo IRRELEVANT;  // Выведет «Hello»

FFI::cdef('char *memcpy(char *dst, const char *src, size_t len);')
    ->memcpy("Hello ", "world!", 6);

echo IRRELEVANT; // Выведет «world!»

В чём суть? Мы объявляем константу IRRELEVANT, убеждаемся, что она содержит присвоенное ей значение, потом вызываем через FFI копирование одной строки в другую, и константа внезапно меняет своё значение. Как это произошло? Чтобы понять, немного модифицируем программу.

function memcpy(string $dst, string $src):void
{
    FFI::cdef('char *memcpy(char *dst, const char *src, size_t len);')
         ->memcpy($dst, $src, strlen($src));
}

$rock1 = str_repeat('ROCK', 1);
$rock2 = str_repeat('ROCK', 1);

var_dump($rock1, $rock2); // Выведет «ROCK» два раза

memcpy($rock1, "SOCK");
memcpy($rock2, "LOCK");

var_dump($rock1); // выведет «SOCK»
var_dump($rock2); // выведет «LOCK»

Что у нас тут? Вызов memcpy обёрнут в функцию, которая ничего не возвращает и ничего не должна модифицировать — параметры передаются по значению, а не ссылке. Тем не менее, если вызвать объявленную функцию и передать в неё переменные, их значение будет изменено.

В ПХП для обеспечения производительности используется механизм копирования при записи — если куда-то переменную нужно передать по значению, то интерпретатор для скорости передаёт её по ссылке, а если требуется модификации переданного значения, копирует его. Модификацию отслеживает сам интерпретатор, но в случае FFI этого, по всей видимости, не происходит.

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

Кстати, если изменить строку инициализации переменных на вот такую:

$rock1 = $rock2 = str_repeat('ROCK', 1);

то после вызовов memcpy обе переменные получат значение «LOCK» — работает тот же самый механизм.

Почему же в первом листинге изменилось значение константы? Сейчас разберёмся, осталось совсем немного.

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

Таким образом константа IRRELEVANT и строка «Hello » в первом параметре — суть одна и та же область памяти. Когда функция memcpy модифицирует эту область, меняются сразу все значения всего, что, для оптимальности, ссылается на это же место. Естественно, константа изменяется тоже.

Поскольку интернирование не работает во время выполнения, результат str_repeat('ROCK', 1); не интернируется и во втором листинге такого эффекта не создаётся.

Как же разорвать эту мистическую связь и заставить работать код так как задумывалось? Для этого нужно, чтобы интерпретатор создал новую область памяти, которую будет портить FFI, не затрагивая нашу переменную. Это можно сделать, например, при помощи уже упомянутой функции str_repeat:

function memcpy(string $dst, string $src):void
{
    // Создаём новое место, которое испортит memcpy
    $dst = str_repeat($dst, 1);
    FFI::cdef('char *memcpy(char *dst, const char *src, size_t len);')
        ->memcpy($dst, $src, strlen($src));
}

$rock = 'ROCK';
var_dump($rock); // Выведет «ROCK»

memcpy($rock, "SOCK");
var_dump($rock); // Так же выведет «ROCK»

Внимание! Это некорректный способ, корректный описан в более поздней заметке.

Естественно, подойдут и substr, и sprintf, и вообще любые функции, в общем случае возвращающие модифицированную строку. Интересно, что implode([$dst]) от бага не защищает, видимо для этого случая внутри работает какая-то оптимизация, возвращающая значение $dst по ссылке до первой модификации.

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

10 комментариев

Кручёныховский ад

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

Зимний городской пейзаж: заснеженная дорога с движущимися автомобилями, высокие жилые дома на фоне пасмурного неба, голые деревья и металлические ограждения.
Я даже потрудился сфотографировать этот вид по направлению взгляда курившего мужика

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

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

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

Чёрно-белая графика: женщина с серьёзным взглядом держит ребёнка, рядом — силуэт другого человека; экспрессивные мазки, контрастные тона, эмоциональная сцена.
Иллюстрация из поэмы «Игра в аду» Хлебникова и Кручёных (издание 1912 года) : «Покой и мрачен и громоздок, // Деревья — сероводород. // Здесь алчны лица, спертый воздух — // Тех властелинов весел сброд.»

Картина не просто безрадостная, это просто ад на Земле! Даже наша холодная девятимесячная зима, уже кажется не такое наказание, как пожизненная ссылка в Нячанг.

Не скрою, приятно съездить сюда погреться на неделю, искупаться в Южно-Китайском море, покататься на слоне, погладить оленей в бухте Ня Фу, поесть свежайших морепродуктов и стоящего копейки манго, и обратно, в унылую Россию, всё, повеселился!

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

6 комментариев

Друг наш Лазарь уснул. Я иду разбудить его ★

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

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

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

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

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

Но в будущем технологии обязательно продвинутся настолько, что мы будем способны воспроизвести личность. Большой вопрос — готовы ли родственники к существованию в каком-то ином качестве? Или вот лично я? Готов ли к тому, что после смерти моё «я» откроет виртуальные глаза в виде какого-то хитрого тамагочи для моих потомков?

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

В общем, киберпанк стал на шаг ближе.

3 комментария

99 бутылок: V

71. V — один из языков, за развитием которых я пристально наблюдаю. Искренне желаю ему развития и процветания — под влиянием «Раста», «Гоу» и чего-то вроде Пе́рла, у авторов получается довольно интересный язык, который пока, правда, находится в стадии альфы.

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

Сильнее всего язык, кажется, похож на Гоу — есть даже синтаксически такой же оператор go, позволяющий запускать что-нибудь в отдельном потоке (позднее обещают сделать корутины), но и уши «Раста» торчат даже в моей небольшой программе: совпадение с образцом, условные операторы-конструкции, константные переменные (если не указан mut).

Есть обобщённое программирование (которого так не хватает в Гоу), интерполяция переменных в строках (привычная ребятам, программирующим на ПХП, Перле и шеллах) и ограниченная перегрузка операторов (как в Си++).

Насколько я понял из сайта и блога, язык нацелен на безопасное программирование, скорость, как выполнения (проигрывает Си всего на три процента), так и выполнения и простоту кода. Повторюсь, выглядит очень интересно.

// 99.v by Evgeny Stepanischev Feb 2020

fn bottles(beer byte) string {
    return match beer {
        0 {
            'no bottles'
        }
        1 {
            '1 bottle'
        }
        else {
            '$beer bottles'
        }
    }
}

fn main() {
    mut b := bottles(99)

    for i := 98; i >= 0;  {
        println('$b of beer on the wall, $b of beer.')
        b = bottles(i--)
        println('Take one down and pass it around, $b of beer on the wall.\n')
    }

    println('No more bottles of beer on the wall, no more bottles of beer.')
    println('Go to the store and buy some more, 99 bottles of beer on the wall.')
}

2 комментария

Коронавирус

На экране двое работников в защитных костюмах проводят дезинфекцию зала ожидания; внизу надпись: «Температурный контроль работает постоянно, другие меры безопасности также активны
Процесс обеззараживания камраньского аэропорта, ролик во вьетнамском аэропорту

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

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

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

🦠🦠🦠

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

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

1 комментарий

Гарантийный талон

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

Гарантийный талон от Automatic Adding Machine Co. (Нью-Йорк, 30 августа 1913 г.) на сумму № G 52316: гарантия на год замены дефектного механизма «Golden Gem» при возврате машины.
Гарантийный талон от арифмометра «Голден Гем» с гарантией от 30 августа 1913 года

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

Как видно из текста, гарантия выдана на год с 30 августа 1913 года на замену любого дефектного механизма в арифмометре «Голден Гем».

Эти довольно популярные арифмометры производила нью-йоркская компания «Automatic Adding Machine Co.» до первой половины 20-го века. На заграничных онлайн-аукционах такие машинки не редкость, но мне похоже очень повезло купить экземпляр с инструкцией и гарантийным листом — других таких лотов я не вижу. Возможно их не так много сохранилось — всё-таки бумага штука недолговечная.

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

AppleScript Tetris ★

Я очень люблю «ненормальное программирование» — где вместо получения результата (такого мне и на работе хватает), приходится преодолевать нетривиальные трудности, придумывать какие-то нестандартные ходы и решать нерешаемые задачи.

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

Для начала немного об ЭплСкрипте. Это скриптовый язык для автоматизации, который встроен в МакОС в незапамятные времена — в «Википедии» написано, что он появился аж в 1993 году, то есть широкоизвестный ПХП его младше аж на два года!

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

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

tell application "Microsoft Word" to quit
display dialog "Hello, world!"

print pages 1 thru 5 of document 2

Сильно популярным его не назовёшь, но в своей нише он хорош и продвинутые «маководы» о нём знают. До «Тетриса» я писал на нём «песню о пиве» и интерпретатор Брейфака.

За всё историю существования на ЭплСкрипте никто никогда не писал графических интерактивных игр. Причина проста: в языке нет поддержки графики и опроса клавиатуры. ?, расходимся!

Тем не менее идея создать на нём что-то подобное «Тетрису» мучала меня несколько лет, видимо интуиция жужжала где-то в фоне, что это возможно.

Первым придумался способ вывода графики — я подумал, что фигуры можно рисовать свёрнутыми окошками какой-нибудь программы, например обычного маковского текстового редактора. В моём воображении это выглядело примерно так:

Четыре одинаковых элемента интерфейса с кнопкой «Helvetica» и иконкой шрифта, расположенные в два ряда по три и один.

Для этого, в припципе, всё есть — ЭплСкрипт умеет запускать программы и управлять размерами и расположением окон:

tell application "TextEdit"
    set the bounds of 1st window whose id is wid to {x, y, (x + |size|), (y + |size|)}
end

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

На снежном стекле нарисованы чёрными точками контур дома и несколько снежинок, на заднем плане видны ели.

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

В первом же прототипе появилась ещё одна проблема — наверху у «МакОСи» есть строка меню, приложения не могут на неё залезать, при попытке вывести в эти координаты окно, оно «сползает» вниз. В итоге первые несколько точек выводились в других координатах и всё рушилось. Было два решения — центрировать ещё и по вертикали или как-то измерить размер меню (кодировать его высоту константой мне показалось плохим решением — вдруг изменится).

В итоге, способ придумался. Сразу после запуска я вывожу окно в нулевые координаты и смотрю на сколько пикселей оно съехало, это и будет высотой меню:

-- Get height of menu bar
tell application "TextEdit"
	activate
	make new document at the front
	set the bounds of 1st window to {0, 0, 0, 0}
	set coords to bounds of 1st window
	close 1st window
end

set minimalY to coords's item 2

С графикой разобрались, а что с клавишами? В ЭплСкрипте, как я уже говорил, нет способов опросить клавиатуру, существуют плагины и сторонние решения, но их использование рушит всю идею. Хотелось чистого решения.

Голову пришлось ломать очень долго, пока в один момент я не додумался заиспользовать под это опрос значения громкости — уменьшение и увеличение громкости как кнопки влево/вправо, а отключение динамика — для поворота фигуры.

Панель управления медиаплеером с кнопками: закрыть, яркость, режимы отображения, перемотка, воспроизведение, громкость.
Сейчас на моём «Макбуке» аппаратных кнопок громкости уже нет, но «Тетрис» слушается и нарисованных на тачбаре

Для этого на пуске я устанавливаю громкость на середину и в цикле опрашиваю текущее значение. После каждого изменения значение опять сбрасывается на среднее:

on levelReset()
    set volume output volume volumeMiddle without muted
end

on checkDirection()
    set level to output volume of (get volume settings)
    levelReset()
    _sign(level - volumeMiddle)
end

on checkRotate()
    return output muted of (get volume settings)
end

Тут _sign — моя собственная функция взятия знака, у ЭплСкрипта нет встроенной.

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

Если вдруг кому-то станет интересно запустить игру, то убедитесь, что всё, что у вас есть во встроенном текстовом редакторе (TextEdit) сохранено, — приложение создаст целую кучу мелких дополнительных окон, которые не будут очищены после остановки программы, их придётся закрыть вручную, в этом случае легко потерять что-нибудь нужное.

Полный исходный код есть на гитхабе.

2 комментария

Китайские удлинители

Белый удлинитель с тремя вставленными блоками питания (белым, чёрным и белым с кабелем) и рядом стоящий портативный фонарь с металлической решёткой на белой поверхности у стены.
«Умная» китайская розетка, воткнутая в глупый китайский удлинитель

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

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

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

Греческая шляпа

Слушали мы недавно в исполнении «Алисы» русскую-народную сказку про Добрыню Никитича и Змея Горыныча. Я не особо внимательно слушал, но потом, когда дочка в игре повторяла историю этих двух персонажей, обратил внимание на какую-то «греческую шляпу».

Действительно, в сказке есть такое место:

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

Ухватил Добрыня шляпу греческую, насыпал в неё песку жёлтого — ни много ни мало — пять пудов — да как ударит шляпой Змея Горыныча — и отшиб ему голову.

Повалил он Змея с размаху на землю, придавил ему грудь коленками, хотел отбить ещё две головы…

Три воина в доспехах на конях: один на белом с копьем, другой на черном с щитом и мечом, третий на гнедом с луком; они стоят на холме под облачным небом.
Добрыня Никитич, Илья Муромец и Алёша Попович на картине Васнецова

Вот что же тут такое Добрыня Никитич насыпал без малого центнер песка?

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

По интуиции, изумляющей своей точностью совпадения с былинной, маститый художник В.М. Васнецов в картине «Три богатыря» изобразил Добрыню Никитича именно в шлеме данного — византийского — вида. Весьма вероятно, что живописец воспользовался былинной подсказкой, выступив таким образом ранее всех филологов и фольклористов с наглядным и справедливым комментарием к эпическому сюжету «Добрыня и Змей».

— Горелов А.А. — «„Шляпа Земли греческой“ в былинах»

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

Специалистам виднее, но мне, простому обывателю, более близок простой сюжет драки с реликтовым чудовищем при помощи носимого на голове ведра, которое наполнили песком.

🐉🐉🐉

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

Недавние жизненные уроки

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

С последнего ДТП, когда я сильно приложилсся головой о подголовник, проверяю есть ли подголовник вообще, если нет, пересаживаюсь — не хочется в следующем происшествии сломать себе шею.

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

10 комментариев

26 марта 1908 года

Страницы календаря на 26 марта 1908 года: день недели, церковные праздники, восход/заход солнца, стих А. Жемчужникова и меню на 27 марта.
Лист отрывного календаря за 26 марта 1908 года

Продолжаю оцифровывать бумажные находки с чердаков. В этот раз — очередной лист календаря, на 26 марта 1908 года. Кстати, интересно — отрывные календари ещё продаются? Кто-то ими пользуется? Я помню, что в моём детстве у бабушек они ещё висели, а родители ими уже не пользовались.

4 комментария

Прибытие поезда на вокзал Ла-Сьота

Помню когда я получал высшее в 90-е, специализация «Искусственный интеллект» была самая осмеиваемая среди студентов, расхожая шутка тех времён — что туда шли те, у кого естественного интеллекта не было. Эта область тогда и правда выглядела сомнительно, не могла похвастаться какими-то интересными практическими результатами, да и идти работать по специализации было просто некуда, разве что оставаться в Университете, заниматься наукой.

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

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

Вот и мимо восстановленного алгоритмами машинного обучения самого знаменитого фильма — «Прибытие поезда на вокзал Ла-Сьота» братьев Люмьер (1896 год) я пройти не смог. Найдите на Ютубе оригинал и посмотрите из чего нейросети смогли сделать 60 кадров в секунду и 4К-картинку!

Нас ждёт удивительное будущее!

11 комментариев

← сюда туда →