Re[9]: Оберон vs все остальное
От: Cyberax Марс  
Дата: 13.01.05 15:10
Оценка:
Сергей Губанов пишет:

> C>Да, а почему сам используешь при этом возможности Object Pascal'я, а не

> C>обычный Pascal?
> Я не понял Ваш вопрос. Вообще-то я тут говорил про Component Pascal от
> Никлауса Вирта. При чем тут борландовские поделки ума не приложу...

Ошибся, как раз Component Pascal и имел в виду...

> C>а покажи на Паскале аналог вот этого:

> C>========================================
> C>class Something : public virtual boost::signals::trackable
> C>{
> C>public:
> C> void processMessage(std::vector<int> some1, double some2)
> C> {
> C> ....
> C> }
> C>};
> C>...
> C>boost::signal<void(std::vector<int>, double)> sig;
> C>Something s1=new Something();
> C>Something s2=new Something();
> C>...
>
> C>sig.connect(boost::bind(&Something::processMessage,s1,_1,_2));
> C>sig.connect(boost::bind(&Something::processMessage,s2,_1,_2));
> C>sig(param1,param2);
> C>delete s1;
> C>sig(param1,param2);
> C>delete s2;
> C>========================================
>
> Да, загадали загадку так загадали, ну какой вопрос — такой и ответ,
> смотрите:
>
>TYPE
> Something = POINTER TO RECORD (Signals.Trackable) END;
>
>PROCEDURE ProcessMessage (this: Something; IN some1: ARRAY OF INTEGER; some2: REAL);
>BEGIN
> (* ... *)
>END ProcessMessage;
>
>
>...
>
>VAR sig: Signal; s1, s2: Something;
>BEGIN
> NEW(s1); NEW(s2);
> sig.Connect(bind(ProcessMessage, s1, _1, _2));
> sig.Connect(bind(ProcessMessage, s2, _1, _2));
> sig(param1, param2);
> s1 := NIL;
> sig(param1, param2);
> s2 := NIL;
>
>
Э, нет. Во-первых, в моем примере Something это объект, причем он
автоматически отключается от сигнала при уничтожении. Далее, с помощью
boost::bind'а я создаю функтор-адаптер, который позволяет мне подключить
к сигналу обработчик с другой сигнатурой функционального оператора.
Можно еще усложнить пример:
==============
class Something : public virtual boost::signals::trackable
{
public:
void processMessage(std::vector<int> some1, double some2, int
THIRD_PARAMETER)
{
....
}
};
...
boost::signal<void(std::vector<int>, double)> sig;
Something s1=new Something();
Something s2=new Something();
...

sig.connect(boost::bind(&Something::processMessage,s1,_1,_2,111111));
sig.connect(boost::bind(&Something::processMessage,s2,_1,_2,222222));
sig(param1,param2);
delete s1;
sig(param1,param2);
delete s2;
==============
Причем все типы проверяются на этапе компиляции, поэтому такой код:
sig.connect(boost::bind(&Something::processMessage,s2,_1,));
просто не скомпилится.

Такой гибкости Паскалю и близко не снилось.

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[9]: Оберон vs все остальное
От: AndrewJD США  
Дата: 13.01.05 15:14
Оценка: 2 (2) +6
Здравствуйте, Сергей Губанов, Вы писали:

C>>Да, а почему сам используешь при этом возможности Object Pascal'я, а не

C>>обычный Pascal?

СГ>Я не понял Ваш вопрос. Вообще-то я тут говорил про Component Pascal от Никлауса Вирта. При чем тут борландовские поделки ума не приложу...


ИМХО только благодаря "борландовским поделкам" паскаль все еще остается популярным.
"For every complex problem, there is a solution that is simple, neat,
and wrong."
Re[10]: Оберон vs все остальное
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 13.01.05 15:50
Оценка: :)
Здравствуйте, Кодёнок, Вы писали:


Кё>>>OK, аналогично C#. Но как копирование? Как массив копирует объекты при прераспределении памяти — всегда побитово?


СГ>>Что значит перераспределение памяти?


Кё>Добавление еще 100 элементов, когда для них нет размера.


Куда добавляем-то, массив же уже создан...

Нужно вручную создать совершенно другой новый массив, который на 100 элементов длиннее, и вручную скопировать в него то что хотите. О старом массиве забыть.
NEW(tmp, LEN(a) + 100);
FOR i := 0 TO LEN(tmp)-1 DO tmp[i] := a[i] END;
a := tmp;
Re[11]: Оберон vs все остальное
От: Schade Россия  
Дата: 13.01.05 16:27
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Куда добавляем-то, массив же уже создан...

СГ>Нужно вручную создать совершенно другой новый массив, который на 100 элементов длиннее, и вручную скопировать в него то что хотите. О старом массиве забыть.

В общем, опять занимаемся изобретением однотипных велосипедов в разных ракурсах. Наличие в языке generic'ов запросто решает эту проблему. Или в "настоящих модульных компонентных ... etc. системах" это не нужно, лишено смысла? Может, все-таки никому не нужны такие вот системы?

З.Ы. Я уж надеялся, что флейм об Обероне ушел в прошлое. Зачем же паутину с него смахивать?
... << RSDN@Home 1.1.4 @@subversion >>
Re[12]: Оберон vs все остальное
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 13.01.05 19:51
Оценка:
Здравствуйте, Schade, Вы писали:

S> В общем, опять занимаемся изобретением однотипных велосипедов в разных ракурсах. Наличие в языке generic'ов запросто решает эту проблему.


Э-э-э, а какую проблему?

Написать три строчки кода:
  NEW(tmp, LEN(a) + 100);
  FOR i := 0 TO LEN(tmp)-1 DO tmp[i] := a[i] END;
  a := tmp;

это что теперь проблемой называется????

А я то думал, что проблема, это, например, придумать хорошую эвристику для NP-задачи...
Re[13]: Оберон vs все остальное
От: Cyberax Марс  
Дата: 13.01.05 19:56
Оценка: +2
Сергей Губанов пишет:

> S> В общем, опять занимаемся изобретением однотипных велосипедов в

> разных ракурсах. Наличие в языке generic'ов запросто решает эту проблему.
> Э-э-э, а какую проблему?
> Написать три строчки кода:
>
> NEW(tmp, LEN(a) + 100);
> FOR i := 0 TO LEN(tmp)-1 DO tmp[i] := a[i] END;
> a := tmp;
>
> это что теперь проблемой называется????

Да, когда повторяется n раз (n>100)

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[9]: Оберон vs все остальное
От: Кодёнок  
Дата: 14.01.05 05:32
Оценка:
СГ>Да, загадали загадку так загадали, ну какой вопрос — такой и ответ, смотрите:

Мимо Пропущена реализация Signal и функтора, которая собственно и интересует. Вспоминая GC в C# — тут обязательно придется привлечь WeakReferences.

СГ> sig.Connect(bind(ProcessMessage, s1, _1, _2));


Число параметров и типы могут отличаться, короче — быть любыми. Что, будешь писать разные процедуры для каждой новой комбинации?

PROCEDURE bind_void_void(IN A: PROCEDURE; ...): functor
PROCEDURE bind_void_int(IN A: PROCEDURE(a:integer); ...): functor
PROCEDURE bind_void_real(IN A: PROCEDURE(a:read...): functor
PROCEDURE bind_void_int_real(IN A: PROCEDURE(a:read...)
PROCEDURE bind_void_real_int(IN A: PROCEDURE(a:read...)

Главное запастись травой на год!

СГ> sig.Connect(bind(ProcessMessage, s2, _1, _2));

СГ> sig(param1, param2);
СГ> s1 := NIL;

А вот это не приведет к удалению. Потому что ссылка на s1 уже хранится где-то в функторе, коорый возвращает bind().

Это уже к спору о проблемах GC
Re[13]: Оберон vs все остальное
От: Кодёнок  
Дата: 14.01.05 05:44
Оценка:
СГ>Куда добавляем-то, массив же уже создан...

СГ>Нужно вручную создать совершенно другой новый массив, который на 100 элементов длиннее, и вручную скопировать в него то что хотите. О старом массиве забыть.


Ладно, Cray X, я думаю, справится с таким языком

СГ>Написать три строчки кода:

СГ>
СГ>  NEW(tmp, LEN(a) + 100);
СГ>  FOR i := 0 TO LEN(tmp)-1 DO tmp[i] := a[i] END;
СГ>  a := tmp;
СГ>

СГ>это что теперь проблемой называется????

СГ>А я то думал, что проблема, это, например, придумать хорошую эвристику для NP-задачи...


Да нет, проблема — это вылавливать в коде на 25000 строк LEN(tmp) вместо LEN(tmp)-1, написанные по привычке tmp[i] := a[i] вместо DeepCopy(tmp[i], a[i]). Причем в разных случая циклы могут чуть-чуть отличаться, как в случае с DeepCopy, например, так что процедурой не отмажешься, и придется в каждый кусок кода вникать. Тут — копирование, там — вставка, там — сдвиг, там — элементы ссылаются на индексы друг друга в этом массиве. Через неделю ты забудешь, что эта программа делает
Re[14]: Оберон vs все остальное
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 14.01.05 07:54
Оценка: -1
Здравствуйте, Кодёнок, Вы писали:

Кё> Да нет, проблема — это вылавливать в коде на 25000 строк LEN(tmp) вместо LEN(tmp)-1, написанные по привычке tmp[i] := a[i] вместо DeepCopy(tmp[i], a[i]). Причем в разных случая циклы могут чуть-чуть отличаться, как в случае с DeepCopy, например, так что процедурой не отмажешься, и придется в каждый кусок кода вникать. Тут — копирование, там — вставка, там — сдвиг, там — элементы ссылаются на индексы друг друга в этом массиве. Через неделю ты забудешь, что эта программа делает


Да ладно Вам фантазировать, ничего вылавливать не надо, все пишется в 1 экземпляре в одном модуле.
Re[15]: Оберон vs все остальное
От: Кодёнок  
Дата: 14.01.05 07:58
Оценка:
СГ>Да ладно Вам фантазировать, ничего вылавливать не надо, все пишется в 1 экземпляре в одном модуле.

Это опыт работы с Дельфи...
Re[10]: Оберон vs все остальное
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 14.01.05 08:08
Оценка: -1 :)
Здравствуйте, Кодёнок, Вы писали:

Кё>Число параметров и типы могут отличаться, короче — быть любыми. Что, будешь писать разные процедуры для каждой новой комбинации?


Кё>
Кё>PROCEDURE bind_void_void(IN A: PROCEDURE; ...): functor
Кё>PROCEDURE bind_void_int(IN A: PROCEDURE(a:integer); ...): functor
Кё>PROCEDURE bind_void_real(IN A: PROCEDURE(a:read...): functor
Кё>PROCEDURE bind_void_int_real(IN A: PROCEDURE(a:read...)
Кё>PROCEDURE bind_void_real_int(IN A: PROCEDURE(a:read...)
Кё>


Ах вот в чем дело. То есть термином "гибкость" здесь названо, то, что другие люди называют термином "грязный хак". Дело в том, что когда возникает необходимость определить процедуру принимающую произвольное количество аргументов различных типов, то это решается элементарнейшим способом:
TYPE
  Params = ABSTRACT RECORD END;

PROCEDURE Bind(VAR params: Params);


TYPE
  Params1 = RECORD (Params)
    (* Какие угодно параметры *)
  END;

PROCEDURE Bind1(VAR params: Params);
BEGIN
  WITH params: Params1 DO (* ... *) ELSE (* ... *) END
END Bind1;

TYPE
  Params2 = RECORD (Params)
    (* Какие угодно параметры *)
  END;

PROCEDURE Bind2(VAR params: Params);
BEGIN
  WITH params: Params2 DO (* ... *) ELSE (* ... *) END
END Bind2;
Re[11]: Оберон vs все остальное
От: Кодёнок  
Дата: 14.01.05 08:16
Оценка: +4
СГ>Ах вот в чем дело. То есть термином "гибкость" здесь названо, то, что другие люди называют термином "грязный хак". Дело в том, что когда возникает необходимость определить процедуру принимающую произвольное количество аргументов различных типов, то это решается элементарнейшим способом:

Сам-то понял что написал? Нет ни у меня хака, ни у тебя элементарности.
Re[11]: Оберон vs все остальное
От: Курилка Россия http://kirya.narod.ru/
Дата: 14.01.05 08:17
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

<skipped>

Т.е. проверку делаем в рантайме со всеми вытекающими (довольно "грязными") последствиями?
Re[8]: Оберон vs все остальное
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 14.01.05 08:22
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Кстати, а как твоим функциям передавать КОНТЕКСТ вычислений? Или как обычно, через глобальные переменные?


Да.

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



Впрочем, если возникает необходимость в нескольких контекстах вычисления одновременно, то Вы правы, тут уже надо использовать ООП, и смысл в именно такой функции какую просил я значительно снижается — ведь можно использовать для того же самого другие средства уже свойственные только ООП.
Re[9]: Оберон vs все остальное
От: Cyberax Марс  
Дата: 14.01.05 08:33
Оценка:
Сергей Губанов пишет:

> C>Кстати, а как твоим функциям передавать КОНТЕКСТ вычислений? Или как

> обычно, через глобальные переменные?
> Да.

В морг. СРАЗУ же, без разговоров.

> Только глобальные переменные в модульных языках — это вовсе не тоже

> самое что глобальные переменные в не модульных языках. В модульных
> языках все переменные находятся внутри модулей, а модули загружаются в
> память и выгружаются из нее динамически во время работы программы — то
> есть никакие они (переменные) вовсе не "глобальные" в строгом смысле
> этого слова.

Плевать, два потока, исполняющие один код я запустить уже не смогу.
Реентерабельности тоже нет. И не нужно говорить, что это все фигня — это
важнейшие вещи.

> Впрочем, если возникает необходимость в нескольких контекстах

> вычисления одновременно, то Вы правы, тут уже надо использовать ООП, и
> смысл в именно такой функции какую просил я значительно снижается —
> ведь можно использовать для того же самого другие средства уже
> свойственные только ООП.

А контекст нужно передавать ВСЕГДА (в 99.99% случаев), иногда только
можно для целей оптимизации использовать глобальные переменные.

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[11]: Оберон vs все остальное
От: Cyberax Марс  
Дата: 14.01.05 08:35
Оценка:
Сергей Губанов пишет:

> Кё>Число параметров и типы могут отличаться, короче — быть любыми.

> Что, будешь писать разные процедуры для каждой новой комбинации?
> Кё>
>
>Кё>PROCEDURE bind_void_void(IN A: PROCEDURE; ...): functor
>Кё>PROCEDURE bind_void_int(IN A: PROCEDURE(a:integer); ...): functor
>Кё>PROCEDURE bind_void_real(IN A: PROCEDURE(a:read...): functor
>Кё>PROCEDURE bind_void_int_real(IN A: PROCEDURE(a:read...)
>Кё>PROCEDURE bind_void_real_int(IN A: PROCEDURE(a:read...)
>Кё
>
>
> Ах вот в чем дело. То есть термином "гибкость" здесь названо, то, что
> другие люди называют термином "грязный хак". Дело в том, что когда
> возникает необходимость определить процедуру принимающую произвольное
> количество аргументов различных типов, то это решается элементарнейшим
> способом:

Не совсем то. Вот есть у меня функциональный оператор с сигнатурой "void
(int,int)", я хочу на него сделать
адаптер вида "void(int)", а второй параметр сделать равным 2. С boost'ом
это делается так:
=============
boost::bind(xxx,указатель_на_функтор,_1,2);
=============
У меня создается функтор, принимающий один параметр, делегирующий вызов
моему функтору, устанавливая второй его параметр в 2.

И еще раз — совместимость типов проверяется на этапе компиляции.

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[12]: Оберон vs все остальное
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 14.01.05 08:36
Оценка:
Здравствуйте, Курилка, Вы писали:

К>Т.е. проверку делаем в рантайме со всеми вытекающими (довольно "грязными") последствиями?


В оберонах вообще и в Component Pascal в частности нет множественного наследования, а есть просто расширение типа. В связи с этим инструкция конкретизации типа
WITH v: T1 DO S1 | v: T2 DO S2 | v: T3 DO S3 ... ELSE Sn END

не обладает ни какими грязными последствиями, а также выполняется очень быстро — примерно так же быстро как выполнялся бы обычный CASE (или switch) по скрытому тэгу в записи (ну разьве только что если иерархия расширения типов будет глубокой — вот из-за этого может быть чуток медленнее).
Re[10]: Оберон vs все остальное
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 14.01.05 08:40
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Плевать, два потока, исполняющие один код я запустить уже не смогу.

C>А контекст нужно передавать ВСЕГДА (в 99.99% случаев), иногда только
C>можно для целей оптимизации использовать глобальные переменные.

А если система встроенная и там потоков нет?
Re[13]: Оберон vs все остальное
От: Курилка Россия http://kirya.narod.ru/
Дата: 14.01.05 08:43
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Здравствуйте, Курилка, Вы писали:


К>>Т.е. проверку делаем в рантайме со всеми вытекающими (довольно "грязными") последствиями?


СГ>В оберонах вообще и в Component Pascal в частности нет множественного наследования, а есть просто расширение типа. В связи с этим инструкция конкретизации типа

СГ>
СГ>WITH v: T1 DO S1 | v: T2 DO S2 | v: T3 DO S3 ... ELSE Sn END
СГ>

СГ>не обладает ни какими грязными последствиями, а также выполняется очень быстро — примерно так же быстро как выполнялся бы обычный CASE (или switch) по скрытому тэгу в записи (ну разьве только что если иерархия расширения типов будет глубокой — вот из-за этого может быть чуток медленнее).

С чего это не обладает?
Например:
Берём ситуацию, что в with ты забудешь один из типов по запарке, бывает такое, ну и оберон твой нихрена не скажет, всё будет ништяк, но работать-то будет в итоге прога не правильно.
А в плюсах тебе компилер скажет — нифига нет определения с такими параметрами, соответственно ты прогу даже скомпилить не сможешь.
Что ты скажешь хотябы на это?
Re[11]: Оберон vs все остальное
От: Cyberax Марс  
Дата: 14.01.05 08:49
Оценка: +1
Сергей Губанов пишет:

> C>Плевать, два потока, исполняющие один код я запустить уже не смогу.

> C>А контекст нужно передавать ВСЕГДА (в 99.99% случаев), иногда только
> C>можно для целей оптимизации использовать глобальные переменные.
> А если система встроенная и там потоков нет?

Тогда там нечего делать GC, и код следует писать на С/Asm. Кроме того,
проблема реентерабельности никуда не исчезает и без потоков (что будет,
если я захочу два конечных автомата, вызывающих друг друга?).

Кстати, на С такая функция будет выглядеть так:
=========
void* func(void* someFunc)
{
return someFunc;
}

...
void funcPtr=func(&func);
assert(funcPtr==&func);
=========
Хотя нетипобезопасно получается, но во встроенных системах (если уж о
них разговор) это обычно не так важно.

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.