среда, 19 мая 2010 г.

Грамматика и её граф.

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

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

(из графа удалены все терминалы)


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

четверг, 22 апреля 2010 г.

Пасьянс для программиста.

Думал о модульности. О зависимостях, в том числе циклических. О графе зависимостей, способах и методиках его трансформации. О том что же такое модуль вообще (если в синтаксисе ЯП присутствует ключевое слово module это ещё ни о чем не говорит), и что это такое в таких странных ЯП как С и С++. Особенно если не полагаться на общепринятые практики и распространенные реализации, а следовать стандарту. Печалился из за отсутствия в современных ЯП явной декларации какие модули данный модуль использует, т.е. нормального import'a (например этого нет ни в java, ни в C# ни в F# или erlang'e). Читал стандарт Haskell'я, удивлялся и радовался, что в Haskell'e с модульностью как раз всё хорошо.

В общем меня это всё в конце концов таки утомило, и я решил во что-нибудь поиграть, дабы отвлечься. Посему запустил FAR (поскольку в тот момент сидел в винде), и решил проинспектировать содержимое винчестера на предмет каких-нибудь игрушек. В ходе инспекции внезапно наткнулся на BlackBox (если кто не знает, это такая среда разработки, и не только для ЯП Компонентный Паскаль, который, несмотря на название, никакой не паскаль, а вовсе модифицированный Oberon-2, см http://ru.wikipedia.org/wiki/BlackBox_Component_Builder и http://oberoncore.ru/). Запустил. Открыл какой-то примерчик. Пошарил по менюшкам. Наткнулся на пункт меню с интригующим названием "Dependencies". Нажал. Оно мне выдало вот такую картинку:
Что, как видимо, оказалось не чем иным, как графом зависимостей модулей. В данном случае -- графом зависимостей модулей подсистемы Hosts. Как видим, картинка довольно убога и не читабельна. Но поскольку оказалось что это не просто картинка, а вполне себе живой граф где узлы можно перетаскивать мышкой, я решил немного поразвлекаться и попробовать сделать картинку более наглядной. Развлекался в результате я где-то с час. Задача усложнялась тем, что хоть модулей всего 12ть, многие из них зависили чуть ли не ото всех остальных модулей. Результат развлечений получился такой:
В общем, хоть в результате в игрушку я и не поиграл, да и отвлечься от модулей не получилось, позабавился на славу. Всякие сапёры, пасьянсы и прочие преферансы по сравнению с этим где-то как-то курят в сторонке.

воскресенье, 14 марта 2010 г.

Знакомство с верблюдом.

Верблюд оказался страшноватым, не чистым, и весьма энергичным.

понедельник, 7 сентября 2009 г.

Локальные функции.

Иногда бывает так, что пишешь вот какую-то функцию (пусть функцию foo), и в процессе написания начинаешь осознавать что некий код в оной функции дублируется и что неплохо бы было его вынести в отдельную функцию (назовем её boo). Но выносить этот код в отдельную функцию-член класса плохо, т.к. по сути она больше никому не нужна, т.е. не имеет большого смысла вне функции foo. А замусоривать общее пространство имен своими личными потрохами не есть хорошо. Для борьбы с этим в паскаль-семействе языков (pascal, modula, modula-2, modula-3, oberon. oberon-2, component pascal, ada) существуют т.н. локальные процедуры и функции, т.е. функции которые объявляются прямо в самой родительской функции, видны соответственно только из нее и имеют, кстати, потенциально доступ ко всем локальным переменным родительской функции.

В С к сожалению такого удобного механизма нет. В С++ тоже нет, однако по наследству от Си ему досталась возможность объявлять новые типы внутри тела функции, в том числе и структуры и классы. А структура и класс в С++ это уже не просто набор полей/данных, но и набор функций-членов! Собственно чем мы грязно и воспользуемся:
void foo() {
struct
int a; // к этой переменной имеет доступ и функция boo
void boo(){cout << a;}
} local;

local.a = 15;
local.boo(); // вызов локальной функции
}

Т.о. мы получили фактически полный аналог локальных функций из паскаль-семейства.

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

четверг, 3 сентября 2009 г.

Условие с запятой.

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

#include <iostream>

using namespace std;

void foo(int a)
{
if ( (0==a and (
cout << "a=zero",
cout << endl,
true ) )
or
(1==a and (
cout << "a=one",
cout << endl,
true) )
or
(2==a and (
cout << "a=two",
cout << endl,
true) ) );
}

int main()
{
foo(0);
foo(1);
foo(2);
foo(3);
foo(5);

return 0;
}

Думаю всем ясно что выведет программа, а если не ясно, то попробуйте её запустить ;-)

Таким образом, очевидно, что else, как впрочем и тело условного оператора по сути своей синтаксический сахар чистой воды.
Вложенные if'ы -- тоже по сути синтаксический сахар.

среда, 21 мая 2008 г.

Характер дистрибутивов.

Прислали мне ссылочку на забавную картинку:(взято отсюда: http://2ch.ru/k/src/1209539085612.jpg)

воскресенье, 18 мая 2008 г.

Про OSS.

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

Чем замечатален опенсорс? Прежде всего тем что:
  1. Программа как таковая не имеет отдельной ценности, и соответственно распространяется (обычно) бесплатно. Ценность имеют конечные решения (грубо говоря, компутер + это ПО + конфигурирование всего этого под нужды заказчика).
  2. Если тебе в руки попал бинарник такой программы, то ты можешь получить и исходник её (а затем его спокойно изучать, менять и т.д. и т.п.).
Однако, если вспомнить "доперсоналочные" времена, то мы однако увидим что тогда ПО как таковое также не имело обособленной ценности (т.е. отдельно от аппаратного комплекса для которого предназначалось) и распространялось имено что в исходниках. Таким образом, всё возвращается на круги своя. А чем-то кардинально новым и необычным является, как ни странно, именно что коробочная проприентарщина. По всей видимости это было некое временное явление (по кр. мере для промышленных решений, за домашний десктоп сейчас говорить не буду, ибо это отдельная и довольно обширная тема.), которое сейчас вновь будет постепенно вытеснено классической схемой.

Да, а реально новым является развитие коммуникаций, разным компаниям совместно развивать нужное им ПО (т.е. то ПО которое они использует в своих решениях) не порождая форков.