Имя: Пароль:
1C
1С v8
Рекурсивная функция некорректно работает
0 Tata_77159
 
19.01.24
11:49
В моей практике рекурсию приходилось писать пару раз в жизни
Вопрос: написана рекурсия, при отладке на  точке "Возврат  БизнесПроцесс;" - обращение идет столько сколько было итераций в функции, а не единожды,  подскажите пожалуйста что неверно написано



Функция ПолучитьГП(БизнесПроцесс) Экспорт
             
        Запрос = ...
        
        РезультатЗапроса    =  Запрос.Выполнить();
        
        Если не РезультатЗапроса.Пустой() Тогда
            
            Выборка    = Запрос.Выполнить().Выбрать();
            Выборка.Следующий();
            БизнесПроцесс = Выборка.ГП;    
            ПолучитьГП(БизнесПроцесс);
            
        КонецЕсли;          
        
        Возврат  БизнесПроцесс;

КонецФункции

И смущает этот код
БизнесПроцесс = Выборка.ГП;    
ПолучитьГП(БизнесПроцесс);
Без присвоения БизнесПроцесс = Выборка.ГП;   возврат идет первоначального значения вызываемой функции
1 Волшебник
 
19.01.24
11:58
что такое ГП? Опишите задачу в терминах предметной области
2 Tata_77159
 
19.01.24
12:03
(1) ГлавныйПроцесс - корень всех бизнес-процессов
Задача, по текущему процессу нахожу корень , поэтому применена рекурсия , рекурсия в принципе выдает правильный результат , но я думаю что немного тут некорректно идет
3 Галахад
 
гуру
19.01.24
12:10
Если не РезультатЗапроса.Пустой() Тогда
...
Иначе
   Возврат  БизнесПроцесс;
КонецЕсли;
4 mikecool
 
19.01.24
12:11
работает - не трожь
5 Tata_77159
 
19.01.24
12:15
(3) тогда при отладке на строке КонецФункции - несколько раз точка останова срабатывает , это пробовала
6 Галахад
 
гуру
19.01.24
12:22
(5) Не понял. Это же рекурсия. Функция отрабатывает несколько раз...
7 lodger
 
19.01.24
12:23
(0)
если отбросить всю шелуху, то вот эти 4 строки волнуют.

Функция ПолучитьГП(БизнесПроцесс) Экспорт
БизнесПроцесс = Выборка.ГП;    
ПолучитьГП(БизнесПроцесс);
Возврат БизнесПроцесс;
8 Tata_77159
 
19.01.24
12:25
(6) ну функция должна в конец функции один раз прийти или несколько раз (т.е. столько раз сколько итераций было)?
9 lodger
 
19.01.24
12:25
(7) а) вы входящему параметру присваиваете новое значение
б) вызываете функцию и не ловите возвращаемый ответ
в) возвращаете входящую переменную.

по отдельности эти трюки - вроде ладно, но вместе вызывают бесконечный самовызов.
10 RVN
 
19.01.24
12:27
(8) Т.к. вы функцию вызываете несколько раз (сколько итераций было) столько раз она в конец и придет.
11 Волшебник
 
19.01.24
12:33
(0) Покажите запрос. Может он там не нужен и достаточно точки?
12 Tata_77159
 
19.01.24
12:34
Функция ПолучитьГлавныйПроцесс(БизнесПроцесс) Экспорт
    
         ГоловнойБизнесПроцесс = БизнесПроцесс;    
        
        Запрос = Новый Запрос ("ВЫБРАТЬ
        |    ДочерниеБизнесПроцессы.РодительскийПроцесс КАК ГоловнойБизнесПроцесс
        |ИЗ
        |    РегистрСведений.ДочерниеБизнесПроцессы КАК ДочерниеБизнесПроцессы
        |ГДЕ
        |    ДочерниеБизнесПроцессы.ДочернийПроцесс = &ДочернийПроцесс");
        
        Запрос.УстановитьПараметр("ДочернийПроцесс",БизнесПроцесс);
        
        РезультатЗапроса    =  Запрос.Выполнить();
        
        Если не РезультатЗапроса.Пустой() Тогда
            
            Выборка    = Запрос.Выполнить().Выбрать();
            Выборка.Следующий();    
            ГоловнойБизнесПроцесс=ПолучитьГлавныйПроцесс(Выборка.ГоловнойБизнесПроцесс);
        Иначе
            Возврат  ГоловнойБизнесПроцесс;
        КонецЕсли;          
КонецФункции
13 mikecool
 
19.01.24
12:37
(12) главный БП проще сделать реквизитом БП
14 Tata_77159
 
19.01.24
12:38
(0) в таком варианте не работает , после строки  Возврат  ГоловнойБизнесПроцесс; ,  точка останова идет на КонецФункции и там несколько раз происходят итерации и переменные
ГоловнойБизнесПроцесс и БизнесПроцесс - меняются  и в результате при окончании процедуры выходит Неопределенно
15 Волшебник
 
19.01.24
12:40
(12) главный БП проще сделать реквизитом БП

Потом уберите рекурсию вообще. Используйте цикл Пока

Функция ПолучитьГлавныйПроцесс(Знач БП) Экспорт
  Пока НЕ БП.РодительскийПроцесс.Пустая() Цикл
     БП = БП.РодительскийПроцесс;
  КонецЦикла;
  Возврат БП;
КонецФункции


Хотя если хотите красиво с рекурсией, то можно так:

Функция ПолучитьГлавныйПроцесс(Знач БП) Экспорт
  Возврат ?(БП.РодительскийПроцесс.Пустая(), БП, ПолучитьГлавныйПроцесс(БП.РодительскийПроцесс);
КонецФункции
16 Tata_77159
 
19.01.24
12:50
(15) я не могу сделать реквизит , потому что пока это не нужно
17 Волшебник
 
19.01.24
13:04
(16) Тогда заведите ещё одну функцию ПолучитьРодительскийБП и используйте её вместо конструкции "БП.РодительскийПроцесс"
Независимо от того, куда вы едете — это в гору и против ветра!