Архив за Январь 2010

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

Вот, например, карта зарегистрированных секс-оффендеров в районе Пасадены:

sex-offenders.jpg

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

Кликнув на квадратик, можно посмотреть адрес и фотку преступника:

sex-offender-photo.jpg

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

При походе в парк или устройстве в школу (выделены белыми квадратиками на карте), американец-параноик заходит на сайт и смотрит, сколько рядом секс-оффендеров в округе:

Grace Christian Academy
-----------------------
address:    73 N. Hill Av
Pasadena, Ca 91106
closest offender    0.27 miles
offenders within 1000 ft    0
offenders within 1/2 mile   3

Ближайший к этой школе секс-оффендер находится в 0.27 милях, а в радиусе полмили их целых три.

Некоторые секс-оффендеры, если так решит суд, обязаны иметь таблички на домах и машинах, типа “Тут живет насильник” или “В этой машине едет плохой дядя”:

sex-offender-sign.jpg

Предыдущая заметка была на самом деле работающей программой на языке Lua (“луна”) с бриджем в Objective-C под названием “Луноход”, который я недавно написал-недописал. На скринкасте я показываю, как это работает (включите звук!):

lunokhod-demo.jpg

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

* Обновление: точнее сказать, я мечусь между двумя похожими проектами — на Lua и Scheme, и пока не могу выбрать какой развивать.

-- Это наша программа.

app = Application()

-- А это кнопка.

firstButton = Button:new{

-- У нее есть название,

    title = "Сказать привет",

-- размеры,

    width = 160,
    height = 40,

-- положение

    x = 10,
    y = 10,

-- и действие.

    action = function ()
                print "Привет, мир!"
             end

-- Вот.

}

-- Это вторая кнопка, которая делает то же самое,

secondButton = firstButton:new{

-- только называется по-другому

    title = "Опять сказать",

-- и находится правее.

    x = 170

-- Вот.

}

-- Это окошко, у которого есть название, положение и размеры.

window = Window:new{
    title = "Программа для передачи приветов миру",
    x = 0,
    y = 0,
    width = 360,
    height = 60,

-- А еще в этом окошке есть наши кнопки!

    subviews = { firstButton, secondButton }

-- Вот.

}

-- Теперь мы скажем окошку показаться,

window:show()

-- а программе — запуститься.

app:run()

--[[

Луноход

Это космические технологии. Но не rocket science. Жаль, что на Земле так не пишут.

--]]

Пару дней назад сделал текстовый архив блога с прикольными названиями файлов. Мне лень было разбираться с форматом SQLite-базы Movable Type (кроме того, заметки я писал в HTML, Textile и Markdown в разные времена), поэтому я просто сделал

wget -m http://sellme.ru

и получил копию блога у себя на диске. Потом написал скриптик, который проходился по всем страничкам и выдергивал содержание заметок и комментариев. На выходе получался кусок HTML, который я пропускал через html2text.py и получал красивый простой текст с Markdown-разметкой (пример).

Но этого мне показалось мало: что за названия файлов такие reshil-uznat--russkie-slova.txt? Поэтому из каждой заметки я выдернул заголовок, пропустил его через Google Translate, убрал лишние пробелы, заменив остальные на “-“, и получил красивые имена файлов типа i-decided-to-learn-russian-words.txt (а иногда и смешные: davydov-quot-modern-teaching-omarketinge-is-poluideologie.txt).

Скачать архив sellme-2010-01-09.zip (1.9 МБ)

Это только текст, картинки не включены. Распакованный архив весит 4.5 мегабайт; wc выдает, что я написал 380079 слов. Это уже почти три тома универсальной единицы словоизмерения:

$ wc -w war_and_peace*.txt 
139059 war_and_peace_vol_1.txt
127219 war_and_peace_vol_2.txt
134185 war_and_peace_vol_3.txt
112377 war_and_peace_vol_4.txt
512840 total

Как часто вы пользуетесь CAPS LOCK по сравнению с Control (^)? Хоть в маках основная клавиша-модификатор для команд — Command, я использую ^ очень часто. В терминале (^d, ^c, ^a, ^e) и в текстовых полях Cocoa (^a, ^e, и т.д.). А вот Caps Lock вообще не нужен на клавиатурах.

Поэтому, в Snow Leopard, System Preferences > Keyboard:

caps-lock-control.jpg

Теперь Control будет под левым мизинцем (и на старом месте останется тоже). У меня уже несколько месяцев так настроено и это очень удобно.

Обновление: кстати, лампочка на Caps Lock загораться не будет (до 10.6 для замены Caps Lock на Control приходилось применять хаки, которые не выключали лампочку. Обновление 2: оказывается, еще с 10.4 такое можно было сделать).

Мне был 21 год, когда я запустил этот блог. Сейчас мне 26, и вот как я изменился:

  • Отрастил волосы.
  • Поумнел и стал более циничным.
  • Перестал читать и писать о маркетинге (маркетинга не существует :-).
  • Пересел на Mac.

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

Что осталось без изменения:

Что поменялось в блоге:

  • Из более-менее тематического блога он трансформировался в персональный.
  • Стал писать меньше про бизнес, продуктивность, маркетинг и бла-бла-бла, больше про программирование.
  • Подписчиков на RSS стало пять тысяч двести (и их количество снова стало расти, что странно, учитывая первый и второй пункты).
  • WordPress → TextPattern → самописный движок 1 → самописный движок 2 → WordPress → Movable Type.

sellme-feed-stats.png

Это пока все, что пришло в голову. Ищите меня в твиттере.

Я уже забыл многие программистские термины на русском (заметку про Lua пришлось писать на трех языках), а некоторые и совсем не знал, потому что 1) CS отрасль в России находится в заднице, 2) спал на лекциях, 3) нет литературы на русском языке, 4) не читаю программистскую литературу на русском языке, 5) у программеров есть международный язык — код и комментарии в нем (на английском).

Решил посмотреть термины, которых я не знал. Оказалось, что все словари отстойные: что мультитран, что лингво не знают многих слов. Пришлось погуглить. Некоторые переводы вызвали улыбку (closure — замыкание), и конечно, как обычно все придумывают свои переводы, mark-and-sweep GC — сборщик мусора “отметь и выкинь” или “алгоритм пометок” или “пометить-очистить”

“First-class functions” не нашел (функции первого класса?). IBM до сих пор называет скрипты сценариями. В общем, паника.

Уже не первый раз попадаюсь на утверждение, что strlen() в линуксовом glibc оптимизирована, а у BSD нет. Утверждение “подтверждается” ссылками в соответствующие репозитории:

  1. strlen() в glibc
  2. strlen() в OpenBSD

Посмотрите какой длинный оптимизированный код у glibc и какой обычный тупой у BSD! Вот они, в перевернутом виде:

strlen.png

Появляется еще один аргумент о превосходстве Линукса над BSD! Ура!

И так пока какой-нибудь чел (вроде меня) не полазает по репозиториям и не скажет, что ни та, ни другая версия не используется во многих архитектурах. Достаточно посмотреть, например, в sysdeps/i386/strlen.c в glibc:

    size_t
    strlen (const char *str)
    {
      int cnt;

      asm("cld\n"                   /* Search forward.  */
          /* Some old versions of gas need `repne' instead of `repnz'.  */
          "repnz\n"                 /* Look for a zero byte.  */
          "scasb" /* %0, %1, %3 */ :
          "=c" (cnt) : "D" (str), "0" (-1), "a" (0));

      return -2 - cnt;
    }

и в arch/i386/string/strlen.S в OpenBSD:

    ENTRY(strlen)
        pushl   %edi
        movl    8(%esp),%edi        /* string address */
        cld             /* set search forward */
        xorl    %eax,%eax       /* set search for null terminator */
        movl    $-1,%ecx        /* set search for lots of characters */
        repne               /* search! */
        scasb
        notl    %ecx            /* get length by taking complement */
        leal    -1(%ecx),%eax       /* and subtracting one */
        popl    %edi
        ret

или в i386/string/strlen.s в Apple’овской libc (где используется SSE3, тут приводить не буду, кликайте ссылку).

Не повторяйте этот миф, пожалуйста.

lua.gifНачал недавно изучать Lua (читаю Programming in Lua) и хочу поделиться первыми впечатлениями.

Что нравится:

First-class functions, closures и lexical scoping (простите, не знаю русских терминов).

local p = print

function counter (n)
  return function (i)
            if i ~= nil then n = n + i end
            return n
         end
end

c = counter(0)
p(c) --> function: 0x1001064e0
p(c()) --> 0
p(c(1)) --> 1
p(c(1)) --> 2
p(c(10)) --> 12

x = counter(99)
p(x) --> function: 0x100106880
p(x(1)) --> 100

p("c counter is " .. c() .. " and x counter is " .. x())
--> c counter is 12 and x counter is 100

(как удобно, что комментарии в Lua начинаются с “--”).

Неопределенные переменные и незаданные аргументы функций равны nil.

local a = "something"
print(a) --> something
print(b) --> nil

function welcome (msg, name)
  print(msg .. ", " .. (name or "неизвестный") .. "!")
end

welcome("Привет", "читатель") --> Привет, читатель!
welcome("Привет") --> Привет, неизвестный!

Функции могут возвращать несколько значений.

function div_mul (a, b)
  return a/b, a*b
end

d, m = div_mul(3, 4)
print("division: " .. d) --> division: 0.75
print("multiplication: " .. m) --> multiplication: 12

Это особенно удобно для работы с ошибками:

local f, err = io.open("bogus filename")
if f == nil then
  print("Error: " .. err)
end
--> Error: bogus filename: No such file or directory

Наконец, весь Lua (или вся Lua?) состоит всего из ~16000 строчек ANSI C и у Lua один из самых быстрых интерпретаторов среди динамических языков.

Что не нравится:

  • забываю then после if :)
  • local для определения локальных переменных.

Первое, правда сильно упрощает парсер, судя по всему.