2015-01-24

Ползи, ползи улитка...



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

2015-01-23

Пушкин vs Гоголь

Однажды летом ехали с семейством в Орегон. Совместно решили приобщиться к великому и послушать Пушкина. Что можно найти более русского, чем Пушкин? Слушали старую советскую Радио России, без новых штучек, классику, "Повести Белкина", точнее, "Выстрел", которую когда-то имел честь и счастие читать, будучи в обучении в россейской гимназии, пародон мой френч, в средней школе города Горького.

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

На дороге обратно, по дороге из Орегона, я, желая этот привкус чем-то заесть, включил на том же компакт-диске Гоголя, "Вий". View, по нашему. Это же совсем другое дело! Это солнечный такой, красочный, сочный текст, даже рассказывая про розги, бурсу и голодных бурсаков, текст тем не менее сочный и вкусный. И ничто так не вкусно, как мечты голодранцев об обеде. Слюнки текли так, что пришлось заехать в придорожный "Red Robin" и съесть гамбургер. Тут я и понял разницу между русью Киевской и Московской. Я за Киевскую. В ней больше солнца, больше жизни, больше любви к ней. В ней хотя бы иногда есть что пожрать.

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

Снова Maui



Давненько я ничего не фотографировал. Поэтому ставлю опять декабрьскую фотографию.

Это та самая гора, на вершине которой обсерватория, которую я так люблю фотографировать. Обсерватория, как оказалось двойного назначения - и наука, и наблюдение за спутниками.

Кстати, гребля стоя - это гавайское изобретение.

Снято во время прогулки на катамаране "Pacific Whale Foundation", где я почти встретился с тигровой акулой. Мы тогда приплыли на известное черепаховое место, встали, как только разрешили спускаться в воду, я тут же поплыл от судна. Отплыл довольно далеко, как мне замахали плыть обратно. Я поплыл обратно. Оказалось, что те, кто спускался за мной наткнулись на любопытную тигровую акулу, которая плавала около катамарана. Большую. Среди спустившихся был фотограф, он ее сфоткал, но фотографию бесплатно не дал. А платить тридцатник за мутную фотографию акулы не хотелось. Акула никого не съела, но мы собрались и отплыли на другое место. Акуле, конечно, ничего не стоило бы проплыть за нами, но обычно они не нападают на людей, только по ошибке.

2015-01-21

Sony wearable HDTV, 2D/3D (HMZ-T3W)

Каюсь, около года назад, купил себе вот эту штуку. То есть сначала я заказал попробовать, думая что верну обратно. Покупая в Амазоне, можно вернуть с возвратом полной стоимости. Но оказалось так удобно смотреть иногда вечером кино никому не мешая! Это конечно сибаритство и трата денег. И еще большее сибаритство то, что я ввернул в спальне в стенку держатели, на которые можно вешать гамак и отдыхать после работы. Так вот, эти очки оказались идеальны для просмотра фильма лежа в гамаке.
Шутки про гамак не коментирую.

3D в них выглядит, как и должно выглядеть 3D - нормально и ненавязчиво, так что через 5 минут про него забываешь, увлекаясь сюжетом. Да и не слишком много вокруг 3D фильмов.
У очков множество недостатков, которые описаны в амазоновских review. И тем не менее, получается персональный кинозал. Вечер, зима, кругом темно, ребенок уроки делает, жена за компьютером сидит, а я устав от компьютеров, надеваю эту штуку и оказываюсь в виртуальном мире.

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

Говорят, можно играть в игры, но я не игрок совершенно! Не пробовал.

Я подключил к этой штуке старый Apple TV. На самом деле, она дает 720p. Это не совсем полный HDTV. И оптика у нее та еще. И электроника тоже, когда беспроводной доступ вдруг теряет сигнал. Кстати, да, она умеет делать беспроводной доступ, когда от очков провод к кирпичу в кармане, а дальше уже без проводов. Но, с другой стороны, как-то работает, я к компьютерным глюкам привычный, достаточно, чтобы получать удовольствие.

Для 3D лучше всего подходит sony blue-ray player. Он с очками договаривается и играет не только 3D blue-ray, но даже некоторые 3D фильмы с Netflix. Но можно втыкать hdmi в компьютер, загружать 3D с торрента и смотреть. 3D, как оказалось, это двойная картинка, разделенная либо по вертикали, либо по горизонтали, на две половинки, которые показывают картинки для левого и правого глаза. Этот плейер умеет такие фильмы показывать, надо только переключить во внутреннем меню.

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

Маленькие javascript-ости: простая графика


Это демонстрация работы библиотечки для рисования простых графиков, написанная на typescript для одного моего домашнего проекта. All the sources are inside that post.

2015-01-20

Маленькие javascript-ости: array wrapper

Есть два способа перебрать элементы обычного массива:
for(var i=0; i<a.length; i++){ var e=a[i]; do_something_with(e); }
for(var i in a){ var e=a[i]; do_something_with(e); }
Хотя второй выглядит короче, первый считается быстрее. Если мы возьмем ассоциативный массив, то первый метод неприменим, а второй продолжает работать.

Javascript - идеальный язык для определения всяких wrappers = оберток. Определим такую обертку для массива:
function array_wrap(a){
  return {
    a: a,
    fill: function(n, f){
      for(var i=0; i<n; i++) this.a.push(f(i));
      return this;
      },
    foreach: function(f){
      for(var i=0; i<this.a.length; i++){ var e=this.a[i]; f(i,e); }
      return this;
      }
    }
  }

Тогда мы можем написать вчерашний пример так:
array_wrap([])
  .fill(10, function(i){ return function(){ document.write(i); } } )
  .foreach( function(i, e){ e(); } );
Результат: "0123456789".

На typescript это выглядит еще компактнее:
array_wrap([])
  .fill(10, (i)=>( () => { document.write(i); } ))
  .foreach( (i,e) => { e(); } );

Заметьте, поскольку вызов функции уже присутствует внутри метода foreach, копии значений индекса и значения элемента массива уже сделаны и вызываемое тело может безопасно захватывать их без дополнительных усилий.

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

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

2015-01-19

Маленькие javascript-ости: lambdas and closures.

Subj, все знают? Несмотря на мудреное название, lambda = closure = "замыкание" это просто функция, которая имеет доступ к переменным окружения. Говорят, она их "захватывает", поскольку внутри она должна хранить информацию о них. Зачем замыкание нужно? Чтобы можно было делать отложенные вычисления, определить некоторое действие, которое будет выполнено потом, например, когда пользователь нажмет на кнопку. Или передать некоторое действие в качестве параметра вызываемой процедуре. Напимер типа вот такого:
var found={};
database.iterate_records(
  function(record){ found[record.phone]=record.name; }
  );

Напишем простой тест. Определим десять функций, печатающих числа от 0 до 9 и вызовем их последовательно:
var a=[];
for(var i=0; i<10; i++) a.push(function(){ document.write(i); });
for(var i=0; i<10; i++) a[i]();
Запускаем, получаем: "0123456789". Что и требовалось, так? Ship it!

Теперь изменим немножко заменив переменную во втором цикле:
var a=[];
for(var i=0; i<10; i++) a.push(function(){ document.write(i); });
for(var j=0; j<10; j++) a[j]();
Что ожидаем? То же самое. Что получаем? "10101010101010101010". Как это?
Это очень просто. Замыкание захватывает не значение i в какой-то момент времени, а саму переменную, объект переменной. Выражение document.write(i) печатает текущее значение переменной i сейчас, а те то, которое было в момент, когда создавалась 'function'. Это очень важная особенность javascript, которая часто приводит к большому количеству ошибок.

Ok, скажем мы, давайте изменим, чтобы была не переменная, а выражение:
var a=[];
for(var i=0; i<10; i++) a.push(function(){ document.write(i+' '); });
for(var j=0; j<10; j++) a[j]();
Получаем: "10 10 10 10 10 10 10 10 10 10 ". Не помогает.
Потому, что выражение вычисляется в момент вызова функции, а не в момент создания замыкания.

Сделаем копию:
var a=[];
for(var i=0; i<10; i++){ var ii=i; a.push(function(){ document.write(ii); }); }
for(var j=0; j<10; j++) a[j]();
Получаем "9999999999". Как это?
Потому, что замыкание захватило переменную ii. И текущее значение ii = последнее, что было присвоено = 9.

Ну и что можно сделать? Единственное, что можно сделать в javascript, это вызвать функцию с параметром. Параметры передаются по копии значения, а не по ссылке. Как-то так:
var a=[];
for(var i=0; i<10; i++) a.push(
  function(i){ return function(){ document.write(i); }} (i)
  );
for(var j=0; j<10; j++) a[j]();
Получаем "0123456789". Ура! Заработало. Теперь не забыть писать такое везде, где есть замыкание. Здорово, правда?

Понятно почему так? Здесь i в замыкании и i цикла - разные i. Можно заменить внутреннюю i:
var a=[];
for(var i=0; i<10; i++) a.push(
  function(a){ return function(){ document.write(a); }} (i)
  );
for(var j=0; j<10; j++) a[j]();
Здесь мы определяем функцию и тут же ее вызываем: function(a){...}(i)
Этот вызов создает копию значения переменной i и присваивает его параметру a.
Результатом этой функции будет уже замыкание, которое захватило a, и это a - локальная переменная функции, поэтому каждый вызов порождает новый экземпляр a и каждое замыкание захватывает свою переменную, а не все одну и ту же, как в первых примерах.

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

2015-01-16

Combined Russian-English keyboard layout for Mac (OSX).

I use this layout for more than a year on all my macs, it works just fine: Русско-английская раскладка для OsX с переключением кнопкой CapsLock. Nobody downloaded it yet, so I decided to give one more chance by placing instructions in English.

The combined layout is a single layout, where you have both Cyrillic and English character sets and you can use CapsLock modifier to switch between them. My file combines American layout and Russian Typewriter layouts.

I was using similar layout in Windows before and when I switched to Mac I started to look for a similar solution, but finally I've gave up and done it myself. The layout file is actually just an XML file mapping keyboard codes to unicode characters. There is no code in the layout file, so its safe to install.

Setup:
  1. Download the zip-file.
  2. Open (unpack) zip archive
  3. Copy "us-ru.keylayout" file to the "~/Library/Keyboard Layouts" to install layout for the current user or alternatively to the "/Library/Keyboard Layouts" to install for all users.
  4. If you don't know how to open Library in Finder: use 'Go' menu item in Finder and type "~/Library". It will open that folder.
  5. Open "System Preferences", navigate to "Keyboard / Input Sources", choose "US-RU" and add it to the list of active layouts. You can also make it default.
  6. I recommend to select "Use the same layout in all documents" option in Input Sources.
  7. You need to select this US-RU layout as active using keyboard indicator on menu bar.
  8. The menu indicator stays the same, but CapsLock light would show the actual mode: light on - Russian, light off - English.

There is no "Ё", sorry.

The CapsLock key does switch character set, but doesn't switch input language. Usually apps don't use that information. I don't type in Russian a lot, but it seems everything works just fine. I've tested the layout in Lion and Maverick. I haven't installed Yosemite yet.

Its Ok to ask questions or send me spelling corrections.

2015-01-08

Чудо-юдо-рыба-кит



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

Makena State Park



Сижу и разглядываю отпускные фотографии. Макена - это этот вулканический холм, вокруг которого парк. Справа от него big beach, очень длинный песчаный пляж, с хорошим крупным и глубоким песком. А слева - little beach, закрытый со всех сторон clothing-optional beach, который забит в выходные значительно теснее его большого собрата. И я там был, мед-пиво пил, плавал в море-окияне, золотую рыбку фоткал, желаний не загадывал: чего можно еще желать в таком месте?

2015-01-06

Снежный Леопард



Подарок от Иры на новый год. Висит в рамочке рядом с подарком на прошлый новый год. Нарисован шариковой ручкой.

После дождичка в четверг



Это опять долина реки Snoqualmie. Правда, дождик был в воскресенье ночью. И фотка не моя, а karlson-a, снятая его квадрокоптером. Рекомендую, нетривиальный автор, очень интересный журнал.

2015-01-04

Lake Wenatchee



Я уже много раз снимал это озеро и зимой и летом. Этот State Park - одно из моих любимых мест. В этот раз мы катались на лыжах. Панорама ниже дает примерно 180° view.