среда, 2 декабря 2009 г.

Подсветка динных срок в vim

PEP-8 рекомендует не использовать строки длинее 79 символов. vim позволяет устанавливать подобное ограничение при помощи:


set tw=79

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

au BufWinEnter *.py let w:m1=matchadd('Search', '\%>79v.*', -1)

Что означает: для файлов с расширением "py" подсвечивать части строк, которые превышают лимит.

Read More...

воскресенье, 29 ноября 2009 г.

Хвостовая рекурсия в Erlang'e

Хвостовая рекурсия - это рекурсия только с одним рекурсивным вызовом, когда функция вызывает саму себя только в конце своего выполнения (хвостовой вызов). Все остальные рекурсивные вызовы преобразуются в итерации - оптимизация хвостовой рекурсии. Так экономятся ресурсы на использовании стека вызовов - при увеличении глубины рекурсии, память не растет линейно, а остается постоянной. Это очень важно для Erlang'а, где циклы реализуются только через рекурсию. Но не смотря на важность, оптимизация хвостовой рекурсии выполняется только если рекурсивный вызов является последней операцией в функции, поэтому для следующей функции оптимизация не будет выполнена:


%% Сумма элементов списка
sum([]) -> 0;
sum([H|T]) ->
%% последняя операция - "+"
H + sum(T).

Здесь последней операцией будет сложение, которое может быть выполнено только когда известны значения обоих аргументов. Для преобразования в "правильную" форму используется накапливающий параметр - аккумулятор:

sum(X) ->
sum(X, 0).
%% Результат каждой итерации
%% складывается в Acc
sum([], Acc) ->
Acc;
sum([H|T], Acc) ->
%% хвостовой вызов
sum(T, H + Acc).

sum/1 и sum/2 - это разные функции, поэтому определение sum/1 отделяется точкой, в противном случае при компиляции вылезет ошибка "head mismatch".

Существует мнение, что хвостовая рекурсия выполняется значительно быстрее, чем "обычная", но исходя из мифов об Эрланге, it depends.

Дополнительно о хвостовой рекурсии можно почитать:
- Recursion;
- A Deeper Look at Tail Recursion in Erlang;
- Erlang, Tail Recursion, and Living the Dream;
- Adventures in F#--Tail Recursion in Three Languages.

Read More...

суббота, 28 ноября 2009 г.

STRICT-функции в Postgres

STRICT, он же RETURNS NULL ON NULL INPUT, параметр, указываемый при создании функций в Postgres, означает, что функция возвращает NULL, если ей передается хотя бы один NULL. Благодаря этому можно экономить на вызовах функций - сразу использовать NULL вместо вызова функции с нулевыми аргументами.


create or replace function test_strict(str text)
returns text as
$$
begin
if str is NULL then
raise info 'str is NULL';
else
raise info 'str is %', str;
end if;
return str;
end;
$$
-- По умолчанию функция CALLED ON NULL INPUT
language 'plpgsql'

При вызове этой функции со значением str равным NULL увидим сообщение "INFO: str is NULL". Если в последнюю строку функции добавить STRICT, то сообщение выведено не будет - функция не вызывается:
language 'plpgsql' strict

Такое поведение strict-функций сразу наводит на мысль, что в некоторых случаях можно получить не совсем очевидные результаты. Например, если фукнция возвращает тип boolean, то вместо двух ожидаемых true и false, можно получить еще и NULL:

create or replace function is_equal(v text, t text)
returns boolean as
$$
begin
if v = t then
return true;
end if;
return false;
end;
$$
language 'plpgsql' strict;

select is_equal('test', 'test'), -- true
is_equal('test', 'test2'), -- false
is_equal(null, 'test'); -- NULL

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

Read More...

вторник, 17 ноября 2009 г.

Запуск Python-скрипта из Vim

Ничего IDE'шное Vim'у не чуждо. Для исполнения редактируемого питоновского скрипта достаточно написать в командной строке:


:!python file_name.py

Так как Vim позволяет создавать хоткеи для любой последовательности команд (:help mapping), то можно замапить запуск на нажатие какой-нибудь кнопки. Для этого в .vimrc нужно добавить две строки:

map <F5> :w\|!python %<cr>
imap <F5> <Esc><F5>

В первой строке по F5 файл сначала сохраняется, потом запускается. map - создает хоткей в нормальном режиме. Вторая строка - для режима редактирования (imap). Из режима редактирования Vim переходит в нормальный (как по нажатию Esc), потом в нормальном режиме эмулируется нажатие F5.

Перед запуском скрипта полезно знать, есть ли в нем ошибки. Для этого можно использовать PyLint, PyChecker или Pyflakes. Мне удобнее всего пользоваться последним - работает быстро и не перегружает консоль ворнингами.

После установки Pyflakes (sudo aptitude install Pyflakes) нужно создать в .vimrc команду для проверки файла:

command Pyflakes :call Pyflakes()
function! Pyflakes()
let tmpfile = tempname()
execute "w" tmpfile
execute "set makeprg=(pyflakes\\ " . tmpfile .
"\\\\\\|sed\\ s@" . tmpfile ."@%@)"
silent make
cw
endfunction

И добавить ее вызов перед запуском скрипта:

map <F5> :w\|call Pyflakes()\|!python %<cr>
imap <F5> <Esc><F5>

Вуаля! Теперь по нажатию F5 редактируемый скрипт сохраняется не зависимо от режима, выполняется проверка синтаксиса и, если все ок, выполняется. Хотя это удобно только для одного файла, для целого проекта этого будет маловато.

Read More...

среда, 23 сентября 2009 г.

666 и туалетное чтиво

Недавно решил сменить репертуар туалетного чтива с Маяковского на что-нибудь более практичное. И вот получил первый положительный результат. Читая давно пылившуюся в шкафу книгу "Операционная система Unix", открыл для себя тайный смысл магической команды:
В юниксе права доступа (чтение - r, запись - w, выполнение - e) могут устанавливаться владельцу (u), группе (g) и остальным (o). Например, для того, что бы установить всем классам доступа право на чтение и запись нужно выполнить следующее:
Если в последовательности rwe заменить каждый элемент на 1 в случае наличия и 0 в случае отсутсвия права, а затем полученное число перевести в десятичную систему счисления (rwe => 111 => 7), параметры предыдущей команды можно будет записать более компактно - 666.

Read More...

пятница, 24 апреля 2009 г.

Kyiv Mapping Party

Kyiv Mapping Party 2009 состоится завтра. Приглашаются все любители GPS'ов ;)

Read More...

суббота, 28 февраля 2009 г.

Найти стороны прямоугольника (еще одно решение)

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

На прямоугольник можно наложить сетку с ячейками 1х1. Получится такая картинка:


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

Площадь - сумма площадей ячеек, для нашего случая (1*1=1) она численно равна количеству ячеек - серых и белых.

Если периметр равен площади, значит он численно равен количеству ячеек и на 4 меньше, чем количество серых ячеек, а значит белых ячеек должно быть 4. Это возможно только в 2-х случаях - прямоугольник 6х3 и 4х4:



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

Read More...

четверг, 26 февраля 2009 г.

Найти стороны прямоугольника

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

PS: Задачка для 6-го класса ;)

Read More...

среда, 25 февраля 2009 г.

Hello Ubuntu

Поставил себе на ноут вторую ось - Ubuntu 8.10. Для меня это первый linux, который сразу заработал, без проблем с видео, звуком и т.д. Неработающий wi-fi не считается - все решилось за считанные минуты. Сложнее было найти как у висты отобрать кусок диска - менеджер дисков не позволял за один раз ужать до нужного мне размера.

Наконец-то у меня появился vim :)

Read More...

пятница, 13 февраля 2009 г.

Просто об Erlang'e

Несколько ссылок, где можно доступно почитать об Erlang'e на русском.

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

Обработка ошибок в Erlang - тоже на rsdn'e, тоже перевод.

Erlang по-русски - проект, занимающийся переводом документации на русский. Плюс дополнительный бонус - постоянно обновляющиеся новости о событиях в мире Эрланга.

Erlang в Рисоваське, часть 1, Erlang в Рисоваське, часть 2 - разработчик Рисоваськи раскрывает секреты :) Начало цикла статей об Эрланге и его применении в реальном проекте.

Дополнительно:

Joe Armstrong on Erlang - подкаст на английском с Joe Armstrong'ом, создателем Erlang.

Read More...

среда, 4 февраля 2009 г.

Задачка про вирусы и бактерии

В колонии из Х бактерий, которая каждую секунду увеличивается вдвое, заводится вирус. Каждую секунду он съедает одну бактерию и "рождает" еще один вирус. Обречена ли колония бактерий на полное уничтожение?

Read More...

вторник, 3 февраля 2009 г.

Мешки с деньгами (задача)

Еще одна задача про фальшивое бабло...

Есть 5 мешков с деньгами. Мешки небольшие - в каждом всего по 10 монет. В четырех мешках монеты фальшивые. Фальшивая монета, весом 10 грамм, на один грамм легче настоящей. Как при помощи весов за одно взвешивание определить настоящие монеты?

Read More...

понедельник, 26 января 2009 г.

На свои же грабли...

Недавно писал про with в Python'e и сам же наступил на связанные с ним грабли: некоторые исключения при таинственных обстоятельствах исчезали. Кроме with'а, подозреваемых не было, но следствие показало, что сам по себе оператор в этом не виноват. Причина была в менеджере контекста, функция __exit__ которого всегда возвращала True и тем самым подавлял все возможные исключения.

Read More...

четверг, 22 января 2009 г.

Пример оптимизации кода на Python

Интересный пример оптимизации кода на Python можно посмотреть здесь.

Read More...

четверг, 15 января 2009 г.

The History of Python

Гвидо ван Россум, тот который автор Питона, начал вести блог об истории Питона, который так и называется The History of Python.

Read More...

среда, 14 января 2009 г.

Трабла setHidden у QTreeWidgetItem

Суть проблемы

Есть дерево (QTreeWidget) элементов (QTreeWidgetItem). По событию некоторые элементы нужно скрыть, а скрытые отобразить, для чего используется функция setHidden у QTreeWidgetItem. После фильтрации это все сортируется:

def add_subitems(self, root_item):        
'''Добавить элементы к корневому элементу'''

def add(text, hide=False):
sub_item = QtGui.QTreeWidgetItem(root_item)
sub_item.setText(0, text)
sub_item.setHidden(hide)

map(lambda val: add(*val), ( ('one',),
('two', True),
('three',) ))

def update_subitems(self, root_item):
'''Обновить под-элементы - скрыть или отобразить'''

for index in range(root_item.childCount()):
item = self.root_item.child(index)
# для упрощения скрываются видимые элементы,
# а скрытые отображаются
item.setHidden(not item.isHidden())

self.treeWidget.sortItems(0, QtCore.Qt.AscendingOrder)

Если update_subitems вызывается когда окно скрыто (свернуто в трей), часть вызовов setHidden отрабатывается не правильно и при восстановлении окна из трея пользователь видит не то, что должен видеть. Если убрать сортировку или не скрывать окно - все работает как надо.

Решение

Единственное решение, которое я нашел - отлавливать момент, когда окно отображается (QShowEvent) и обновлять дерево еще раз:
def event(self, ev):
if ev.type()==QtCore.QEvent.Show:
#....
self.update_subitems(root_item)

Read More...

вторник, 6 января 2009 г.

Меньше кодить, больше думать

Джордж Сантаяне: Фанатизм состоит в удвоении Вашего усилия, когда Вы забыли свою цель

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

Read More...

воскресенье, 21 декабря 2008 г.

Qt Creator

Qt Software (так называется Trolltech после покупки компанией Nokia) выпустили бету новой кросс-платформенной IDE для работы с Qt - Qt Creator. На данном этапе среда поддерживает только компилятор gcc и дебагер gdb. Можно так же использовать Microsoft Visual Studio компилятор, но тогда не получится дебажить.

Qt Creator - это не попытка заменить Eclipse и Visual Studio:

Qt Creator is not an Eclipse replacement, but instead a lightweight IDE designed specifically for cross-platform Qt development.

Qt Creator is not a Visual Studio replacement, but instead a lightweight IDE designed specifically for cross-platform Qt development.

Финальный релиз намечается на начало 2009 года. Подробнее можно почитать здесь.

Выглядит это так:



Самореклама: мой второй блог

Read More...

суббота, 20 декабря 2008 г.

1+1=4

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

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

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

Самореклама: мой второй блог

Read More...

пятница, 19 декабря 2008 г.

Бесконечные проекты

Навеяло постом про собеседования.

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

Read More...