Имя: Пароль:
1C
1С v8
Как выйти из рекурсивной функции в нужный мне момент?
,
0 aptomilov
 
26.06.12
11:17
Собственно возврат стоит в самом начале  а она один хер пробегает все дерево ваще недогоняю почему отладчиком  статус все функции бывает истина

Процедура ЗаписатьЗначениеВ_ТЗБ(ТабПараметров,Стр,Ветка,ЭтоПлан=Ложь,Ключ="",СтатусВсейФункции=Ложь)
   Если  СтатусВсейФункции Тогда
       Возврат;
   КонецЕсли;
   СтатусФункции =Ложь;
   Для Каждого Узел Из Ветка.Строки Цикл
       ИдентификаторУзла=     Узел.N;
       НаименованиеУзла = Узел.Наименование;
       ЭтоНоваяСтрока=НаименованиеУзла = "Структура бюжета ООО 'Интерполис'";            
       Если ЭтоНоваяСтрока Тогда
           Попытка
               Если  СтатусПроверкиТекущихДанных=0 Тогда
                   ЗаписатьТзВотстойник(ПредИдущаяТаблица);
               КонецЕсли;
           Исключение
           КонецПопытки;
           СтатусПроверкиТекущихДанных=0;
       КонецЕсли;    
       ПредИдущаяТаблица=ТабПараметров;
       Если ИдентификаторУзла<>Неопределено   ТОгда
           УровеньУзла=     Узел.Уровень();
           ЗначениеВетки=    Узел.Значение;
           НаименованиеВетки=СокрЛП(Узел.Наименование);
           Если  не ЭтоПлан или Ключ=ИдентификаторУзла Тогда
               СтатусФункции = ПроверитьЗначениеВТЗБ(Узел,УровеньУзла,ЗначениеВетки,НаименованиеВетки,ТабПараметров,Стр,ИдентификаторУзла,ЭтоПлан);
               Если СтатусФункции Тогда
                   СтатусПроверкиТекущихДанных=СтатусПроверкиТекущихДанных+1;
               КонецЕсли;
           КонецЕсли;
       КонецЕсли;
       ЗаписатьЗначениеВ_ТЗБ(ТабПараметров,Стр,Узел,ЭтоПлан,Ключ,СтатусФункции)
   КонецЦикла;
КонецПроцедуры
1 Alex S D
 
26.06.12
11:18
а возврат происходит в первом вызове? раскрутка стэка
2 aptomilov
 
26.06.12
11:18
не обязательно в первом может и в десятом
3 Андрюха
 
26.06.12
11:19
Глобальную переменную и проверяй ее на истинность в рекурсивной функции
4 Жан Пердежон
 
26.06.12
11:19
рекурсию можно заменить циклом со стеком
5 aptomilov
 
26.06.12
11:22
да как бы хочется так нормальный способ выхода из рекурсии
(3) отладчиком смотрел как она проходит возврат и исполняет его и потом прыгает на саму себя в цикле и полетели дальше
6 Alex S D
 
26.06.12
11:22
ЗаписатьЗначениеВ_ТЗБ(ТабПараметров,Стр,Узел,ЭтоПлан,Ключ,СтатусФункции) может это за цикл вынести?
7 Alex S D
 
26.06.12
11:22
хотя не
8 aptomilov
 
26.06.12
11:23
(6) неа как я тогда буду ветку передавать в рекурсию
9 Ненавижу 1С
 
гуру
26.06.12
11:23
Если ИдентификаторУзла<>Неопределено   ТОгда
           УровеньУзла=     Узел.Уровень();
           ЗначениеВетки=    Узел.Значение;
           НаименованиеВетки=СокрЛП(Узел.Наименование);
           Если  не ЭтоПлан или Ключ=ИдентификаторУзла Тогда
               СтатусФункции = ПроверитьЗначениеВТЗБ(Узел,УровеньУзла,ЗначениеВетки,НаименованиеВетки,ТабПараметров,Стр,ИдентификаторУзла,ЭтоПлан);


всегда Ложь?
10 aptomilov
 
26.06.12
11:23
11 aptomilov
 
26.06.12
11:23
нет не всегда
12 aptomilov
 
26.06.12
11:25
я не жалуюсь на работу функции я не пойму как с нее вылететь хочу вылетать как только СтатусФункции будет истина
13 aptomilov
 
26.06.12
11:26
Возраты ставил где попало не помогает пока блин дерево не оббежит не успокоится
14 Alex S D
 
26.06.12
11:27
так может возврат из цикла делать?
15 Alex S D
 
26.06.12
11:28
(13) так у тебя 10 раз идет вызов функции, и затем этот экземпляр закрывает сам себя.. но не верхний уровень
16 Irbis
 
26.06.12
11:28
А параметр у функции ПринудительныйВыходИзРекурсии и в нужном месте менять его.
17 ILM
 
гуру
26.06.12
11:30
Ф1(1) вызов
Ф1(2) вызов
ф1(3) вызов
ф1(4) вызов
ф1(5) вот тут возврат бла-бла, куда пойдет управление?  
Правильно на Ф1(4)
18 aptomilov
 
26.06.12
11:31
(14) ставил не помогает
(15) интересная мысль и чего можно сделать
(16) такой параметр уже есть СтатусФункции)
19 Irbis
 
26.06.12
11:32
(18) И что тогда не устраивает, то что обратно рекурсия собирается? Так это правильно.
20 aptomilov
 
26.06.12
11:32
(17) все я понял а чего можно сделать чтоб прибить ее на корню
21 Irbis
 
26.06.12
11:33
(20) Не нужно ничего делать. Не крайняк безусловный переход по метке.
22 IamAlexy
 
26.06.12
11:33
ресетом
23 aptomilov
 
26.06.12
11:33
безуловный в другую процедуру тогда))
24 aptomilov
 
26.06.12
11:34
ресет ваще тема
25 Irbis
 
26.06.12
11:34
(23) Ты же этого добиваешься.
26 Kolls
 
26.06.12
11:35
Глобальную переменную модуля, и проверять ее на истину в начале функции, и так же в теле фунции после ее вызова
27 aptomilov
 
26.06.12
11:36
(26) в этом случае она просто покрутиться в холостую пока выйдет напервый уровень
28 Жан Пердежон
 
26.06.12
11:39
или СтатусФункции всегда Ложь
или ТС не умеет пользоваться отладчиком
29 orefkov
 
26.06.12
11:41
Выход из всей рекурсии:

Процедура Рекурсивная(счетчик)
   Если счетчик = 100 Тогда
       ВызватьИсключение "Выход";
   Иначе
       Рекурсивная(счетчик + 1);
   КонецЕсли;
КонецПроцедуры

Попытка
   Рекурсивная(0);
Исключение
   Если ОписаниеОшибки() = "Выход" Тогда
       Сообщить("Все нормально");
   КонецЕсли;
КонецПопытки;
30 Rie
 
26.06.12
11:42
(29) +1000000
31 aleks-id
 
26.06.12
11:44
(29) опередил :)
хотел написать а=1/0;
32 Жан Пердежон
 
26.06.12
11:47
(29) фу, грязный хак
33 orefkov
 
26.06.12
11:48
(31)
Так в 77 приходилось делать, ибо ВызватьИсключение не было. И то считалось кошерным юзать
аа=СоздатьОбъект("НесуществующийОбъект-Выход");
дабы из описания ошибки выцепить полезную инфу.
34 Мигрень
 
26.06.12
11:48
Средневековых программистов сжигали за веру в рекурсию. © Д. Кнут
35 orefkov
 
26.06.12
11:49
(32)
Почему же хак? И почему грязный?
Считаешь правильнее при каждом вызове вложенной функции проверять код возврата?
36 Kreont
 
26.06.12
11:52
(0) А не смущает что все передается явно, и правиться потом прямо в теле процедуры, и изза этого и выхода норм нету?
Поменяй:
Процедура ЗаписатьЗначениеВ_ТЗБ(ТабПараметров,Стр,Ветка,ЭтоПлан=Ложь,Ключ="",СтатусВсейФункции=Ложь)
на
Процедура ЗаписатьЗначениеВ_ТЗБ(ТабПараметров,Стр,Ветка,ЭтоПлан=Ложь,Ключ="",Знач СтатусВсейФункции=Ложь)
37 ILM
 
гуру
26.06.12
11:52
Утечки памяти не будет? Стек вызовов вроде бы остается.
38 izekia
 
26.06.12
11:54
(35) а почему бы ей просто не выходить?
39 izekia
 
26.06.12
11:55
автор просто не проникся духом рекурсии, точнее думает что рекурсия - это вызов процедуры из самой себя, отсюда и соответствующие проблемы
40 izekia
 
26.06.12
11:56
+(38) просто если мы вернулись из рекурсивного вызова, значит мы там все сделали и дополнительных проверок не нужно, а иначе проблема в алгоритме
41 Жан Пердежон
 
26.06.12
11:58
(35) нет, проверять его перед вызовом
42 orefkov
 
26.06.12
16:14
(40)
Это справедливо только для хвостовой рекурсии, а она редка, т.к. всегда без проблем заменяется циклом.
А допустим, любой алгоритм обхода дерева вызывает рекурсию для каждого из подчиненных узлов, и после каждого вызова тогда надо проверять - обрабатывать следующие узлы или прерваться и вернуться.
43 orefkov
 
26.06.12
16:14
(41)
Что пнем об сову, что совой об пень.
44 izekia
 
26.06.12
16:16
(42) то есть мы не все подчиненные элементы обрабатываем?
45 orefkov
 
26.06.12
16:19
(44)
Почему бы и нет.
Например, задача - найти первую строку в дереве, удовлетворяющую какому-либо условию.
Как раз и надо, если условие для строки выполняется - выйти из всей рекурсии, не перебирая остальные строки.
46 izekia
 
26.06.12
16:37
Функция НайтиСтроку(строка)
   Возврат ЭтоТаСтрока(строка) ИЛИ строка.Строки.Количество() > 0 И НайтиСтроку(строка);
КонецФункции
47 izekia
 
26.06.12
16:38
(46 слажал, сейчас поправлю
48 izekia
 
26.06.12
16:42
Функция ОбработатьСтроку(строка)
   Возврат ЭтоТаСтрока(строка) ИЛИ строка.Строки.Количество() > 0 И НайтиСтроку(строка.Строки);
КонецФункции

Функция НайтиСтроку(строки)
   Для каждого строка Из строки Цикл
       Если ЭтоТаСтрока(строка) Тогда
           Возврат Истина;
       КонецЕсли;
   КонецЦикла;
   Возврат Ложь;
КонецФункции
49 izekia
 
26.06.12
16:44
ну и более правильно все же:
Функция НайтиСтроку(строки)
   Для каждого строка Из строки Цикл
       Если ОбработатьСтроку(строка) Тогда
           Возврат Истина;
       КонецЕсли;
   КонецЦикла;
   Возврат Ложь;
КонецФункции
50 Funeral_Worm
 
26.06.12
16:45
(0) Насколько понял, проверка в начале просто отсекает поддерево. А уровень выше ничего об этом не знает, поэтому делаются дальше рекурсивные вызовы по другим внутренним узлам.
51 izekia
 
26.06.12
16:45
(50) похоронный червь?)
52 orefkov
 
26.06.12
16:55
(49)
Ну вот ты только что подтвердил мое утверждение, и сам же опроверг свое же (40).
Вот в:
"ЭтоТаСтрока(строка) ИЛИ строка.Строки.Количество() > 0 И НайтиСтроку(строка.Строки);"
Ты как раз после вызова рекурсии проверяеешь ее результат и в зависимости от этого прерываешься или нет.
Кроме того, возвращает просто нашли - не нашли. А ты верни найденную строку :)
53 orefkov
 
26.06.12
16:59
+(52)
Даже скорее вот здесь проверяешь результат рекурсивного вызова:

Если ОбработатьСтроку(строка) Тогда
   Возврат Истина;
КонецЕсли;
54 izekia
 
27.06.12
00:33
(52) строку можно вернуть где угодно, хоть в глобальную, хоть вторым параметром, хоть сделать возвратом функции, но тогда код более громоздким станет

я не опроверг (40)
может я не совсем корректно выразился, я имел в виду лишние проверки в коде, здесь я ищу строку, и проверяю нашел ли ее, и если да, то возвращаюсь