Здравствуйте, Сергей Губанов, Вы писали:
СГ>Однако.... А без continue слабо?
Канешна слабо! Это же Кодт, он на RSDN известный слабак.
Вот, к примеру, хоть здесь посмотри: Топ100
Здравствуйте, Сергей Губанов, Вы писали:
V>>Ну а какие дополнительные возможности предоставляет команда call? Что мешает руками запихать адрес возврата в стек и сделать jmp? То есть нет никаких дополнительных возможностей.
СГ>Вы из своего любимого языка программирования мысленно удалите такое понятие как процедуры и подумайте что от этого изменится. А потом, верните их назад, и мысленно удалите шаблоны. От удаления/добавления шаблонов мощность языка не меняется, в отличие от удаления/добавления процедур.
Это ты так думаешь, потому что с шаблонами мало имел дела.
Давай мы выкинем из твоего любимого Оберона всё то, что туда насыпано сверх Паскаля. Тоже мощность не изменится, разве что кодить придётся раз в пять больше, да за чистотой рук следить.
СГ>http://www.rsdn.ru/Forum/Message.aspx?mid=862197&only=1
"Уберите переменные, оставьте константы"...
Получим нормальный декларативный язык. Да, приёмы программирования на ФЯ/ЛЯ существенно отличаются от императивных. Но это не значит, что они ущербны.
Здравствуйте, Сергей Губанов, Вы писали:
СГ>Можно ли эту фразу понимать в том смысле, что Вы держитесь двумя руками за Си++, не смотря на тщательно раскиданные в нем ровным слоем грабли, только потому, что в остальных языках (ну, если не считать Аду) нет шаблонов?
Кстати, если из Ады выкинуть шаблоны, то министерство обороны США отправит такого пионера "к первоисточнику". И правильно сделают, потому что шаблоны там сделаны не для красоты, а для критического увеличения надёжности.
Здравствуйте, Сергей Губанов, Вы писали много бреда:
Ни один из современных языков не превзошол машину Тьюрига.
Те любую программу написаную на любом из современных языков можно перевести в эквивалентную программу для машины Тьюринга.
Машина Тьюринга это: Бесконечная в обе стороны лента разбитая на ячейки памяти в которые можно записать что угодно. На ленте есть корретка у которой есть состояние и она может посмотреть что находиться в текущей ячейке, записать что-то в текущею ячейку, изменить свое состояние или сдвинуться на одну позицию в право или в лево.
... << RSDN@Home 1.1.4 rev. 185 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, Сергей Губанов, Вы писали:
СГ>Формального определения не дам. Дам интуитивное. Мощностью ЯВУ я называю количество вариантов разных программ, которые на нем можно написать.
Мощность множества всех конечных цепочек из конечного алфавита — алеф-0.
Поэтому в ТМ-трактовке все языки программирования имеют одинаковую мощность (кроме специально выведенных ублюдков, в которых длина программы жёстко ограничена).
А мощность множества вообще-всех программ — алеф-2, поскольку программа — это функция, у которой область определения/результатов имеет мощность алеф-1 (бесконечные цепочки конечного алфавита). Но средствами формальных языков всё это множество не покроешь.
СГ>Например, интуитивно понятно, что если убрать из ЯВУ указатели, ссылки и оператор NEW, то на таком ЯВУ нельзя будет написать ни одной программы работающей с динамическими структурами данных, то есть размерность пространства всевозможных программ, которые можно написать на таком ЯВУ уменьшиться. Я употребляю слово "мощность", чтобы обозвать, хм, эту штуковину.
Нет, можно, только гораздо мучительнее, чем на тех языках, где это входит в синтаксис.
"Женская интуиция — поразительное чувство, дающее женщине уверенность в своей правоте вне зависимости от того, права она или не права".
(дамы, не обижайтесь... просто к слову пришлось)
СГ>>Ни что не мешает делать аналогичную оптимизацию для WITH по сравнению с цепочкой dynamic_cast-ов.
К>Мешает, и ещё как мешает. К>Если в спецификации не прописано явно, что with всегда выбирает most derived ветку, то порядок проверок становится существенным. К>В этом отличие от case: целочисленная переменная не может быть равна нескольким разным ключевым значениям, а полиморфный объект — может принадлежать разным классам одновременно.
Ну и разумеется, в случае множественного наследования никакое most derived не спасёт в принципе.
Здравствуйте, Дарней, Вы писали:
Д>Указатели на функции тоже не являются абсолютно необходимыми. Их при желании можно заменить на большой такой switch, который в зависимости от полученного числа будет вызывать разные
Ничего подобного! switch Вы напишете только для известных Вам функций (а зачем его тогда писать если они Вам и так известны), а для неизвестных функций Вы его не напишите! В этом весь прикол и состоит что процедурную переменную можно передать в чужой код и он сможет вызвать не известную ему процедуру.
Здравствуйте, eugals, Вы писали:
E>Здравствуйте, Сергей Губанов, Вы писали:
СГ>>Однако.... А без continue слабо? E>Канешна слабо! Это же Кодт, он на RSDN известный слабак. E>Вот, к примеру, хоть здесь посмотри: Топ100
Здравствуйте, eugals, Вы писали:
СГ>>Однако.... А без continue слабо? E>Канешна слабо! Это же Кодт, он на RSDN известный слабак. E>Вот, к примеру, хоть здесь посмотри: Топ100
Авторитетом давишь но всё равно приятно
Без continue — это будет или иерархическое нагромождение if'ов, или добавление переменных stop и bypass.
Здравствуйте, Сергей Губанов, Вы писали:
СГ>Ничего подобного! switch Вы напишете только для известных Вам функций (а зачем его тогда писать если они Вам и так известны)
А затем писать, чтобы эмулировать вызов функций по указателям при их отстутствии
СГ>а для неизвестных функций Вы его не напишите! В этом весь прикол и состоит что процедурную переменную можно передать в чужой код и он сможет вызвать не известную ему процедуру.
А мне этого и не надо. Нужно всего лишь соглашение о том, как именовать эту самую функцию-диспетчер. Чужой код вызовет моего диспетчера, передав ему полученное из моего кода значение — и таким образом вызовет неизвестную ему функцию
Какие еще будут аргументы? От чего мы будем отказываться на этот раз? Так можно и правда до машины Тьюринга добраться
init();
bool stop=false;
while(!stop && cond())
{
bool bypass=false;
// в первых двух строчках проверка вырождена, но я её написал для однородности кодаif(!bypass) work1();
if(!bypass) if(x()) { workx(); bypass=true; }
if(!bypass) work2();
if(!bypass) if(y()) { worky(); bypass=true; stop=true; }
if(!bypass) work3();
if(!bypass) if(z()) { workz(); bypass=true; }
if(!bypass) work4();
// условие перед итерациейif(!stop) next();
}
init();
bool stop=false; // для break всё равно нужноwhile(!stop && cond())
{
work1();
if(x()) workx();
else {
work2();
if(y()) { worky(); stop=true; }
else {
work3();
if(z()) workz();
else {
work4();
}}}
if(!stop) next();
}
О господи-ты боже мой, что за чудеса творятся на белом свете-то...
Универсальная конструкция:
init();
LOOP
IF x1() THEN v1() ELSE
w1();
IF x2() THEN v2() ELSE
w2();
IF x3() THEN v3(); EXIT ELSE(* обратите внимание на вставленные EXIT - это вместо Вашего break *)
w3();
IF x4() THEN v4() ELSE
w4();
IF x5() THEN v5() ELSE
w5();
IF x6() THEN v6() ELSE
w6();
..................................
END
END
END
END
END;
END
next();
END
В том месте где нуже выход из цикла, там вставляем EXIT
Здравствуйте, Кодт, Вы писали:
К>Авторитетом давишь
Никого я не давлю. Просто призываю соотносить уровень аргументов с уровнем собеседников.
Очевидно ведь, что любой мало-мальски грамотный программист догадался бы заменить в том примере два ифа на один, с условием ИЛИ внутри. К чему эти мелкие придирки, никак не опровергающие основного сообщения...
да ещё и "слабо" это...
Д> ... Чужой код вызовет моего диспетчера ... Д> ... Какие еще будут аргументы? ...
Да ровно теже самые. Ведь, чужой код может вызвать Ваш диспетчер, только если Вы сами передадите ему Ваш диспетчер (call-back функцию). А по условию задачи указателей на функции нет. Значит чужой код не знает откуда взять Ваш диспетчер и одновременно Вы не можете его ему передать.
PROCEDURE ЧужойКод(Д: Диспетчер);
BEGIN
...
END ЧужойКод;
Здравствуйте, Сергей Губанов, Вы писали:
СГ>Да ровно теже самые. Ведь, чужой код может вызвать Ваш диспетчер, только если Вы сами передадите ему Ваш диспетчер (call-back функцию). А по условию задачи указателей на функции нет. Значит чужой код не знает откуда взять Ваш диспетчер и одновременно Вы не можете его ему передать.
госсподи, ну здесь то чего непонятного? пишем например так.
Это вот чей-то чужой код:
// импорт функций из моего модуляint GetMyModuleFunction();
void MyModuleDispatcher(const int targetCode);
void SomeAlienFunction()
{
const int myFunctionPseudoPointer = GetMyModuleFunction();
MyModuleDispatcher(myFunctionPseudoPointer); // вот здесь внутри и будет произведен вызов
}
Так доступнее? Не знаю, как правильно записать аналог на Паскале или например Обероне
Здравствуйте, Дарней, Вы писали:
Д>госсподи, ну здесь то чего непонятного? пишем например так. Д>Это вот чей-то чужой код:
// импорт функций из моего модуляint GetMyModuleFunction();
void MyModuleDispatcher(const int targetCode);
void SomeAlienFunction()
{
const int myFunctionPseudoPointer = GetMyModuleFunction();
MyModuleDispatcher(myFunctionPseudoPointer); // вот здесь внутри и будет произведен вызов
}
Д>Так доступнее?
Понимаетели, Вы привели случай, когда чужой модуль использует Ваш модуль: "импорт функций из моего модуля". А надо наоборот. Вы используете чей-то чужой УЖЕ написанный модуль и Вам надо в этот чужой уже написанный модуль как-то передать свою функцию обратного вызова (call-back function). Если в языке нет процедурных переменных (указателей на функцию), то сделать это Вы не сможете.
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
Здравствуйте, Сергей Губанов, Вы писали:
К>>Объясни — чем ты меряешь мощность языка? Ваттметром? СГ>Формального определения не дам. Дам интуитивное. Мощностью ЯВУ я называю количество вариантов разных программ, которые на нем можно написать. Например, интуитивно понятно, что если убрать из ЯВУ указатели, ссылки и оператор NEW, то на таком ЯВУ нельзя будет написать ни одной программы работающей с динамическими структурами данных, то есть размерность пространства всевозможных программ, которые можно написать на таком ЯВУ уменьшиться. Я употребляю слово "мощность", чтобы обозвать, хм, эту штуковину.
Интересное определение, хотя и глюкавое. ИМХО, разумеется. Опять же ИМХО, но определение "мощности" должно прямо или косвеннно включать в себя понятие "времени", просто чтобы не выбиваться из устоявшейся трактовки. Тем более, коль скоро мы обсуждаем некий инструмент. Т.е., в нашем случае, вероятно, имеет смысл оценить количество языковых конструкций, потребных для реализации каких-то задач. Значит, нужно определить выборку задач, провести оценки (можно — приблизительные) и т.п. Но сначала, всё-таки, неплохо бы назвать предмет исследований. В нашем случае это — мощность инструмента. ЯВУ — это ведь инструмент, правильно?
Что же касается "размерности пространства всевозможных программ", то тут уже правильно говорили, что машины Тьюринга хватит на всё, на что можт хватить компьютера. Так что здесь предел имеется. Значит, остаётся оценивать мощность в контексте усилий программиста...
Ну-с, теперь — твой ход.
... << RSDN@Home 1.1.3 stable >>
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
Д>госсподи, ну здесь то чего непонятного? пишем например так. Д>Это вот чей-то чужой код: Д>
Д>// импорт функций из моего модуля
Д>int GetMyModuleFunction();
Д>void MyModuleDispatcher(const int targetCode);
Д>void SomeAlienFunction()
Д>{
Д> const int myFunctionPseudoPointer = GetMyModuleFunction();
Д> MyModuleDispatcher(myFunctionPseudoPointer); // вот здесь внутри и будет произведен вызов
Д>}
Д>
Д>Так доступнее? Не знаю, как правильно записать аналог на Паскале или например Обероне
Из какого моего модуля?
Мой модуль может быть ещё не написан во время написания библиотечной функции.
Вы как-то упускаете из виду тот момент, что Оберон поддерживает компонентную парадигму...
Программа на Обероне — не формируемый компилятором единый текст программы пр раскрытии всех define-ов.
Здесь не может быть циклических ссылок между компонентами системы.
Сергей и говорит Вам о том, что указатель на функцию — это "страховка" для одного модуля гарантированно вызывать функции, которые "ещё не написаны" (виртуальность).
Курилка:
> СГ>Так убери еще и goto. Что изменилась мощность языка? То-то, а от шаблонов она не меняется.
> Объясни — чем ты меряешь мощность языка? Ваттметром?
Если это кому-то, действительно, интересно, то хоть сколько-то строго "уровень" языка можно измерять, прибегнув к понятию функциональных единиц (function point). И, таки да, наличие generics и статического полиморфизма вообще и шаблонов в частности при такой трактовке "уровня" языка будут этот "уровень" поднимать.
> Имхо, показателем мощности можно считать число затрачиваемых программером физических и умственных усилий для написания кода, остальное — демагогия, не более того.
Это достаточно близкая к function point трактовка
Posted via RSDN NNTP Server 1.9 gamma
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Кодт, Вы писали:
СГ>>>Ни что не мешает делать аналогичную оптимизацию для WITH по сравнению с цепочкой dynamic_cast-ов.
К>>Мешает, и ещё как мешает. К>>Если в спецификации не прописано явно, что with всегда выбирает most derived ветку, то порядок проверок становится существенным. К>>В этом отличие от case: целочисленная переменная не может быть равна нескольким разным ключевым значениям, а полиморфный объект — может принадлежать разным классам одновременно.
К>Ну и разумеется, в случае множественного наследования никакое most derived не спасёт в принципе.
Давайте подумаем. У объекта есть скрытое поле — указатель на место в памяти, в котором хранится информация о типе объекта. Давайте для краткости обзовем этот указатель указателем на дескриптор типа. Что у нас есть в WITH? Там у нас есть N предложенных вариантов типов указателей на дескрипторы типов и один указатель на дескриптор типа испытуемого объекта. Первым шагом ищем точное равенство указателя на дескриптор типа с предложенными указателями. Ота операция в худшем случае отнимает O(Log(N)) времени. Если поиск не увенчался успехом, то надо повторить его для всех тех указателей на дескрипторы типов рассширениями которых является тип испытуемого объекта. Обозначим число предков типа испытуемого объекта символом H. В случае одиночного наследования H просто равно глубине иерархии расширения типа. И так, в наихудшем случае (т.е. когда ответ будет отрицательный), время необходимое для работы инструкции WITH определяется формулой
t = const*H*Log(N)
В то время как цепочка if-dynamic_cast-else будет работать за время:
T = const'*H*N
где H в первой и второй формуле одинаковы (надо же проверить все варианты!)