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