понедельник, 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'ы -- тоже по сути синтаксический сахар.