?

Log in

No account? Create an account
nyaload

Журнал Пушыстого

Журнал Пушыстого

Entries by category: it

Как закрыть панель в Blender
nyaload
_winnie
Blender - наиболее популярный свободный и кроссплатформенный редактор для создания 3d-анимации. В добавление к созданию анимации - там есть поддержка монтажа нарендеренного. Сегодня немножко потыкался в его UI. Как ни странно, это единственная программа которую я нашёл, в которой можно редактировать видео для простого монтажа в разных форматах. В других - то .wmv не загружается, то .mov не загружается (и похоже нет ни одной программы, которая могла бы резать видео по key-frames без перекодировки в разных форматах-контейнерах, включая mov, wmv, avi, mkv).

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

Если вы не осознали, что тут выше написано - то ничего страшного, я тоже не понял, пока я не посмотрел ролик на ютубе.

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


Вопрос на stackexchange, как закрывать панели в blender - http://blender.stackexchange.com/questions/1223/how-to-close-open-a-view-panel
Ролик на ютубе, объясняющий как закрывать панели в blender - https://www.youtube.com/watch?v=AMBi1R7KB48
Человек полгода работающий в blender, спрашивает как закрывать панели - http://blenderartists.org/forum/showthread.php?234374-Closing-Split-Screens

Говорят, что это более удобно, чем то что было в более ранних версиях, <2.6

Видно, не один я был в тупике, как же это делается:


Это не единственная непривычная вещь в интерфейсе. Ещё есть кастомный Open/Save File диалог, в котором нельзя открыть файл по его абсолютному пути (два отдельных текстовых поля для директории и имени файла). И кастомная логика сохранения проекта. Благодаря которой я несколько раз закрыл проект, не сохранив - дефолтная кнопка при закрытии это "да, выйти не сохранив", вместо привычного "выйти и сохранить". Если закрыть по 20-летней привычке Open/Save File диалог крестиком - то закроется текущий проект, а не этот диалог. Если не прочитать внимательно модальный диалог при закрытии Open/Save - то выход будет без сохранения. Это то, об что я стукнулся лбом при освоении самой базовой функциональности и UI блендера.

Видимо, разработчики Блендера совсем не наблюдали, какие проблемы возникают у начинающих, и не считают благим делом сокращение времени обучения.

Иммутабельность мешает иммутабельности
nyaload
_winnie
Всё-таки мутабельность объектов в небольших пределах - иногда весьма облегчает написание алгоритмов. Это здорово, когда можно в небольшом обозримом участке кода создать объект A, перебросить на него указатели из другого уже созданного объекта B (который мы только что создали), и отложить заполнение полей A до того момента, когда они станут известны. Но в иммутабельном языке - невозможно создать объект, пока мы не знаем все параметры для его создания, и это дико мешает при переложении известных алгоритмов на такой язык. Нужно вводить дополнительные структуры данных, чтобы поменять порядок создания объектов A и B, так как мы в случае иммутабельности не можем создать A, а потом провести из него указатель в B.

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

Это, например, мешает переписывать из википедии алгоритм персистентного красно-черного дерева на такой язык. Там есть подзадача, похожая на такую: в односвязном списке поменять значение ноды с удаляемым значением где-то внутри списка на значение из ноды в конце списка. Список персистентный, поэтому "поменять" означает "создать клон с нужным изменением".
В языке, где можно менять значения полей объекта - всё тривиально, решается в один проход от начала до конца списка.
Идем от начала до нужной внутренней ноды списка, пока идём - создаем дубликаты проходимых нод. Когда нашли нужную ноду - запоминаем указатель на её дубликат, доходим до конца списка, копируем значение в созданный дубликат. Лишней памяти, при условии что нам надо сохранить и старый список (персистентность в copy-on-write её варианте) - не тратится.


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

shared_ptr
nyaload
_winnie
У std::(boost::)shared_ptr в блоке, который хранит счетчик, есть ещё указатель на функцию удаления (deleter), который запоминается в момент создания shared_ptr
Это позволяет:
* не париться с виртуальным деструктором, если мы кастуем shared_ptr<derived> в shared_ptr<base> (not recommended, если shared_ptr это не единственный указатель в проекте).
* не париться с переносом деструктора из .h в .cpp, когда делаем PImpl
* передавать shared_ptr в другой модуль, у которого свой собственный аллокатор памяти и свой delete
* Вообще не привязывать способ удаления к типу в shared_ptr (можно использовать свой кастомный аллокатор, и пользователям shared_ptr<T> не нужно знать, какой аллокатор использовался при создании T).

Так же у shared_ptr есть отдельный счетчик для weak-ссылок (иногда нужно в многопоточном программировании и прочих случаях "мы не можем статически отследить вложенность lifetime").

Функция make_shared позволяет не делать две аллокации на счетчик и объект, объединяя их в один кусок памяти.
Tags:

binary search
nyaload
_winnie
В книге "жемчужины программирования" сообщается, что невозможно написать binary search с первого раза.

На самом деле его невозможно написать с первого раза, если не осознаешь что такое инвариант цикла. Если осознаёшь - то скорее всего запросто напишешь (я вот уже в третий раз за год написал).

Если не осознаёшь инвариант цикла, то с большой вероятностью будет одна из ошибок:

* mid = (lo+hi)/2 или hi/2+lo/2 ? (и нет, дело не в overflow, эти формулы просто разные (1+3)/2 != 1/2 + 3/2 ).Read more...Collapse )

Как писать двоичный поиск чтобы он не бажил:
* Выбрать инвариант "если искомый элемент существует, то он в [lo, hi)", изначально выбрать lo,hi = 0, N.
* mid = lo+(hi-lo)/2 (при этом для кода верно утверждение "промежуток длиннее 1 всегда укоротится").
* Если ищем первый среди равных - то сравнение выглядит как key<=array[mid-1], если последний - key<array[mid]
* в зависимости от сравнения присваиваем mid в lo или hi (в любом случае, не mid-1).



Двоичный поиск для равномерно распределённых ключей (хешей) ускоряется простым хаком "для каждого из 65536 двубайтовых префиксов запомнить, где он начинается", это убирает 16 начальных итераций.Read more...Collapse )
Tags:

Особенности реализации #pragma once в gcc
nyaload
_winnie
Это исследование с gcc написал Vladimir Kozbin ( https://twitter.com/wawakadesu ), я его сюда только лишь скопировал.
--------------------------------------------------
Задачка.

Возьмём файлик a.h

#pragma once
x += 1;

Read more...Collapse )
Tags:

JavaScript массив не массив
nyaload
_winnie
[] + [] — получается ""
[] + {} — получается "[object Object]"
{} + [] — получается 0
{} + {} — получается NaN
({} + []) — получается "[object Object]"

Объяснение фокуса: при сложении [] и {} конвертируются в строки. [] - в пустую строку, {} - в "[object Object]".
В {}+[] или {}+{} без круглых скобок - первый {} это блок кода ( так же как в {alert(3)} + [] ), а '+' - унарный. Отсюда 0 и NaN, из-за автоматической конверсии в число для унарного плюса.

Оператор == считается "опасным". Блин, в JS всё опасно, но только у == есть "безопасная" альтернатива ===. А у операторов *,/,-,вызова методов,[], сравнения < и > случайно нет безопасных версий? Издевательство: пара десятков операторов, для одного из них есть безопасная версия другого.
Возникает два вопроса: нафига тогда этот другой, и где безопасные версии остальных операторов. Вам дали 100 пистолетов, только один из них не взрывается в руках. Но зато иногда не стреляет: "безопасный" оператор === не может сравнивать строки, созданные как new String("x"), всегда возвращая false.

В любой хеш-таблице по умолчанию есть ключ "constructor", "toString" и тд. Человек с логином "constructor" автоматом будет админом, модератором и в бан-листе, потому что конечно же программисты чаще всего не используют Object.prototype.hasOwnProperty.call. Я бы тоже не стал, без CoffeeScript.

Массивы - это по поведению хеш-таблицы из строк, причем ключи могут быть как числами, так и не числами, ошибок это не вызывает, влияет только на свойство .length:

var a = [];
a["5"] = 123;
a["asdfasdfasdf"] = 123; // Ok.

a.length вычисляется исходя из максимума ключа, которые можно конвертировать в число, 6 в данном случае.

Массив - это хеш-таблица, а не массив, я вам точно говорю. Может хром что-то и оптимизирует для "плотного" расположения ключей, но в общем случае - это хеш-таблица. Данный код не вызывает истощения памяти (не создаёт промежуточные элементы между 5 и 1024*1024*1024, между 1024*1024*1024 и 10*1024*1024*1024), но эксплуатирует возможности пропуска элементов в хеш-таблице не до конца, и криво считает length:

var a = [];
a[5] = 123;
a[1024*1024*1024] = 123;
a[10*1024*1024*1024] = 123;

a.length считается равным 1024*1024*1024+1. Элемент 10*1024*1024*1024 там тоже хранится, без overflow, но length считается только до 1024*1024*1024.

bash linux repeat: printf
nyaload
_winnie
Команда printf довольно мощная, часто позволяет обойтись без циклов:

function f { printf "%.0s$1$2" $(seq 10); printf "%.0s$1" ; }
printf "$(f "$(f + ----)\n" "$(f '|' " %%%%2s ")\n")" $(seq 0 99)

Вывод:Read more...Collapse )

Пояснение: "%.0s" печатает аргумент как пустую строку.
printf "%.0sXYZ" $(seq 1 20) - повторяет строку "XYZ" 20 раз.
Как обычно, заботливо подложены грабли: printf воспринимает 0 аргументов как один пустой аргумент. А не как 0 аргументов.

upd: Кто-то интересовался однострочниками на питоне:
python -c "print (lambda f:f(f('+', '----') + '\n', f('|', ' %2s ') + '\n') % tuple(range(0, 100)))(lambda a, b: a + 10*(b+a))"
Tags:

fuzzy search grep своими руками
nyaload
_winnie
Если нужно провести неточный поиск слова по большому файлу (напр. по дампу википедии), то самое простое - это сгенерить регулярное выражение со всеми нужными вариантами опечаток, и сунуть в хорошую библиотеку регулярных выражений ( стандартный grep - OK, PCRE/python.re - NOT OK ).

Например, слово WORD превращается в регулярку:
.ORD|ORD|W.RD|WRD|W.ORD|WO.D|WOD|WO.RD|WOR.|WOR|WOR.D

Если нужен поиск по UTF-8 файлу - то можно ускорить поиск, используя вместо точки и UTF8-локали - "[^\x80-\xbf][\x80-\xbf]*" и C-локаль.

Если нужен case-insensitive поиск - то при генерации регулярки вместо СЛОВО писать (С|с)(Л|л)(О|о)(В|в)(О|о). И вы сами определяете, что вы хотите - [iI] или [Iiı], ẞ или (ß|ẞ|SS|S-S|ss|SSS|SZ), ё или (е|ё).

Пример генератора, который генерирует регулярку для всех вариантов на расстоянии 1 по Левенштейну: https://gist.github.com/dobrokot/6150988
Tags:

прикольные гифки для программистов!
nyaload
_winnie
На http://devopsreactions.tumblr.com/ - прикольные гифки о разработке интернет-сервисов

http://securityreactions.tumblr.com - тоже прикольно, но как-то выдыхается, чем раньше гифка, тем лучше

Ещё http://this-plt-life.tumblr.com , но там как-то совсем редко попадалось развеселившее

updated:
http://geek-and-poke.com/
http://morekoda.ru ( русскоязычная копипаста )
http://thejoysofcode.com/

Tags:

iPad/iPhone python scripting
nyaload
_winnie
Нашел замечательную гиковскую игрушку для iPad - Pythonista. Это интерпретатор питона, с удобной программистской клавитурой и автокомплитом кода.

Так же в Pythonista есть набор библиотек, что бы делать простые 2d-игры, ну и значит какие-то самые простые приложения - делать самому, а не искать в AppStore. Есть фреймворк для создания 2d-игр. Есть доступ к clipboard, есть PIL, можно мутить свой гиковский инстаграмм загружая картинки по FTP на свой хост или по http на чужой, можно мучать публичные API отображая погоду и курс доллара каким-то своим особым способом. Доступа к камере увы пока нет.

В питоне есть HTTP-сервер в стандартной библиотеке. Скопировал кусок кода из документации, зашёл веб-браузером с компьютера на iPad. Тыкнулся в /var/media/mobile/DCIM , в файлы других программ/игрушек - увы access denied, без jailbreak приложения друг от друга изолированы.

В принципе, простешие приложения можно писать и на JavaScript, запуская в браузере, но этот Python может помочь что-то заскриптовать, что из JS сложно из-за дополнительной клетки браузера и особенностей языка. стоит его иметь ввиду как ещё один инструмент.

Удивляет, что такое оказалось в AppStore и пугает, не потрут ли его оттуда за излишнюю мощность. BTW, стоит 5$, но если вдруг приспичит что-то запускать или писать на питоне, и при этом именно на iPhone/iPad - то он лучше других бесплатных интерпретаторов, которые только как калькулятор можно использовать.