Опера Бриттена

Новая «Опера» (69.31КиБ)
Скриншот браузера «Опера» — уютно, как дома

Когда-то я был яростным фанатом «Оперы» — охотно ею пользовался, защищал перед коллегами, знал все её особенности и писал какие-то плагинчики.

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

Дальше в качестве основного браузера я использовал «Сафари» — «Хром» мне казался слишком пресным, «Файэрфокс» — слишком приторным, «Вивальди» — какой-то павлиний хвост, у меня глаза кроваточат, не могу им пользоваться.

Никогда не подумал бы, что вернусь на «Оперу». Однако ж вышел новый релиз, который меня убедили поставить коллеги — и работаю вторую неделю, уютно. Всё на своих местах, есть встроенные «Телеграм» и «Вотсапп», основные мои пейджеры — это очень удобно, есть блокировщик рекламы, ВПН и куча мелочей, облегчающих жизнь. Если вы ещё не видели этот браузер, рекомендую хотя бы попробовать, имеет смысл.
8 комментариев
31 мая 2017 21:23

Присваивания в R

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

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

Сначала небольшой исторический очерк.

В далёком 1964 году на свет появился язык программирования APL — функциональный язык программирования, предтеча разных там «Матлабов» и иже с ними. Язык вводил для своих нужд целую кучу специальных значков в качестве операторов, так что программисты даже использовали специальные накладки на клавиатуры, либо рисовали спецсимволы фломастерами.

Вот так, например, выглядит на «АПЛе» гиковская игра «Жизнь»:
life←{↑1 ⍵∨.∧3 4=+/,¯1 0 1∘.⊖¯1 0 1∘.⌽⊂⍵}
Стрелка слева от слова «life» — операция присваивания, примерно в таком виде она по наследству перешла во многие математические языки, в том числе и в «Эр». Обычное «равно» же в «Эре» использовалось для другой цели — присвоения значений именованным параметрам:
op <- function (..., func) print(get(func)(...))
op(1, 2, 3, 4, 5, func = "sum") # =15
op(4, 2, func = "/") # =2
Пример выше иллюстрирует использование обоих операторов — стрелкой мы присваиваем переменной тело анонимной функции, которая принимает неограниченное количество параметров и один именованный параметр, а ниже указываем значение именованного параметра через «равно».

Как видите, символ деления вполне подходит в качестве имени функции, но об этом как-нибудь в другой раз.

Присваивание стрелкой и наличие в языке «равно», которым нельзя присваивать значения переменным, приводило новичков в замешательство, так что под влиянием более современных языков («Си», «Джавы» и так далее) случилось непоправимое — «равно» стало использоваться и для присваивания тоже, что только усугубило путаницу:
# Присваивание переменной «x» значения «1»
x = 1
f <- function(x) print(x)
# Вызов функции «f» со значением «5» аргумента «x»
f(x = 5)
# Вызов функции «f» с присваиванием переменной «x» значения «5»
# и передачей этого же значения в качестве первого аргумента
f((x = 5))
Казалось бы все операции выше выглядят вполне логично и «равно» тут исправно выполняет новую роль. Но увы. Дело в том, что «Эр» — язык «ленивых» вычислений, выражения в аргументах передаются в функцию не значениями, а промисами, которые будут вычислены в момент использования.

Это означает, в частности, что если аргумент не использовался в функции (выполнение пошло по какой-то ветке, где он не используется, например), то вычислен он не будет. Вот предельно упрощённый случай для иллюстрации:
x = 1
f <- function(x) TRUE
f((x = 5))
print(x) # выведется единица
Так как первый аргумент в функции использован не был, то переданное выражение вычислено не было, а значит и переменная «x» своего значения не изменила. Возможно новичкам и стало проще, но наравне с этим на поле языка рассыпалось несколько новых интересных грабель.

Есть и ещё проблемы. Операции «стрелка» и «равно» имеют разный приоритет и их лучше не использовать в цепочках присваиваний вместе:
# работает, вычисляется справа налево, трактуется как a = (b = 5)
a = b = 5
# работает, вычисляется справа налево, трактуется как a <- (b <- 5)
a <- b <- 5
# выдаст ошибку, так как «стрелка» имеет приоритет выше: (a <- b) = 5
a <- b = 5
# работает, так как «стрелка» имеет приоритет выше: a = (b <- 5)
a = b <- 5
Вообще, конечно, не всё так страшно — можно это всё либо понять (что почти никто не делает), либо запомнить несколько нехитрых правил (прочитав пару хороших книг по языку), либо набить шишки на практике (что чаще всего и происходит).
2 комментария
23 мая 2017 23:08

Счастливые билеты

Мы тут недавно с одним товарищем разговорились про точное количество «счастливых» билетов. В ответ я вспомнил, что как-то очень давно считал их количество на Перле — тогда короткие программы я предпочитал писать на нём. В алгоритмом я не заморачивался — там простой перебор, в комментариях есть указание, что выполняется он за три секунды.

На что товарищ прислал мне ссылку на выписку из статьей о счастливых билетах журнала «Квант». Там, помимо перебора, предлагается несколько методов вычисления, в частности есть даже интеграл: Вычисление через интеграл (12.78КиБ)
Вычисление количества шестизначных счастливых билетов через интеграл

Вообще статьи интересные, умели же раньше писать! Кстати, стало интересно насколько сейчас плох старый-добрый перебор на современных мощностях и интерпретаторах. Взял код из своей заметки в блоге, на пятом Перле и ПХП7 — 0,9 и 0,5 секунды соответственно, вместе с запуском интерпретатора.

Вариант на R, который я наскорую написал по мотивам второй статьи из подборки выглядит вот так:
N <- function (n, k) {
	if (n == 1)
		ifelse(k >= 0 & k <= 9, 1, 0)
	else
		sum(sapply(0:9, function (l) N(n-1, k-l)))
}

lucky <- function (n) {
	0 -> s
	for (k in 0:999) {
		N(3, k) -> v

		if (v == 0) {
			break
		}

		s + v * v -> s
	}

	s
}

print (lucky(3))
Выполняется вместе с запуском интерпретатора за треть секунды, если кому-то интересно, чуть медленнее интеграла. Можно было бы переписать его аккуратнее — накапливать значение N, а не вычислять заново каждый раз.
2 комментария
19 мая 2017 14:16

Сумматор Вебба

Складыватель Вебба (70.97КиБ)
Ранняя модель сумматора Чарльза Генри Вебба, выпущенная между 1868 и 1889 годами

На днях в фонде музея появился экспонат, которому без малого 150 лет — это сумматор Чарльза Вебба. Выпущен он между 1868 и 1889 годами, первая дата — год получения патента на это устройство, вторая — дата выпуска более изящной второй версии устройства, без деревянного основания.

Американский поэт, автор, журналист и изобретатель Чарльз Генри Уэбб родился 24 января 1834 года в Нью-Йорке. Получив начальное образование, в ранней юности убежал в море. По возвращении отправился в штат Иллинойс, куда переехали к тому времени его родители. Затем, с 1856 по 1860 год он занялся бизнесом на берегах реки Миссисипи, позже выращивал пшеницу в Чикаго, участвовал в Гражданской войне в США, а позднее стал банкиром и брокером на Уолл-стрит в Нью-Йорке.

Свою карьеру журналиста Вебб начинал в газете «Нью-Йорк Таймс» в начале 1860-х годов, позже перешел в «Вестник Сан-Франциско», затем редактировал «Калифорнийский» еженедельник и так далее. Он был другом Марка Твена и был известен своей юмористической социальной критикой, опубликовал несколько бурлесков и пьес. Чарльз Уэбб умер в Нью-Йорке 24 мая 1905 года. Заметка о сумматоре (136.35КиБ)
Мировая пресса регулярно писала об удивительных изобретениях Вебба; статья 1869 года

Как изобретатель он имел несколько патентов, несколько из них — на вычислительные машины, в том числе и на упомянутый сумматор, который назывался просто «The Adder».

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

В комплекте было стило, но оно, к сожалению, не сохранилось, как и прочие элементы комплектации.

Порядок использования устройства следующий: в начале работы на сумматоре вручную выставляется ноль на обоих дисках, после чего стило вставляется в отверстие напротив суммируемого числа и диск проворачивается до отметки «ноль». Так числа и складываются — повороты дисков накапливают значение, в окошечке виден текущий результат.
Комментировать
17 мая 2017 21:28

Про две тыловые камеры в смартфоне

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

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

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

Получится отличная мулька — делаешь снимок двумя камерами сразу, он сохраняется в специальном формате и в просмотре при наклоне получается эффект объёма из-за смещения планов. Мне кажется даже «Инстаграмм» сделал бы поддержку, а то они уже не знают какой фигни ещё приделать к приложению.
9 комментариев
17 мая 2017 12:55

Арифмометр «Golden Gem»

Golden Gem (133.65КиБ)
Арифмометр «Голден Гем» с гарантийным талоном до 30 августа 1913 года

Потихоньку двигаюсь к цели — хоть как-то представить в Музее вычислительной техники дореволюционный период, хочется прочувствовать историю.

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

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

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

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

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

На самом устройстве времени выпуска нет (разве что какое-то представление даёт надпись, что ожидаются патенты 1904, 1906 и 1907 годов), но мне повезло — попался экземпляр с гарантийным талоном до 30 августа 1913 года.
4 комментария
14 мая 2017 18:35

Ой, Дуся, ой, Маруся

Сравнение фотографий (225.49КиБ)
Фотография Прокудина-Горского (вверху) и кадр из клипа группы «Отава Ё» (внизу)

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

16 лет назад я как-то писал о Сергее Михайловиче Прокудине-Горском — российском фотографе, архив которого (1800 пластин) за 1907—1915 год был оцифрован библиотекой Конгресса.

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

Сейчас таких ухищрений, естетственно, не требуется.

Фотографии уже много лет делают сенсацию у свежеподключившихся, а 16 лет назад это было свежо настолько, настолько запало в память, что я не раздумывая понял что вижу в кадре — имитацию фотографии «Крестьянские девушки» 1909 года.
7 комментариев
13 мая 2017 12:50

Тридцать пятый выезд за монетами (открытие сезона)

Результат выезда (62.70КиБ)
Результат выезда и первое серебро в этом году — советские 15 копеек 1923

Первый выезд «в поля» в этом году.

¹⁄₄ копейки 1909 года, серебряные 15 копеек 1923, 2 копейки 1929, 3 копейки 1968, 3 копейки 1980, пуговица «Копейкинъ, 1 сортъ, Peterburg», две «конины» плюс обломок, медаль «За доблестный труд в Великой Отечественной Войне 1941—1945 гг.» (поздний вариант медали), пуговица с рисунком, который уже не разобрать, обломок бляшки ремня, крест-лепесток, медное кольцо, пуля, три гильзы «Remington» 1917 года, гильза «Кайнокъ» (английский производитель) того же года, тульская гильза того же года и три гильзы без маркировки.

Безо

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

С употреблением «без» там где нужно «безо» то же — сейчас слышу и вижу везде и очень страдаю.
6 комментариев
4 мая 2017 19:01

Матфей и Стефан

Матфей и Стефан (70.68КиБ)
Мои загадочные предки — Матфей Тимофеевич и Стефан Матфеевич

А вот, например, странная вещь, которая не даёт мне покоя. Есть у меня такая ветка — Стрелковы/Шапкины, я о них писал буквально недавно.

Стефан на рисунке выше — мой прямой предок, прапрапрадед, родился по Бугульмой, в деревне Старое Чирково. Странность в том, что его зовут именно Стефан, а отца — Матфей, оба через «ф», хотя рядом навалом Матвеев и Степанов — записи об их крещении на соседних страницах.

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

Продолжая версию — там Солдатская Письмянка недалеко, одна её сторона называлась в те времена «Панской», может они оттуда? Фамилия «Стрелковы» может указывать на военное происхождение.
8 комментариев
29 апреля 2017 22:22

Дореволюционный «Однер»

Арифмометр Однера (73.83КиБ)
Арифмометр Однера 1906 года, выпущенный фабрикой в Санкт-Петербурге

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

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

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

Благодаря моей бабушке, которая забрала с предприятия списанный «Феликс», я с детства умею обращаться с такими машинками, но этот экземпляр уже не рабочий — сильно заржавел, зато обошёлся дешевле рабочих моделей.
Комментировать
23 апреля 2017 18:31

Огород над печью для обжига

Глазурь на кирпиче (63.08КиБ)
Глазурь на кирпиче, вынутого из стены старинной промышленной печи

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

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

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

Кстати, печь очень большая — проходит не только под их огородом, но и под несколькими огородами соседей. Насколько я понял, дальше раскапывать её не стали, заливать чем-либо — тоже, просто по-прежнему живут над ней надеются, что не обвалится.
Комментировать
22 апреля 2017 23:46

Снова о Стрелковых и Шапкиных

Выписка (77.93КиБ)
Выписка о бракосочетании из метрической книги деревни Новое Исаково

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

На скриншоте выше выписка за 1907 год, где косвенно упомянута смена парадигмы — мой двоюродный прадедушка Василий Павлович записан сразу под двумя фамилиями.
2 комментария
20 апреля 2017 14:14

PostgreSQL и PHP — слон слону не товарищ

Продолжаю серию удивительных открытий в мире перехода на «Постгрес». В документации к функции pg_execute есть малозаметное примечание к последнему параметру — в нём передаются значения для запроса:

Warning Elements are converted to strings by calling this function.

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

Перевод такой: все значения, которые передаются, приводятся к строкам. Код, который это выполняется выглядит так (взял из ПХП 7.2):
if (num_params > 0) {
        int i = 0;
        params = (char **)safe_emalloc(sizeof(char *), num_params, 0);

        ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(pv_param_arr), tmp) {
                ZVAL_DEREF(tmp);
                if (Z_TYPE_P(tmp) == IS_NULL) {
                        params[i] = NULL;
                } else {
                        zval tmp_val;

                        ZVAL_COPY(&tmp_val, tmp);
                        convert_to_cstring(&tmp_val);
                        params[i] = estrndup(Z_STRVAL(tmp_val), Z_STRLEN(tmp_val));
                        zval_ptr_dtor(&tmp_val);
                }
                i++;
        } ZEND_HASH_FOREACH_END();
}

pgsql_result = PQexecParams(pgsql, query, num_params,
                                NULL, (const char * const *)params, NULL, NULL, 0);
Вышеупомянутое примечание есть только у этой функции, но на деле в любом месте, где привязываются значения, всё выглядит примерно так же (это касается и модуля ПДО).

Думаю, это связано с типизацией «Постгреса». Взять к примеру числа — два числовых типа ПХП нельзя адекватно преобразовать в россыпь типов «Постгреса», а если привести к неверному типу будут проблемы — в этой СУБД есть понятие перерузки функций, то есть функция выбирается не только по имени, но и по числу и типам параметров.

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

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

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

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

Мой братишка придумал оригинальное решение — определять позиции на которых мы привязываем числа и автоматически внутри нашего фреймворка в этом месте запроса указывать тип bigint явным образом. То есть добавлять после плейсхолдера параметра конструкцию «::bigint».

Пришлось изменить несколько наших хранимых процедур, но в целом всё плошло довольно гладко.
1 комментарий
13 апреля 2017 21:19

Ускорение пользовательских функций в PostgreSQL

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

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

Ниже две функции на разных языках, поддерживаемых «Постгресом», по смыслу идентичные — обе представляют собой замену функции NVL2 «Оракла» над целыми числами:
CREATE FUNCTION nvl2_plpgsql(a numeric, b numeric, c numeric) RETURNS numeric AS '
BEGIN
  IF a IS NULL
    THEN RETURN c;
    ELSE RETURN b;
  END IF;
END;
' LANGUAGE plpgsql IMMUTABLE;

CREATE FUNCTION nvl2_sql(a numeric, b numeric, c numeric) RETURNS numeric AS '
SELECT CASE WHEN a IS NULL THEN c ELSE b END;
' LANGUAGE SQL IMMUTABLE;
Будет ли какая-то разница в производительности? Посмотрим на тесты:

p95=# EXPLAIN ANALYZE SELECT nvl2_plpgsql(g, 0, 0) FROM generate_series(1, 10000000) _(g);

Planning time: 0.066 ms Execution time: 38881.927 ms

p95=# EXPLAIN ANALYZE SELECT nvl2_sql(g, 0, 0) FROM generate_series(1, 10000000) _(g);

Planning time: 0.253 ms Execution time: 15435.231 ms


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

Это неплохое подспорье, так как у нас такие функции встречаются не только в самих запросах, но и в функциональных индексах, значит ускорятся не только чтения, но и вставки.
Комментировать
11 апреля 2017 21:24