Category: it

Vash

Как заставить node-gyp таки работать

Node.js использует для модулей, написанных на С++, ублюдочный пакет под названием node-gyp. Ублюдочный он потому, что авторам глубоко посрать на все операционные системы, кроме их любимой убунты.

Ни разу не видел, чтобы node-gyp заработал под виндой с первого раза. Три самых частых его бага:

1. Переменной окружения PYTHON не должно быть. Она по дефолту ссылается папку с Python, node-gyp от этой наглости входит в ступор и вылетает. Зачем ему питон, спросите вы? Да потому что ублюдок джаваскрипта и С++ просто обязан внутри использовать скрипты на тормозном питоне. (Посмотрите, например, на билд-скрипты Google Closure.)
Проверка: %PYTHON% в cmd должен говорить, что такой переменной нет.
Как исправить: set PYTHON= (и ничего после знака равно) перед тем, как вы будете делать npm install <пакет>.

2. Если у вас, не дай боже, что-то кроме iso-8859-1 в имени пользователя, то node-gyp работать не может, потому что они не умеют работать с юникодом. Переименовать пользователя будет недостаточно, потому что папка пользователя, в которой Node.js хранит настройки, будет называться всё так же. Создайте нового пользователя, убедитесь, что ваше VPN-подключение к Интернет расшарено на всех пользователей, и делайте действия оттуда. Ну или подправьте имя папки в реестре и на диске руками, на свой страх и риск.

3. Если у вас стояло много версий Visual Studio, и зачем-то одну из них удалили, то есть шанс, что node-gyp попытается откомпилировать именно ей. Подотрите остатки от студии и удалите соответствующую переменную окружения VSxxCOMNTOOLS.

Если всё это не помогло, то вы внимательно читаете логи, смотрите, какой конкретно пакет node-gyp не сумел скомпилировать, качаете его исходники в отдельную папочку npm'ом, правите, делаете npm link из этой папки. Теперь возвращаетесь на то место, где должен быть этот пакет в устанавливаемом, делаете оттуда npm link <имя пакета>, и всё!

И да, если ваc это достало так же, как и меня, напишите этим дебилам, что они дебилы.
Vash

Обобщённые стрелки

Предупреждение: дальше по тексту зачастую будет утверждаться какое-нибудь X, однако никаких исследований по этому поводу не проводилось никем и никогда. Поэтому вопросы вроде "c чего ты взял, что Х -- обобщённая стрелка", скорее всего, останутся с ответом "потому что попой чую" или вовсе без оного.

У вас есть некоторый язык программирования.
Вы хотите в нём воспользоваться имеющимся синтаксисом для некоторой хитрой цели.
К примеру, вы кодогенерируете джаваскрипт.
Вам нужен, таким образом, способ перегрузки оригинального синтаксиса.
Существуют языки, где вы можете получить AST некоторого фрагмента кода, поменять его и сделать обратно кодом. Например, Лисп, Хаскелл и Скала.
Такую возможность называют "макросы", саму дисциплину -- метапрограммирование.
Писать AST вручную, если мы что-нибудь генерируем, неприятно.
Нам хотелось бы иметь возможности из почти исходного синтаксиса генерировать неполные AST (c дырками).
Такая возможность называется квазиквотированием.
Но что-либо серьёзное в этом ключе написать всё равно сложно.
Не вполне понятно, в каком именно месте здесь включается типизация, например.
Удостовериться, что данный фрагмент кода генерирует AST с корректными типами всегда, невозможно.
Для этого придётся проводить что-то вроде статического анализа над генерирующим AST кодом.
Учитывая, что используется оригинальный язык, а он обычно Тьюринг-полон, получаем неразрешимую задачу.
Доказывать корректность таких кодогенераторов в общем случае сложно.
Это "вжжж" неспроста.
Рассмотренный ранее подход к метапрограммированию называется интенсиональным.
Существуют ещё и не-интенсиональные подходы, и я знаю из них только один.
Обобщённые стрелки.
Для них в общем случае нужна поддержка интерпретатором или компилятором.
Программа при трансляции переводится в язык из небольшого набора комбинаторов.
Пользователю предоставляется возможность эти комбинаторы переопределять на некотором фрагменте кода.
Чтобы всё было в порядке, комбинаторы поставляются с набором аксиом, которым они должны удовлетворять.
Теперь к подробностям.
Разные программы требуют различного набора комбинаторов.
Если в программе есть несколько переменных, её представление требует комбинаторов, которые работают с парами (типами-произведениями), например, first : (a -(x)> b) -> ((a, c) -(x)> (b, c)). Этот first должен удовлетворять кое-каким аксиомам.
Если одна переменная может использоваться дважды, нужен dup : a -(x)> (a, a).
Если в языке есть литералы целых, нужно что-то вроде int : () -(x)> Int.
Чтобы появился этот (), нужен ещё набор примитивов типа uncancel_l : a -(x)-> ((), a), uncancel_r : a -(x)> (a, ()).
Ну вы поняли идею, да? Шинкуем язык на комбинаторы и типа всё.
На самом деле, мы можем нашинковать исходный язык на комбинаторы многими способами.
Например, если в языке мы можем объявлять рекурсивные функции, то мы можем добавить комбинатор fix, он же loop.
В то же время, если бы в нашем языке была возможна только "хорошая" убывающая рекурсия по натуральным числам, мы могли бы объявить в качестве примитива natrec.
Но ничто нам не мешает иметь и то, и другое одновременно.
Просто данный код будет транслироваться в потенциально разные наборы комбинаторов в зависимости от того, акие комбинаторы мы перегрузили в данном фрагменте кода.
Например, факториал будет иметь возможность транслироваться в natrec, если мы запускаем его в доказанно завершимом контексте, или fix, если мы запускаем его в контексте трансляции в JS.
И ещё: наборы комбинаторов это type class'ы.
Ознакомиться с классическими можно, изучив (необобщённые) стрелки: Arrow, ArrowChoice, ArrowApply, ArrowLoop
Этих наборов целая решётка.

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

Стрелки (необобщённые) были разработаны, в том числе, для создания эффективных парсеров (Swierstra & Duponchel). Дело в том, что стрелка a ~> b это что-то вроде функции a -> b или около того, но она дополнительно может хранить какие-нибудь данные.
data Something a b = Something AdditionalData (a -> [b])
Это, кстати, позволяет решить одну очень больную проблему для других языков.
Представьте себе, что вы можете произвести некоторые затратные вычисления при запуске программы, а потом пользоваться результатами. Например, посчитать таблицы синусов для дальнейшего использования в генерации объёмных сферических объектов или меш нужной детализации по функции, как это делают в демо-сценах
Вы затем хотите вынести этот функционал в библиотеку и обнаруживаете, что не знаете, стоит ли вам вызывать эти вычисления (обычно в конструкторе соотв. класса), так как вы не знаете, будут ли они использованы в пользовательском коде.
Можно сделать это в стиле синглетона, но это породит +1 if (и лишние +5% прочистки конвеера), а также в исполнимый файл может попасть код, который никогда не будет вызван (оптимизатор может его и удалить, но он не тотальный, задача поиска мёртвого кода неразрешимая же).

Самое главное: обобщённые стрелки позволяют создать действительно универсальный язык.
Обычно когда в языке X не хватает Y, кто-нибудь берёт и делает X+Y.
Например, с чего бы от С++ ответвляться всяким PHP?
Нужна была весьма специфическая среда для кода (хорошие встроенные строки, например).
В то же время, несмотря на почти идентичность синтаксиса, в язык были внесены изменения.
Теперь библиотеки для С++ нельзя просто так взять и использовать в PHP и наоборот.
В случае языка со встроенными обобщёнными стрелками нужно было бы просто создать подходящую стрелку, которая работает с server state, session state и чем-нибудь там ещё.
Скорее всего, для такой стрелки не понадобилось бы даже менять компилятор.
Вся кодовая база была бы доступна. Весь старый синтаксис бы работал.

Впрочем, если такой язык написать, то можно будет решить проблему вавилонской башни посредством кодогенерирующих инстансов соответствующих стрелок.
Собственно, ваш покорный слуга шёл к этому 7 лет (из них 6.5 вокруг да около сабжа; нельзя просто так взять и самому придумать обобщённые стрелки, их должен придумать кто-то другой, а кто-то третий -- рассказать), и собирается это таки сделать :)
Интуиции в таком подходе к разработке ЯП мне сильно не хватает, и достать её, в общем-то, особо негде.

Ещё немного интуиции могут дать списки того, за что могут отвечать классы и инстансы обобщённых стрелок.
Классы:
"жонглирование" переменными
использование переменной более одного раза
неподвижная точка / цикл
определение функции
выведение типа
императивные включения (присваивания, ссылки)
рефлексия (получение имён типов и переменных)

Инстансы:
хост-язык (этот инстанс неявно скармливается функции main)
парсеры
кодогенераторы (fix генерирует рекурсивные вызовы, let генерирует заголовки функций, ...)
    CUDA
    шейдеры
    JS, CSS, HTML, PHP
    С++
    заголовки .h для dll сразу из определения функций
    VHDL и Verilog
    электрические схемы (цифровые и аналоговые)
    изображения (векторная графика, генеративное моделирование, SVG)
специализатор (упрощает pow(x, 2) до \x -> x * x)
инлайнер
оптимизаторы
неявное распараллеливание
трансляторы

Хотелось бы поблагодарить ребе akuklev за разъяснение мне этого дела, камрада tomotom за то, что не устаёт слушать мой больной бред и гуру sharpc за лучи ненависти к ФП и стратегию "заткнись и пиши" :)
Vash

Как взломать пароль проекта Visual Basic for Applications (VBA)

Нынче мне пришлось вспомнить старое. VBA, похоже, никогда не устареет.

Если у вас файл свежих офисов (xlsx/docx/xlsm/docm), "сохраните как" в старый.
Открываем файл хорошим текстовым редактором. Ищем строку "DPB". Выглядит она где-то так:
DPB="шестнадцатеричные циферки"
Портим строку "DPB". Например, заменяем на "DPx".
Теперь достаточно открыть файл и открыть редактор VBA (через Alt + F11 удобнее всего).
Появится сообщение в духе "файл слегка попорчен, продолжить загрузку?" Смело нажимаем "да".
Исходники у вас на экране.
Если вы хотите, чтобы в следующий раз всё было в порядке, откройте свойства проекта и поменяйте пароль на новый.
Vash

Как понять макросы в Scala

1. Учим Haskell
2. Пробуем Template Haskell. Запоминаем операторы "боян" [|...|] и "бабло" $(...).
3. Читаем одну страницу (via xeno_by). Запоминаем оператор macro f, который какбы $( f ( [| ... |] ) ).
4. ???????
5. PROFIT

UPD. На самом деле, макросы это штука весьма тонкая, потому что врезаться в процесс компиляции они могут до тайпчека, после тайпчека и даже во время тайпчека, в зависимости от философских убеждений автора, реализации, контекста и положения звёзд на небе. В Scala, например, макросы будут типизированные, в отличие от Haskell. Правда, как там будут работать определения с типовыми переменными, и как будет проводиться тайпчек генерируемого кода, я хз. Уж не через HOAS точно.

Prelude Control.Monad Language.Haskell.TH> :t [| print |]
[| print |] :: Q Exp

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

def printf(format: String, params: Any*): Unit = macro printf_impl
def printf_impl(c: Context)(format: c.Expr[String], params: c.Expr[Any]*): c.Expr[Unit] = ...
Vash

Лямбда-исчисление и автоматическое дифференцирование

Пруф того, что общение с программистами вправляет мозг.
Вот это я не мог нагуглить буквально пару недель назад:
http://oleksandrmanzyuk.files.wordpress.com/2012/04/paper.pdf
https://engineering.purdue.edu/~qobi/stalingrad-examples2009/talk.pdf
Поинт в том, что если в матане заменить функции на лямбда-абстракции, то дифференцирование (и частные производные) по-прежнему можно определить, и получается очень даже неплохо. По-моему, даже лучше символьного дифференцирования.
Vash

Краулинг

Список TODO у меня имеет свойство только расти, поэтому я теперь буду свои идеи выкладывать сюда. Не думаю, что кто-нибудь из читателей возьмётся, ведь навыки и количество идей коррелируют довольно сильно, но хотя бы обратная связь будет.

Задача: хочется делать автоматизированные действия в Интернете.

Подводные камни:
  • "умные" сайты хотят нас наебать обмануть, сделав всё максимально браузерозависимым;
  • библиотеки для всех языков для работы с интернет-контентом -- сраное говно;
  • единственное место, где можно эти камни обойти, т.е. браузер, содержит один более-менее полезный язык программирование, и это JavaScript, что ограничивает сложность приложений на нём хелловорлдами.
Линкдамп:

https://developer.mozilla.org/en/XUL/Method/loadOneTab
Метод плагинового JS для открытия страницы.

http://blog.mozilla.org/addons/2009/01/28/how-to-develop-a-firefox-extension/
http://mytechieself.blogspot.com/2006/06/how-to-writing-firefox-plugin.html
Туториал и подборка ссылок для быстрого погружения в плагинописание.

http://www.quizful.net/post/xpath-in-javascript
http://js-xpath.sourceforge.net/xpath-example.html
Либа для XPath внутри JS.

http://www.haskell.org/haskellwiki/The_JavaScript_Problem
Список решений для трансляции Haskell в JS и около того.

https://addons.mozilla.org/ru/firefox/addon/sqlite-manager/
Аддон, работающий с любыми внешними БД SQLite.

Решение: нужно сделать плагин для Firefox, который позволит
  • писать скрипты для краулинга на Haskell или подобном языке;
  • быстро получать XPath для содержимого страницы и совать его в код;
  • отлаживать краулеры (обрабатывать особые ситуации) в момент их работы, исправлять на лету;
  • получать данные в JSON, XML или в БД на SQLite.
Vash

Квантовые вычисления vs криптография

Есть такая логическая цепочка, которую неплохо бы знать каждому. Наверняка вы уже не раз слышали в желтой прессе о том, что квантовые компьютеры придут и разрушат все схемы шифрования. Иногда там даже приводилось вполне логичное описание того, как система принимает множество состояний одновременно, и как с помощью этого проводится экспоненциально много вычислений. Но есть такая вещь, как принцип Ландауэра, гласящий, что в любой вычислительной системе, независимо от ее физической реализации, при потере 1 бита информации выделяется теплота. Квантовый брутфорс должен будет вычислять значения некой функции и сравнивать с образцом. Если это хеш-функции, очевидно, что они теряют информацию. Для прочих алгоритмов шифрования это не столь очевидно, но они теряют биты тоже (здесь, как я понимаю, играет роль обратимость процесса). Отличный от брутфорса метод позволит производить эти вычисления и на обычном компьютере. Квантовые компьютеры, быть может, и позволяют производить экспоненциально много вычислений за промежуток времени, но они будут и потреблять соответствующее количество энергии, и требовать отвод такого количества тепла.
Vash

Вариадические шаблоны всюду

Пока С++0x в рядовых компиляторах нет, приходится использовать boost::preprocessor для генерации специализаций шаблона до макслимита. Если вам не принципиальны лишние несколько символов в коде, можно сделать это единственный раз. Очень просто, только немногие знают, что в С++ есть такое интересное семейство типов как "функции". Не указатели на функцию, именно функции. Например, int(int). Использовать их можно почти нигде, кроме как в аргументах шаблона. Рецепт:
1) Вызов выглядит так:
test<void(T1, T2, T3)>

2) Откроем исходник boost::type_traits::function_traits, копируем этот код к себе в какой-нить хидер и изменяем typedef ... argN_type; на списки из mpl.
3) Можно смело пользоваться:
template <typename F> struct test : my_func_traits<*F> { /* Здесь мы можем работать со списком аргументов будто с родным */ };

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