Нафталин
Признаться, не помню, чтобы хоть раз встречал нафталин в жизни, кроме как в присказках — обычно это синоним
И вот, копаясь в старом сундуке на чердаке одного из друзей, увидел три пустые упаковки, взял себе, рассмотреть как следует. Инструкция по применению на одной из упаковок гласит:
Нафталин ПРИМЕНЯЕТСЯ для предохранения меховых, шерстяных, ковровых изделий, одежды и обуви от ПОРЧИ их МОЛЬЮ.
Вещи необходимо вычистить и просушить, а затем пересыпать нафталином.
Нафталин необходимо насыпать не на вещи, а на бумагу, которой они перекладываются.
Можно мешочки с нафталином разложить в шкафах или сундуках.
Ценные вещи вешают на плечики, а мешочки с нафталином кладут в карманы или подшивают к подкладке.
Мелкие шерстяные вещи хранят в наволочке, мешках, коробках, на дно которых насыпают нафталин.
Как легко догадаться, нафталин — яд. Отравление им вызывает головные боли, тошноту, рвоту, раздражение слизистых оболочек. Хроническое воздействие нафталина также приводит к нарушению работы печени и поджелудочной железы, вызывает развитие атрофического ринита и фарингита. Помимо этого, он — возможный канцероген.
Думаю, в тех количествах, которые применяли для отпугивания моли, он не опасен, хотя и не изучал этот вопрос.
Нафталин — никакая не «химия» (привет натуропатам!), в природе его выделяет один из видов термитов, чтобы защитить свои гнёзда от муравьёв, грибков и нематод. Добывают его, правда, не из термитов, а из каменноугольного дегтя, закалочного масла и другого сырья.
Выполнение запроса с таймаутом
В продукте, который мы делаем в нашей компании, не используется 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();
}
}После отсылки запроса мы получаем сетевой сокет соединения с базой данных и ожидаем в нём появления данных для чтения. Если за таймаут этого не происходит (или возникает ошибка), то цикл ожидания прерывается, иначе вызывается функция обратного вызова для получения порции данных.
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 число будет преобразовано в строку и искаться будет именно строка, то есть оба этих примера выдадут «Есть».
PHP FFI
В ПХП 7.4 предпринята очередная попытка обзавестись интерфейсом к языку Си. Кажется наконец за это расширение взялись
Для интереса посмотрел что за АПИ получилось. В принципе, всё очень просто. Вот как выглядит
/**
* @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";
}Суть происходящего проста: если директорий удалось создать, то он будет уничтожен, а его имя — выведено на экран, иначе появится текстовое сообщение об ошибке.
19 февраля 1908 года
Продолжаю разбирать находки с чердаков.
Одна из вещей, найденных там, — несколько листков отрывного календаря за 1908 год. Было очень соблазнительно выкладывать по листку в соответствующие даты, но слишком долго ждать, поэтому буду постепенно выкладывать безо всякой системы.
Анекдот меня не впечатлил, а вот «меню» — да. Как я понимаю, это это идеи того, чем можно было бы побаловать гостей в этот день:
Супъ изъ сушеныхъ вишень.
Рыба жареная.
Суфле изъ муки.
Бросился в глаза «суп из сушеных вишен» — очень необычное блюдо, как по мне, никогда о таком не слышал. Я подумал что это в правду
Коронавирус и рукопожатие
Через несколько дней мы собирались лететь в отпуск в Китай,
Весь этот инфошум здо́рово давит на психику и, чтобы понимать реальное положение дел, мне лучшим подспорьем показался канал доктора Комаровского, где он регулярно и популярно рассказывает о том, что известно на текущий момент.
В своём последнем видео доктор призвал тщательно мыть руки, чихать в локтевой сгиб и перестать здороваться за руку со всеми подряд — этой рукой мы потом трём нос и это, по утверждению Комаровского, есть основной канал распространения вируса гриппа.
Я тут подумал, что это хорошо подтверждается статистикой. В основном за руку здороваются мужчины, и 71% заболевших — тоже мужчины. В этом есть даже
Дополнение: рухнула моя теория, друг в комментариях в «Фейсбуке» утверждает, что в азиатских культурах рукопожатие не принято (он живёт в Сингапуре).
Программисты-«волшебники»
Про
Хочу высказаться также по триаде «объект — указатель — ссылка».
Изначально в Си (не «++») ссылок не было. Были только объекты и указатели. Любой начинающий сталкивался с указателями, как только ему требовалось впервые изменить в теле функции значение переданного функции параметра:
void func1(int i) { i = 1; }
void func2(int* i) { *i = 1; }Далее:
int i = 0;
func1(i); // всё ещё i==0
func2(i); // вот теперь i==1Этот код демонстрирует то свойство Си,
Спрашивается, так зачем ещё потребовались ссылки? Ответ таков. В мире существует, не исчезает и даже порой ширится класс
Пусть лучше в теле func2 тоже будет написано
void func1(int i) { i = 1; }
void func1(int &i){ i = 1; }
int i = 0;
func1(i); // волшебного значка нет, i не изменилось
func2(i); // волшебный значок! i изменилось.Смотрите, операторы в теле функций одинаковые, а работает
Программисты Си долго сопротивлялись,
Спички Сапожникова
И снова продолжаю разбирать находки с чердаков.
Иногда среди чердачного хлама попадаются коробки́ спичек, один такой, советских времён, я уже выкладывал. На этот раз хочу поделиться фотографией оборотной стороны дореволюционного коробка.
Мало что проясняющая для современного обывателя надпись «безъ сѣры и фосфора» означает, что спички производились по шведской технологии — без ядовитого белого фосфора (он заменялся красным), а серу, которая сильно воняла при горении (что породило поговорку «сначала вонь, потом огонь»), заменили воском, стеарином или парафином, пропитав ими головку спички.
Как и написано на этикетке, фабрика, произведшая коробок, основана в 1887 году. Её основатель — Иван Исаакович Сапожников родился в деревне Барминская Пустошь Бобинской волости Вятского уезда, вблизи станции Вятка, в семье крестьянина. Однажды Иван Исаакович узнал, что в Слободской волости появился новый промысел — спичечное производство, заинтересовался, разузнал подробности
Сначала работала только семья Ивана, но товар пользовался большим спросом, производство ширилось, вскоре пришлось нанять других крестьян в своей деревне, потом задействовать рабочие руки из других сёл. Спрос рос и Иван Исаакович решил построить собственную фабрику. Купил за бесценок землю на болоте
Дела шли хорошо, продукция стала экспортироваться за рубеж. В 1900 году предприятие Ивана Сапожникова вышло в лидеры губернии: годовой оборот производства составил 260 тысяч рублей, продукция сбывалась в Казанскую, Пермскую, частично в Вятскую губернии, в приволжские города.
В мае 1909 года был учреджён торговый дом с названием «Иван Исаакович Сапожников с сыновьями», а 1916 году открылась ещё одна спичечная фабрика близ слободы Дымково.
Но наступила революция, в 1918 году спичечная фабрика Ивана Исааковича была национализирована и в 1920 году получила название «Красная Звезда». Дальнейшая её история мне уже малоинтересна.
Хоть бренд и исчез, но судя по легкообнаруживаемым на специализированных ресурсах генеалогическим деревьям, потомки Ивана Исааковича
Кто исправит горбатого
Со времён, когда я занимался спортивной гимнастикой, на память осталась травма позвоночника. Сначала в этой связи мало что приходилось делать, разве что иногда посещать довольно неприятные интенсивные массажи, но потом ситуация
Я не знаю когда это произошло,
Основная причина, в моём случае — перенапряжение определённых групп мышц, которые пытались компенсировать повреждение, и в итоге, заспазмировавшись, перекособочили всю спину.
После всех мер, изменения видны невооружённому глазу. Кроме упражнений помогает и специальный массаж, правда пришлось перебрать довольно большое количество массажистов, прежде чем я нашёл такую, которая смогла понять что нужно делать с моими спазмами в мышцах.
А чтобы проблемы не вернулись, приходится работать ещё и над своими привычками — тщательно следить за осанкой, сознательно компенсировать гиперлордоз в пояснице, расслабляя одну группу мышц и напрягая другую, правильно сидеть, не допускать перегиба шеи при работе с ноутбуком и смартфоном.
Последнее, как ни смешно, даётся мне хуже всего. Стоит отвлечься, рука со смартфоном опускается, шея перегибается вниз, плечи сразу сутулятся, поясница и брюшина включают мышцы, чтобы удержать всё в равновесии.
Поскольку на этом сосредоточено много моего внимания, я постоянно замечаю ту же проблему у окружающих — все держат смартфон и ноутбуки очень низко, перегружая шею. Это довольно серьёзная проблема, об этом уже много написано.
Непонятно что делать с этим — ничего или вести
Думаю, делать это в собственном блоге более позволительно, поэтому с невысокой трибуны своего блога хочу всем посоветовать почитать пару статей на этот счёт, испугаться и следить за положением своей головы.
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 тут ничего не делает. Судя по коду модуля, он возвращает функцию как есть и служит маркером, что ниже пойдёт сишная функция. Всё работу выполняет кодек, который подключается первой строкой.
Приём не новый, несколько лет назад я про него уже рассказывал — в Пайтоне в специальном магическом комментарии можно указать кодек, который пропускает через себя текст программы. Обычно он используется для программирования в кодировках, отличных
Итак, код перед выполнением скармливается специальному кодеку inlinec, который разбирает программу, находит в ней
Вьетнам
Вчера прилетели во Вьетнам. Летели ночью, это было немного сложнее, чем я ожидал — жёсткий недосып, сдвиг часового пояса. Вчерашний день — как в тумане, да и сейчас едва соображаю.
Говорят
При этом медицинская грамотность на нуле — здоровые люди ходят в масках (это не уменьшает, а увеличивает шансы заболеть), а те, кто носят маски, нередко освобождают нос — иначе дышать тяжеловато.
Кстати, если вычесть маски от загара (в прошлую нашу поездку во Вьетнам нам рассказывали, что в Азии отсутствие загара считается красивым), то людей в масках не так уж и много, а коронавирус в разговорах не всплывает вообще, в отличие от России, где я слышал о нём каждый день несколько раз.
Погода пока не очень радует — немного пасмурно, море буйное, но хоть тепло — примерно +30°, в Казани сейчас примерно на пятьдесят градусов ниже. Отдохнём от этой странной зимы, в этом году у нас она больше похожа на московскую — слякоть, снегодождь, с редкими заморозками.
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 тысяч итераций.
Конечно
Вьетнамская аптека
За границей иногда сталкиваешься с тем, что привычные понятия означают совсем не то, к чему привык. Мы сейчас во Вьетнаме и у жены очень болит горло — заболело ещё в России. К сожалению, лекарство, которое мы прихватили из дома на такой случай, оказалось перекисью водорода — перепутали похожие пузырьки, поэтому вооружившись
списком латинских веществ, я собрался в аптеку.
Аптеку во Вьетнаме узнать просто, да? На ней так и написано — «АПТЕКА», большими привычными зелёными буквами. В нашем туристическом районе таких аптек —
Вернулся в отель огорчённый, но к счастью, на первом этаже увидел нашего отельного гида. Она и рассказала, что идти с моей проблемой надо не в «аптеку» — это просто разновидность магазина с бухлом и «народной медициной», а в pharmacy — государственные аптеки, где продаются лекарства.
В первой же попавшейся фармаси, которая оказалась прямо через дорогу, мне продали и 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 обёрнут в функцию, которая ничего не возвращает и ничего не должна модифицировать — параметры передаются по значению, а не ссылке. Тем не менее, если вызвать объявленную функцию и передать в неё переменные, их значение будет изменено.
В ПХП для обеспечения производительности используется механизм копирования при записи — если
В силу этой особенности, переменные остаются ссылочными, попадая в таком виде в сишный код, где модифицируются — вызов 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]) от бага не защищает, видимо для этого случая внутри работает
Всё описанное верно для версии актуальной на текущий момент — 7.4.2. Надеюсь, в скором времени этот довольно забавный баг устранят и необходимость в таких ухищрениях исчезнет.
Кручёныховский ад
Эту неделю в Нячанге (туристический город во Вьетнаме), я всё время пытался представить как же тут живут люди (а они тут очевидным образом живут — вокруг нашего отеля очень много жилых пеналов). Пытался представить ровно в том же смысле — поставить себя на место курящего на балконе второго этажа вьетнамского мужика.
За редким исключением, вокруг всегда одни стены, грязные, в чёрной плесени, взгляду не вырваться; очень шумно — даже на моём девятнадцатом этаже слышен шум дороги, ведь движение очень плотное, все сигналят; квартиры, насколько мне видно сверху, — тесные, очень маленькие. Если выйти на улицу, то становится ещё хуже — чёрные от грязи дороги и бордюры, тут же сидящие люди, продающие еду, рядом с ними — кучи объедков и бытового мусора, вокруг пикосекундно сигналящие автомобили и мотоциклы, толпы народа.
Картина не просто безрадостная, это просто ад на Земле! Даже наша холодная девятимесячная зима, уже кажется не такое наказание, как пожизненная ссылка в Нячанг.
Не скрою, приятно съездить сюда погреться на неделю, искупаться
Как бы плохо ни были спроектированы российские города, Нячанг в этом отношении — другая весовая категория. Можно только удивляться как на такой благодатной почве можно было так плохо всё устроить.
Друг наш Лазарь уснул. Я иду разбудить его ★
В фантастике встреча с уже умершими родственниками — нередкая тема, там, кажется, перебрали уже всё — и оцифровку сознания, и заморозку с периодической разморозкой, и восстановление личности по цифровым следами, и много другое.
Я потребляю довольно много фантастики и кажется она меня должна была к этому подготовить, но нет… Когда я смотрю корейский ролик, уже не фантастический, из нашей реальности, где мать встречает в виртуальной реальности свою умершую семилетнюю дочь, мне, пожалуй, жутко. К такому я не готов.
Мне уже 42 и в этом возрасте более чем естественно столкнуться со смертью родственников. Многих из них я иногда вспоминаю, по тем, кто мне был особо близок, — скучаю. Иногда накатывает самая настоящая тоска, например, хочется увидеть бабушек, поговорить,
Видимо для участницы этого эксперимента это своего рода терапия — её дочь умерла несколько лет назад и она до сих пор её не отпустила, искала возможности увидеть её ещё раз, пусть и в таком качестве.
В моём же случае, как кажется, такие встречи только разбередили бы горе. Да и обмануться трудно — ведь ясно же, что в этой симуляции очень мало от прежней личности умершего. Я так понял создатели использовали
Но в будущем технологии обязательно продвинутся настолько, что мы будем способны воспроизвести личность. Большой вопрос — готовы ли родственники к существованию
Наверное ответ тут в том что будет позволено такой личности — плавать в собственной беспомощности, как рыбка в тесном аквариуме, или активно участвовать в жизни общества будущего.
В общем, киберпанк стал на шаг ближе.
99 бутылок: V
71. V — один из языков, за развитием которых я пристально наблюдаю. Искренне желаю ему развития и процветания — под влиянием «Раста», «Гоу»
Сил авторам не занимать — работает (за редким исключением) почти весь заявленный синтаксис, есть компиляция, трансляция в Си и ДжаваСкрипт, а так же обратная трансляция из Си в Ви (на гитхабе есть оттранслированный в Ви «Дум»).
Сильнее всего язык, кажется, похож на Гоу — есть даже синтаксически такой же оператор go, позволяющий запускать
Есть обобщённое программирование (которого так не хватает в Гоу), интерполяция переменных в строках (привычная ребятам, программирующим на ПХП, Перле и шеллах) и ограниченная перегрузка операторов (как в Си++).
Насколько я понял из сайта и блога, язык нацелен на безопасное программирование, скорость, как выполнения (проигрывает Си всего на три процента), так и выполнения и простоту кода. Повторюсь, выглядит очень интересно.
// 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.')
}Коронавирус
Сейчас, когда весь мир в тревоге смотрит на Азию
Если бы не ролик о санитарной обработке в аэропорту вылета, можно было бы вообще не заметить, что под боком там Китай, которого сейчас все боятся, как чумного. Я с интересом ожидал, что же придумают с нами делать в России — видел сообщения об измерении температуры тела прилетающих из Азии, проскакивали
Хорошо, что нас не ждали никакие дополнительные процедуры — в самолёте у меня неожиданно сильно заболела голова, после довольно длинного перелёта с непрекращающейся головной болью и сменой четырёх часовых поясов, дополнительные препятствия к возврату на Родину пережить было бы трудно.
🦠🦠🦠
Кстати в тему — доктор Комаровский, влог которого я завёл привычку слушать, чтобы владеть информацией по коронавирусу, в одном из последних роликов говорил, что у авиакомпаний инструкция — сажать всех болеющих на три последних ряда, с небольшой буферной зоной. Внутри самолётов воздух очищается с бешенной скоростью, ожидается, что такая мера поможет снизить риск заражения в замкнутом салоне. Но видимо инструкция не более чем рекомендательная — на нашем рейсе никакой сегрегации не было, чихающие попадались по всему самолёту.
Гарантийный талон
Про арифмометр «Голден Гем», который я приобретал для Музея вычислительной техники, я уже писал, но недавно снова на него наткнулся (в связи с нехваткой выставочных площадей, некоторые экспонаты лежат у меня дома). Повертел в руках и подумал, что в прошлый раз мало внимания уделил гарантийному листу, а ведь он сам по себе небезынтересный артефакт.
Вряд ли хоть
Как видно из текста, гарантия выдана на год с 30 августа 1913 года на замену любого дефектного механизма в арифмометре «Голден Гем».
Эти довольно популярные арифмометры производила
AppleScript Tetris ★
Я очень люблю «ненормальное программирование» — где вместо получения результата (такого мне и на работе хватает), приходится преодолевать нетривиальные трудности, придумывать
Недостатка в таких задачах у меня в голове не бывает, но руки приложить к ним получается нечасто. «Тетрис» на ЭплСкрипте — один из примеров такого «приложения рук», прошло три года, но он до сих пор мне так нравится, что я решил рассказать о нём ещё раз.
Для начала немного об ЭплСкрипте. Это скриптовый язык для автоматизации, который встроен в МакОС в незапамятные времена — в «Википедии» написано, что он появился аж в 1993 году, то есть широкоизвестный ПХП его младше аж на два года!
Несмотря на то, что язык уже несколько лет не обновляется, заброшенным его не назовёшь, скорее всего в нём просто нечего обновлять — все задачи, которые он призван решать, он решает, в МакОСи есть даже встроенный визуальный редактор и я знаю ребят, которые делают на нём потрясающие вещи в плане создания
Естественно можно программировать и в обычном текстовом редакторе, программы в этом случае выглядят как текст на немного необычном английском языке:
tell application "Microsoft Word" to quit
display dialog "Hello, world!"
print pages 1 thru 5 of document 2Сильно популярным его не назовёшь, но в своей нише он хорош и продвинутые «маководы» о нём знают. До «Тетриса» я писал на нём «песню о пиве» и интерпретатор Брейфака.
За всё историю существования на ЭплСкрипте никто никогда не писал графических интерактивных игр. Причина проста: в языке нет поддержки графики и опроса клавиатуры. ?, расходимся!
Тем не менее идея создать на нём
Первым придумался способ вывода графики — я подумал, что фигуры можно рисовать свёрнутыми окошками
Для этого, в припципе, всё есть — ЭплСкрипт умеет запускать программы и управлять размерами и расположением окон:
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 — моя собственная функция взятия знака, у ЭплСкрипта нет встроенной.
В получившийся вариант вполне можно играть — я пробовал. Немного странное управление через несколько минут уже перестаёшь замечать, единственное, чего не хватает — кнопки сброса фигуры, но тут уж ничего не попишешь.
Если вдруг
Полный исходный код есть на гитхабе.
Китайские удлинители
Я опасался, что
Их удобство в том, что розетки в них — универсальные, сразу на европейскую и китайскую вилку. В детской комнате из связки
Греческая шляпа
Слушали мы недавно в исполнении «Алисы»
Действительно, в сказке есть такое место:
Поглядел Добрыня на берег — нечего ему в руки взять: ни дубинки нет, ни камешка, только жёлтый песок на крутом берегу, да валяется его шляпа греческая.
Ухватил Добрыня шляпу греческую, насыпал в неё песку жёлтого — ни много ни мало — пять пудов — да как ударит шляпой Змея Горыныча — и отшиб ему голову.
Повалил он Змея с размаху на землю, придавил ему грудь коленками, хотел отбить ещё две головы…
Вот что же тут такое Добрыня Никитич насыпал без малого центнер песка?
Гипотез много, самая близкая мне гласит, что «греческая шляпа» — это такой шлем цилиндроконической формы с довольно широкими полями, изображение которого известно каждому школьнику по картине Васнецова «Три богатыря». На ней Добрыня Никитич нарисован слева, как раз в «греческой шляпе».
По интуиции, изумляющей своей точностью совпадения с былинной, маститый художник В.М. Васнецов в картине «Три богатыря» изобразил Добрыню Никитича именно в шлеме данного — византийского — вида. Весьма вероятно, что живописец воспользовался былинной подсказкой, выступив таким образом ранее всех филологов и фольклористов с наглядным и справедливым комментарием к эпическому сюжету «Добрыня и Змей».
— Горелов А.А. — «„Шляпа Земли греческой“ в былинах»
Нельзя не упомянуть, что по основной гипотезе это был обрядовый головной убор дохристианских времён, а сам эпизод сражения — искажённое описание некого обряда низложения реально существовавшего княжича Добрыни, который и явился прототипом былинного героя.
Специалистам виднее, но мне, простому обывателю, более близок простой сюжет драки с реликтовым чудовищем при помощи носимого на голове ведра, которое наполнили песком.
🐉🐉🐉
Недавние жизненные уроки
С тех пор как рассёк до крови бровь, ударившись дома о торец двери, больше не хожу в темноте, вытянув руки вперёд, только загораживая лицо согнутой рукой, локтем от себя.
С последнего ДТП, когда я сильно приложилсся головой о подголовник, проверяю есть ли подголовник вообще, если нет, пересаживаюсь — не хочется в следующем происшествии сломать себе шею.
Насмотревшись роликов про коронавирус из влога Комаровского, стал мыть руки как рекомендуется, — намыливая не менее двадцати секунд, а так же меньше трогать нос правой рукой — через рукопожатие и прочее на руки попадает масса микробов, которые потом так транспортируются на лицо. В сезон простудных заболеваний особенно актуально, надеюсь буду болеть реже.
26 марта 1908 года
Продолжаю оцифровывать бумажные находки с чердаков. В этот раз — очередной лист календаря, на 26 марта 1908 года. Кстати, интересно — отрывные календари ещё продаются?
Прибытие поезда на вокзал Ла-Сьота
Помню когда я получал высшее
Чисто теоретически мы наверное все понимали перспективность направления, но перспектива рисовалась очень уж отдалённой. Но вот прошло двадцать лет и всё изменилось — одна из самых востребованных областей, передний край, масса интересных практических результатов, понятных любому обывателю.
Меня увлекает многое из того, что делается на этом поприще,
Вот и мимо восстановленного алгоритмами машинного обучения самого знаменитого фильма — «Прибытие поезда на вокзал
Нас ждёт удивительное будущее!