|
Конечный автомат и 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, через промежуточные. Получается, что все промежуточные состояния должны иметь в себе проверки, которые могут переопределить по исполнению условий направление перехода. При это совершенно не понятно, а что должно происходить, если процесс перехода будет пересекаться где-то с другим процессом, то как обеспечивать его перезапуск... В общем, согласен тем более, что при наличии возможности сохранения значения указателя на функцию/процедуру хотя бы в каких-то параметрах сеанса или еще каким-то образом, то смысла в этих всех конструкциях было бы гораздо больше |
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |