Имя: Пароль:
1C
1С v8
Конечный автомат и 1С
0 quest
 
13.06.12
09:54
Как лучше реализовать конечный автомат (множество состояний и переходов) на 1С?
Что использовать - goto или выполнить/вычислить?
или есть другие варианты решения?
1 PR
 
13.06.12
09:55
Соответствие?
Или ты о чем?
2 orefkov
 
13.06.12
09:57
(2)
Goto предано анафеме.
Частокол из ИначеЕсли - вот дао истинного адинэс.
3 shuhard
 
13.06.12
09:58
(0) автомат Мурра или Милли ?
4 Maxus43
 
13.06.12
09:59
выполнить/вычислить - не зло же, если подходит для задачи - то их юзать можно, имхо
5 rs_trade
 
13.06.12
10:01
(2) у семерошних конф раруса помниться был такой стиль написания.
6 mirosh
 
13.06.12
10:01
а в С есть switch )
7 andrewks
 
13.06.12
10:03
(0)а нафига тебе для КА гоуту спонадобилось?
8 skiller3000
 
13.06.12
10:03
switch хорошо бы, а так есть только ИначеЕсли....
9 andrewks
 
13.06.12
10:04
цикл, массив состояний, массив кусочков кода
10 PR
 
13.06.12
10:05
(6) Чем он отличается от ИначеЕсли?
11 Рэйв
 
13.06.12
10:05
(8)ИначеЕсли намного гибче.
12 Рэйв
 
13.06.12
10:06
(10) свич проверяет кейсы одного выражения,а КонецЕсли -любого набора
13 Рэйв
 
13.06.12
10:06
*ИначеЕсли
14 Gesperid
 
13.06.12
10:06
(10), (11) switch - синтаксический сахар по большому счету
15 quest
 
13.06.12
10:07
(1) не понял. Ты о чем? Заменить массив на соответствие? ну тут выигрыша можно и не получить. Разве что читать будет удобней
(2) это шутка или иначе действительно удобнее/выгодней?
(3) по моему из одного можно получить другой. И наоброт. Так что особой разницы нет.
(7) если состояния явно заданы в тексте программы. не храняться в массиве/соответствии
например так
~Состояние1:
  если условие1 тогда
    перейти ~Состояние3
 конецесли;
~Состояние2:
 ....
 перейти ~Состояние4;
~Состояние3:
....
и т.д.
16 Gesperid
 
13.06.12
10:08
(11) цикл "Пока" тоже гибче, чем "для" и тем более "для каждого", но ведь удобно
17 Рэйв
 
13.06.12
10:09
(16)Для определенных моментов - да.
18 orefkov
 
13.06.12
10:09
(14)
Ну, все синтаксический сахар вокруг mov и jne :)
19 ОбычныйЧеловек
 
13.06.12
10:12
Ищем в яндексе статьи про "Регистры правил" и пишем под себя (и забываем про всякие "Goto", "ИначеЕсли" и т.д).
20 PR
 
13.06.12
10:14
(12) То, что ИначеЕсли гибче, я в курсе, я говорю, в чем принципиальное отличие в том случае, когда проверяется одно выражение?
21 PR
 
13.06.12
10:15
(15) Так ты может уже расскажешь, что именно хочешь?
22 Рэйв
 
13.06.12
10:15
(20)Если одно, то никакого. switch - это частный случай else if :-)
23 Рэйв
 
13.06.12
10:18
(15)>>перейти ~Состояние4;

Организуй с помощью вызова процедур.
Одна процедура- одно состояние.
24 quest
 
13.06.12
10:19
(21) да вот задумался тут переписывая кусок кода из паскаля - label LexBegin, LexNextState, LexNextSet, LexDone;
var LexEdgePtr:PLexEdge;
   LexSetNr:Integer;
   LexChar:Char;
   LexAccept:Boolean; //reads one character ahead, to enable 123..456
   LexTag, State, OldState:Integer;
begin
 LexTag:=-1;
LexBegin:
 Token.LinePos:=LinePos;
 Token.CharPos:=CharPos;
 Token.Tag:=1; {Tag_ERROR};
 LexemeLen:=0;
 LexemeStr:='';
 State:=InitialState;
 OldState:=InitialState;
 LexChar:=CurChar;
 LexAccept:=False;
LexNextState:
 {$IFDEF Debug_LEXER}
 Write(Fo^,'  LexState=',State:3, ',  ord(Char)=',ord(LexChar):3,',  Char=');
 if ord(LexChar)>31 then write(Fo^,'"',LexChar,'"') else write(Fo^,'***');
 {$ENDIF Debug_LEXER}
 LexEdgePtr:=LexStateList[State];
 LexSetNr:=LexEdgePtr^.SetNr;
 {}
LexNextSet: {Loop}
 if (LexSetNr=Empty) then begin
   LexTag:=LexEdgePtr^.L;
   if (LexTag>=0) or SkipMode then GetChar else begin
     {$IFDEF Debug_LEXER} Write(Fo^,'   (not found, set back)'); {$ENDIF}
     //try to repair error by falling back to previous state;
     LexEdgePtr:=LexStateList[OldState];
     while (LexEdgePtr^.SetNr<>Empty) do inc(LexEdgePtr);
     LexTag:=LexEdgePtr^.L;
   end;
   goto LexDone;
 end;
 if (ord(LexChar) in CharSet[LexSetNr]) then begin
   {$IFDEF Debug_LEXER} WriteLn(Fo^,',  (Found in CharSet[',LexSetNr,'])'); {$ENDIF}
   OldState:=State;
   State:=LexEdgePtr^.L;
   if SkipMode and (LexemeLen=1) then goto LexBegin;
   if LexAccept then GetChar;
   LexChar:=NextChar; LexAccept:=True;
   goto LexNextState;
 end;
 inc(LexEdgePtr);
 LexSetNr:=LexEdgePtr^.SetNr;
 goto LexNextSet;  {next}
 {}
LexDone:
 if (LexTag<0) and (CurChar=EOF) then LexTag:=0; {TAG_EOF}
 {$IFDEF Debug_LEXER} WriteLn(Fo^,',  ==> Tag:=',LexTag); {$ENDIF}
 GetLexeme:=LexTag;
end;

можно ли его попроще как-то переписать в 1С не потеряв в производительности
25 quest
 
13.06.12
10:20
(23) тогда будет туевая хуча гломабльный переменных. Или таскать их придется через параметры.
26 quest
 
13.06.12
10:21
гломабльный  = глобальных
27 Фрэнки
 
13.06.12
10:22
(25) все-таки язык в модулях 1С-ки = метакод, а не ассемблер, с передачей параметров между процедурами через стэк
28 PR
 
13.06.12
10:23
(24) Ну, для начала перепиши его без GoTo, а там может это и будет конечным приемлемым вариантом.
29 Кирпич
 
13.06.12
10:25
(24) ну без потери производительности не получится. язык 1с раз в сто медленнее паскаля :))
30 Фрэнки
 
13.06.12
10:26
(26) и даже наличие глобальных переменных модуля не слишком критично, поскольку деструкторы объектов явным образом не вызываются и влиять на размер съедаемой памяти не могут. Кстати, при передаче параметров в вызовах процедур могут быть свои преимущества, хотя бы и в том, что можно выборочно блокировать их от изменения
31 orefkov
 
13.06.12
10:26
(15)
Ну, смысл КА не в одной смене состояния же, но в действиях при смене состояния.
И обычно он пишется так:


   Пока Истина Цикл
       Если ТекСостояние = 0 Тогда
           Если Условие1() Тогда
               ДействияИз0в1();
               ТекСостояние = 1;
           ИначеЕсли Условие2() Тогда
               ДействияИз0в2();
               ТекСостояние = 2;
           КонецЕсли;
       ИначеЕсли ТекСостояние = 1 Тогда
           ...
       ИначеЕсли ТекСостояние = 2 Тогда
           ...
       КонецЕсли;
   КонецЦикла;
32 badboychik
 
13.06.12
10:29
напиши на нормальном языке внешнюю компоненту и не морщи мозг
33 orefkov
 
13.06.12
10:29
(19)
И как регистр правил поможет выполнить конкретный код для конкретного правила?
Вычислить / Выполнить строку с правилом?
Хорошо ли размазывать код логики по хранилищу?
34 Кирпич
 
13.06.12
10:33
(0) Лексер можно написать и без всяких автоматов. Это довольно просто. За день управишься. Код на автоматах обычно генерируют всякие приблуды типа Lex.
35 Фрэнки
 
13.06.12
10:33
(31) ТекСостояние = ДействияИз0в1(); // <- в виде функции с возвратом нового состояния в качестве текущего

а еще лучще вместо Пока Истина Цикл устанавливать функцию обработки состояний в рекурсии
36 Фрэнки
 
13.06.12
10:36
35+ но лучше не функцией, а процедурой с параметром ТекущееСостояние
Процедура будет легче обрабатываться и код читабельней
37 eduspec82
 
13.06.12
10:39
реккурсия конечно же ыыы
38 ОбычныйЧеловек
 
13.06.12
10:41
(33) >>Вычислить / Выполнить строку с правилом?
В общем и целом - ДА.

>>Хорошо ли размазывать код логики по хранилищу?
Как раз вся логика находится в одной табличке правил, т.е. что-бы изменить правило нет необходимости лезь в код и что-то там менять (добавляя очередные "ИначеЕсли") - достаточно в пользовательском режиме изменить настройки правил.
39 orefkov
 
13.06.12
10:41
(35)
Это был пример для пояснения сути "частокола ИначеЕсли".
И как в 1С "устанавливать функцию обработки состояний" ?
Указателей на функции в 1С нет.
Код покажи для пояснения мысли, если можно.
40 orefkov
 
13.06.12
10:45
(38)
Это я и называю "размазывать код по хранилищу".
грубо говоря, этот же код должен быть изначально как-то прописан в регистр, хотя бы при инсталляции программы.
То есть придется писать код, записывающий этот код в хранилище :)
Это только один из минусов.
41 Рэйв
 
13.06.12
10:51
(39)>>Указателей на функции в 1С нет.
:-)

Зато есть:

Для Состояние=1 по 10 Цикл
  Выполнить("ВызовФункцияНомер"+Состояние+"()");
КонецЦикла;
42 ОбычныйЧеловек
 
13.06.12
10:53
(40) >>То есть придется писать код, записывающий этот код в хранилище :)
Ну это не смертельно (при обновлении конфы обычно много чего\куда пишется и ничего), хотя согласен, что это не удобно.

>>Это только один из минусов.
А еще какие минусы есть? (просто интересно)
43 orefkov
 
13.06.12
11:15
(42)
Ну, медленная работа Выполнить. Невозможность Выполнить в вебклиенте.
Возможность кривыми руками пользователя поломать код.
И все из-за отсутствия в 1С возможности косвенного вызова функции.

(41)
Опять Выполнить? Убогость какая все-таки в этом плане у 1С.
Хотя бы такой вариант предложили:
Обработчик = Обработки.Состояние0.Создать();
Обработчик = Обработчик.ОбработатьСостояние(текСостояние, Данные);

Короче, надо или ООП, или просто хотя бы иметь указатель на функцию.
44 quest
 
13.06.12
12:01
(34) так мне к такой приблуде и надо написать шаблон. И особо переписывать код не хочется :(
(43) Прикольный вариант. Надо будет обдумать - может быть имеет смысл и в этом направлении поэксперементировать.
45 _Atilla
 
13.06.12
13:18
(0) Обычно делаю так:
Спр. Состояния
Табличная часть "След. состояния"

Одним словом это "Таблица переходов"
46 _Atilla
 
13.06.12
13:21
(45) Более сложный вариант
Спр Состояния
Подч. спр "След. состояния"
Подч. спр "Разреш. польз"
47 DVN
 
13.06.12
13:23
Рекурсия -наше все :)
48 _Atilla
 
13.06.12
13:27
(45) (46)
"След. состояния" может иметь 2 рекв
1. след. состояние  (Спр. состояния)
2. Действие (название процедуры)
49 _Atilla
 
13.06.12
13:35
(0) (19) http://aitika.ru/program/146-1c-Podsistema-Registri-pravil
Статья про "Регистры правил".

Есть даже пример в 1С.
50 Фрэнки
 
13.06.12
14:54
(39) согласен полностью, что без установки обработчика событий и без указателей на функции/процедуры весь код рекурсивной обработки будет слабоват.

Допустим есть переход из состояния А1 по какой-то цепочке в А99, через промежуточные. Получается, что все промежуточные состояния должны иметь в себе проверки, которые могут переопределить по исполнению условий направление перехода. При это совершенно не понятно, а что должно происходить, если процесс перехода будет пересекаться где-то с другим процессом, то как обеспечивать его перезапуск... В общем, согласен тем более, что при наличии возможности сохранения значения указателя на функцию/процедуру хотя бы в каких-то параметрах сеанса или еще каким-то образом, то смысла в этих всех конструкциях было бы гораздо больше