О цикле обратном замолвите слово...

30.05.23

Разработка - Механизмы платформы 1С

Однажды, написав статью, расписывающую достоинства 1С, я упомянул среди недостатков - мне не хватает "обратного цикла". При этом, столкнулся с непониманием - "а зачем тебе обратный цикл". Сегодня я отвечу на этот вопрос.
 
 Предисловие

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

Я искренне верю, что внутри фирмы "1С" наши письма с просьбами читают и анализируют. А также, полагаю, они просматривают публикации на Инфостарте.

 
 Про циклы

 В языке 1С платформы "1С:Предприятие 8" на данный момент существует три вида цикла:

  • Цикл "Для" по счетчику, от меньшего к большему, с неизменным шагом +1;
  • Цикл "Для каждого" для коллекций, поддерживающих перебор (большинство коллекций);
  • Цикл "Пока" по условию (только в начале цикла).

И для решения основных задач этого достаточно. А какие виды циклов существуют ещё?

  • Цикл "Для" по счетчику, с настраиваемым шагом (см. язык BASIC)
  • Цикл "Для" от большего к меньшему (с отрицательным шагом -1, или настраиваемым, см. язык PASCAL)
  • Цикл "Делай ... Пока" по условию (в конце цикла, так что цикл выполнится не менее 1 раза, см. язык PASCAL)
  • Существуют также более сложные варианты циклов (см. язык С и все его "потомки").


Однажды, написав статью, расписывающую достоинства 1С, я упомянул среди недостатков - "мне не хватает обратного цикла". При этом, столкнулся с непониманием - "а зачем вообще нужен обратный цикл?". Сегодня я отвечу на этот вопрос.
Итак...

Рассмотрим задачу: 
Есть таблица значений с колонкой, в которой хранятся числа. Требуется удалить все строки, в которых в указанной колонке хранятся четные значения.
Для моделирования такой таблицы и проверки результата подойдёт следующий код:

ТЗ = новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Номер", новый ОписаниеТипов("Число"));
Массив = СтрРазделить("1, 1, 2, 1, 4, 6, 1, 1, 1, 8, 10, 1", ", ", Ложь);
Для каждого НомерСтрокой из Массив Цикл
	ТЗ.Добавить().Номер = Число(НомерСтрокой);
КонецЦикла;

Сообщить("Исходник: " + СтрСоединить(ТЗ.ВыгрузитьКолонку("Номер"), ", "));

// место вставки обработчика

Сообщить("Результат: " + СтрСоединить(ТЗ.ВыгрузитьКолонку("Номер"), ", "));

Имя переменной таблицы "ТЗ", имя колонки "Номер";


Попробуем решить данную задачу "в лоб":

Для сч=0 По ТЗ.Количество()-1 Цикл
	Если ТЗ[сч].Номер % 2 = 0 Тогда
		ТЗ.Удалить(сч);
	КонецЕсли;
КонецЦикла;

Попытка выполнить данный код приведет к исключению: "Индекс находится за границами массива" (да, да, именно "массива" - такую ошибку выдаёт платформа).

 
 Причина ошибки

Причина ошибки в том, что выражение "ТЗ.Количество()-1" рассчитывается только один раз до начала выполнения цикла, а не на каждой итерации (это задействует меньше вычислений и оптимально для большинства случаев использования "Для").
А, т.к. внутри цикла мы удаляем элементы коллекции, то размер этой коллекции тоже уменьшается. В итоге, счетчик выходит за пределы нашей коллекции и попытка чтения элемента приводит к ошибке.

 

Попробуем реализовать это через цикл "Пока"

сч = 0;
Пока сч<ТЗ.Количество() Цикл
	Если ТЗ[сч].Номер % 2 = 0 Тогда
		ТЗ.Удалить(сч);
	КонецЕсли;
	сч = сч + 1;
КонецЦикла;

Теперь мы проверяем Количество() при каждой итерации, что неоптимально в плане вычислительных ресурсов, но позволяет избежать выхода за границы. Вместо этого, можно присвоить ТЗ.Количество() некоторой переменной, сверять сч с ней, и уменьшать её когда удаляем строку. Это будет оптимальнее, но на несколько строк кода больше (а чем больше строк, тем сложнее потом будет его читать и разбирать).
Этот код уже выполнится.
Но в результате выдаст:
Исходник: 1, 1, 2, 1, 4, 6, 1, 1, 1, 8, 10, 1
Результат: 1, 1, 1, 6, 1, 1, 1, 10, 1

 
 Почему удалилось не всё?

Почему удалились не все чётные числа? Давайте разберем пошагово:
сч = 0: Массив значений в колонке: [1, 1, 2, 1, 4, 6, 1, 1, 1, 8, 10, 1], значение в ячейке = 1, пропускаем
сч = 1: Массив значений в колонке: [1, 1, 2, 1, 4, 6, 1, 1, 1, 8, 10, 1], значение в ячейке = 1, пропускаем
сч = 2: Массив значений в колонке: [1, 1, 2, 1, 4, 6, 1, 1, 1, 8, 10, 1], значение в ячейке = 2, удаляем, массив сместился на 1 влево
сч = 3: Массив значений в колонке: [1, 1, 1, 4, 6, 1, 1, 1, 8, 10, 1],     значение в ячейке = 4, удаляем, массив сместился на 1 влево
сч = 4: Массив значений в колонке: [1, 1, 1, 6, 1, 1, 1, 8, 10, 1],         значение в ячейке = 1, пропускаем (!)
сч = 5: Массив значений в колонке: [1, 1, 1, 6, 1, 1, 1, 8, 10, 1],         значение в ячейке = 1, пропускаем
сч = 6: Массив значений в колонке: [1, 1, 1, 6, 1, 1, 1, 8, 10, 1],         значение в ячейке = 1, пропускаем
сч = 7: Массив значений в колонке: [1, 1, 1, 6, 1, 1, 1, 8, 10, 1],         значение в ячейке = 8, удаляем, массив сместился на 1 влево
сч = 8: Массив значений в колонке: [1, 1, 1, 6, 1, 1, 1, 10, 1],             значение в ячейке = 1, пропускаем
сч = 9, сч=ТЗ.Количество(), цикл завершен
(красным выделены значения в строке [сч])

Обратите внимание, когда рядом стоят два четных числа, то после удаления строки - второе число смещается на 1 влево, при этом, счетчик увеличивается на 1 и, получается, перескакивает это число.

Такое происходит не только когда два четных числа стоят рядом. Обратите внимание, что когда сч=2 тоже происходит "перескакивание" через 1 значение, но т.к. оно является нечетным и всё равно не должно было быть удалено, то в результате выполнения это незаметно.

 


А как себя поведёт цикл "Для каждого"?

Для Каждого Строка из ТЗ Цикл
	Если Строка.Номер % 2 = 0 Тогда
		ТЗ.Удалить(Строка);
	КонецЕсли;
КонецЦикла;

Этот код уже выполниться без ошибок. Но результат выдаст точно такой-же, как и цикл "Пока"
Исходник: 1, 1, 2, 1, 4, 6, 1, 1, 1, 8, 10, 1
Результат: 1, 1, 1, 6, 1, 1, 1, 10, 1


Как бы решалась эта задача, если бы у нас был обратный цикл?
"Для" со счетчиком -1 решил бы эту проблему:

Для ТЗ.Количество()-1 По сч=0 Цикл //обратный или шаг -1
	Если ТЗ[сч].Номер % 2 = 0 Тогда
		ТЗ.Удалить(сч);
	КонецЕсли;
КонецЦикла;

Т.к. обход коллекции выполняется в обратном порядке, удаление элемента смещает массив относительно счетчика цикла, но и счетчик смещается в том-же направлении.


 

Так как-же быть?
А теперь, варианты костылей, с помощью которых решается эта задача (все они приводят к желаемому результату):

1. Аналог решения, встречаемый в типовых конфигурациях 1С:

МассивНаУдаление = новый Массив;

Для каждого Строка из ТЗ Цикл
	Если Строка.Номер % 2 = 0 Тогда
		МассивНаУдаление.Добавить(Строка);
	КонецЕсли;
КонецЦикла;

Для каждого Строка из МассивНаУдаление Цикл
	ТЗ.Удалить(Строка);
КонецЦикла;

Нужны комментарии?


2. Вариант с циклом "Пока", но со смещением или счетчика или строки

сч = 0;
Пока сч<ТЗ.Количество() Цикл
	Если ТЗ[сч].Номер % 2 = 0 Тогда
		ТЗ.Удалить(сч);
	Иначе
		сч = сч + 1;
	КонецЕсли;
КонецЦикла;


3. Еще один вариант с циклом "Пока"

сч = 0;
Пока сч<ТЗ.Количество() Цикл
	Если ТЗ[сч].Номер %2 = 0 Тогда
		ТЗ.Удалить(сч);
		сч = сч - 1;
	КонецЕсли;
	сч = сч + 1;
КонецЦикла;


4. Эмуляция обратного цикла с помощью цикла "Пока"
(сам я, чаще всего, в коде делаю именно так, т.к. это минимум лишних операций и уменьшение счетчика в первой-же строке внутри цикла гарантирует, что если в теле цикла будет "Продолжить" - не произойдёт зацикливание)

сч = ТЗ.Количество();
Пока сч>0 Цикл
	сч = сч - 1;
	Если ТЗ[сч].Номер % 2 = 0 Тогда
		ТЗ.Удалить(сч);
	КонецЕсли;
КонецЦикла;


5. Эмуляция обратного цикла с помощью цикла "Для"
(а этот метод мне попался недавно, и заинтересовал. Хотя количество операций смены знака здесь немалое, код смотрится весьма лаконично)

Для сч = -ТЗ.Количество() + 1 По 0 Цикл
	Если ТЗ[-сч].Номер % 2 = 0 Тогда
		ТЗ.Удалить(-сч);
	КонецЕсли;
КонецЦикла;

Ну да, цикл "Для" хоть и по счетчику +1, но нормально работает с отрицательными числами.

6. Еще такой вариант встречается часто:

Количество = Коллекция.Количество();
Для Номер = 1 По Количество Цикл
	ОбратныйИндекс = Количество - Номер;
	Коллекция.Удалить(ОбратныйИндекс);
КонецЦикла;

Автор: (70)  PerlAmutor 29.05.23 06:49

 
Резюмирую

Это упрощенная вариация задач, периодически встречающихся в разработке, к задачам такого-же плана относятся задачи вида "удалить все цифры из строки", "удалить дублирующиеся элементы в коллекции". Даже сама фирма 1С сталкивается с подобными задачами при разработке своих типовых решений. И задача очень лаконично решается через обратный цикл. Вот почему мне бы хотелось видеть его в составе конструкций языка 1С (а заодно, можно бы и "Для каждого" допилить, чтобы не пропускал элементы коллекции).

См. также

Поинтегрируем: сервисы интеграции – новый стандарт или просто коннектор?

Обмен между базами 1C Администрирование СУБД Механизмы платформы 1С Платформа 1С v8.3 Бесплатно (free)

В платформе 8.3.17 появился замечательный механизм «Сервисы интеграции». Многие считают, что это просто коннектор 1С:Шины. Так ли это?

11.03.2024    5882    dsdred    53    

83

Как готовить и есть массивы

Механизмы платформы 1С Платформа 1С v8.3 Бесплатно (free)

Все мы используем массивы в своем коде. Это один из первых объектов, который дают ученикам при прохождении обучения программированию. Но умеем ли мы ими пользоваться? В этой статье я хочу показать все методы массива, а также некоторые фишки в работе с массивами.

24.01.2024    5838    YA_418728146    25    

68

Планы обмена VS История данных

Обмен между базами 1C Механизмы платформы 1С Платформа 1С v8.3 Бесплатно (free)

Вы все еще регистрируете изменения только на Планах обмена и Регистрах сведений?

11.12.2023    6956    dsdred    36    

113

1С-ная магия

Механизмы платформы 1С Бесплатно (free)

Язык программирования 1С содержит много нюансов и особенностей, которые могут приводить к неожиданным для разработчика результатам. Сталкиваясь с ними, программист начинает лучше понимать логику платформы, а значит, быстрее выявлять ошибки и видеть потенциальные узкие места своего кода там, где позже можно было бы ещё долго медитировать с отладчиком в поисках источника проблемы. Мы рассмотрим разные примеры поведения кода 1С. Разберём результаты выполнения и ответим на вопросы «Почему?», «Как же так?» и «Зачем нам это знать?». 

06.10.2023    19041    SeiOkami    46    

118

Дефрагментация и реиндексация после перехода на платформу 8.3.22

Механизмы платформы 1С Платформа 1С v8.3 Бесплатно (free)

Начиная с версии платформы 8.3.22 1С снимает стандартные блокировки БД на уровне страниц. Делаем рабочий скрипт, как раньше.

14.09.2023    12747    human_new    27    

76

Валидация JSON через XDTO (включая массивы)

WEB-интеграция Универсальные функции Механизмы платформы 1С Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

При работе с интеграциями рано или поздно придется столкнуться с получением JSON файлов. И, конечно же, жизнь заставит проверять файлы перед тем, как записывать данные в БД.

28.08.2023    9373    YA_418728146    6    

143

Внешние компоненты Native API на языке Rust - Просто!

Механизмы платформы 1С Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Внешние компоненты для 1С можно разработывать очень просто, пользуясь всеми преимуществами языка Rust - от безопасности и кроссплатформенности до удобного менеджера библиотек.

20.08.2023    6521    sebekerga    54    

95

Все скопируем и вставим! (Буфер обмена в 1С 8.3.24)

Механизмы платформы 1С Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Рассмотрим новую возможность 8.3.24 и как её можно эффективно использовать

27.06.2023    16810    SeiOkami    31    

104
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. salexdv 2331 08.09.22 08:34 Сейчас в теме
Предлагаю не мелочиться, а сразу попросить у 1С фильтры для коллекций, чтобы делать что-то вроде такого

НоваяТаблица = Таблица.Фильтр((СтрокаТЧ) => СтрокаТЧ.Номер % 2 = 0)


И сортировку туда же

Таблица.Сортировать((Строка0, Строка1) => Строка0.Номер - Строка1.Номер)
deletel; brr; CodeNull; LimarenkoA; 7OH; kser87; Бубузяка; VladC#; Altez50; Поручик; Irwin; Sedaiko; kirabr; CyberCerber; cleaner_it; anosin; artbear; Windsor77; Shmell; Артано; SAShikutkin; +21
3. SAShikutkin 5 08.09.22 09:00 Сейчас в теме
(1)Аналог LINQ - действительно, было бы интересно)
+
11. tormozit 7140 08.09.22 09:26 Сейчас в теме
(1) Как их отлаживать? Если выражение достаточно сложное, то захочется пощупать его части для конкретной строки (например на которой возникла ошибка). Как это будет выглядеть?
DrAku1a; +1
12. Артано 762 08.09.22 09:29 Сейчас в теме
(11) Я думаю, что в скобках отдельная функция написанная в одну строку. Соответственно отладка будет в той самой функции. По крайней мере в других языках для переопределения условий сортировки/фильтрации пишется отдельная функция.
+
14. tormozit 7140 08.09.22 09:33 Сейчас в теме
(12) Если будет отдельная функция, то ОК. Технически нам и сейчас мешает ничто сделать такой механизм на прикладном уровне. Только придется делать явный цикл и вызов функции будет компилироваться при каждом его проходе, что несомненно внесет ощутимое замедление.
+
16. Артано 762 08.09.22 09:35 Сейчас в теме
(14) Поэтому граждане и просят, чтобы работало "искаропки". Тогда будет оптимизировано на уровне платформы. Хотя, полагаю, что сложный алгоритм сравнения не оптимизировать и придется применять функцию к каждому элементу.
+
58. ubnkfl 14.09.22 18:31 Сейчас в теме
(14)
мешает ничто

"Мешает ничто" - потому что вам не нравится двойное отрицание в русском языке? :)
+
59. tormozit 7140 14.09.22 22:41 Сейчас в теме
(58) Ты должен последовать моему примеру. Ведь ты и сам об этом задумывался и хотел попробовать. Что тебе мешает?
+
75. brr 182 05.12.23 16:24 Сейчас в теме
(14)Можно собрать текст цикла с вызовом функции и один раз "скомпилировать".
+
13. salexdv 2331 08.09.22 09:32 Сейчас в теме
(11) Это просто сокращенная запись такого

Функция ФильтрПоЧетным(СтрокаТЧ)

    Возврат СтрокаТЧ.Номер % 2 = 0;

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

Таблица.Фильтр(ФильтрПоЧетным);
+
21. DrAku1a 1715 08.09.22 09:51 Сейчас в теме
(1) Не в таком виде, а в виде функции, передаваемой как параметр - можно было бы.
Мне нравится рекомендация 1С писать понятный код, даже используя большее количество строк кода.

Т.е. вместо:
СтруктураДанных = новый Структура("Наименование, Представление, Вид, Модифиукатор", "Наименование", "Представление", ...

делать многострочное:
СтруктураДанных = новый Структура;
СтруктураДанных.Вставить("Наименование", "Наименование");
СтруктураДанных.Вставить("Представление", "Представление");
...

второй вариант - нагляднее.
cleaner_it; Артано; +2
25. salexdv 2331 08.09.22 09:56 Сейчас в теме
(21) Я с одной стороны согласен, а с другой нет. Конечно, если функция для фильтрации/сортировки сложная, то нет смысла записывать её в одну строку, но вот если она простая, как в моём примере, тогда это проще читается. Просто для нас, как для 1Сников это выглядит непривычно.
+
33. JohnyDeath 301 09.09.22 09:28 Сейчас в теме
(1) Можно еще вспомнить великолепную 1С++ для 7.7. Там есть очень крутой объект под названием ИндексированнаяТаблица, в которой можно удалять по Индексу с учетом наложенных на него фильтров. А еще у этого объект есть даже Левые и Правые соединения, разности, итоги по узлу и пр..
Вообще мощная вещь, как и весь 1С++
CheBurator; 7OH; salexdv; Артано; DrAku1a; +5
48. VladC# 64 12.09.22 08:55 Сейчас в теме
(1) Очень напминает лямбды из java, если бы что-то подобное появилось в 1с, то это был бы огромный шаг вперёд, но у 1с своё видение того что нужно, так что даже мечтать не стоит о таком.
+
65. Evil Beaver 8117 30.09.22 12:05 Сейчас в теме
(1) Предлагаю не ждать милостей от судьбы, а портировать на 1С библиотеку fluent от 1Script https://github.com/oscript-library/fluent
alei1180; salexdv; +2
72. tormozit 7140 24.06.23 16:32 Сейчас в теме
(1) Попробовал слепить функцию фильтрации коллекции из того что имеем https://infostart.ru/1c/articles/1887014/
It-developer; salexdv; +2
2. ixijixi 1796 08.09.22 08:50 Сейчас в теме
Как бы решалась эта задача, если бы у нас был обратный цикл?

Я возможно невнимательно читал, но в чем проблема? Обратный цикл в 1С есть и отлично работает
Для Сч = 1 - ТаблицаЗначений.Количество() По 0 Цикл
	ТаблицаЗначений.Удалить(ТаблицаЗначений.Получить(-Сч));
	// или
	ТаблицаЗначений.Удалить(-Сч);
КонецЦикла;
ketr; sivin-alexey; user811769; Revachol; user1792010; Sergey_Borisovi4; akR00b; Lobion; NiGMa; Yashazz; smit1c; Irwin; SerVer1C; insurgut; paybaseme; kuzev; CyberCerber; cleaner_it; mikl79; 0x00; 7o2uYXg; user1559729; tormozit; +23
7. Артано 762 08.09.22 09:12 Сейчас в теме
(2) Если поведение платформы не меняли, то такой цикл не выполнит ни одной итерации.

По сабжу автора - данный вопрос удобно решается обратным циклом, но сам пример может быть решен более оптимально (с точки зрения производительности) без поитерационного удаления строк. Я имею ввиду метод Скопировать().
9. tormozit 7140 08.09.22 09:17 Сейчас в теме
(7) Цикл рабочий. Я тоже его использую. Читай документацию.
Артано; +1
10. Артано 762 08.09.22 09:21 Сейчас в теме
(9) Не разглядел два костыля в алгоритме. Согласен, рабочий. Но не очевидный. Документация тут вообще не причем, это просто своеобразный алгоритм, который будет примерно одинаковым на любом языке
+
8. tormozit 7140 08.09.22 09:15 Сейчас в теме
(2) У меня даже шаблон есть такой
Для Индекс = 1 - <?"Коллекция">.Количество() По 0 Цикл // Обратный обход
	<?"Элемент коллекции"> = <?"Коллекция">[-Индекс];
	Если <?> Тогда
		<?"Коллекция">.Удалить(<?"Элемент коллекции">);
	КонецЕсли;
КонецЦикла;
It-developer; ketr; Serg2000mr; СергейК; Yashazz; Cmapnep; fancy; simgo83; Windsor77; MVK80; DrAku1a; zqzq; +12
35. Cmapnep 18 09.09.22 09:50 Сейчас в теме
(8)
Для Индекс = 1 - .Количество() По 0 Цикл // Обратный обход
= [-Индекс];
Если Тогда
.Удалить();
КонецЕсли;
КонецЦикла;


А можешь поделиться своим файлом шаблонов - уверен там еще много интересного и полезного найдется
+
15. DrAku1a 1715 08.09.22 09:33 Сейчас в теме
(2) Невнимательно. См. в конце: "5. Эмуляция обратного цикла с помощью цикла "Для""
+
17. ixijixi 1796 08.09.22 09:36 Сейчас в теме
(15) В чем тогда суть статьи "Не хватает обратного цикла", если обратный цикл есть?
CodeNull; Yashazz; 0x00; +3
20. Артано 762 08.09.22 09:45 Сейчас в теме
(17) Его нет, но его можно эмулировать. Такая эмуляция на мой взгляд есть хардкод. Нативно отрицательный шаг счетчика невозможен
Fox-trot; unknown181538; Windsor77; DrAku1a; +4
22. DrAku1a 1715 08.09.22 09:52 Сейчас в теме
(20) Да. Именно про это статья.
+
49. ixijixi 1796 12.09.22 10:34 Сейчас в теме
(20) Что такое нативно отрицательный шаг счетчика?
+
50. Артано 762 12.09.22 10:39 Сейчас в теме
(49) Здесь могла быть запятая, но переводится как: "искаропки в 1с нет отрицательного шага счетчика".
+
51. ixijixi 1796 12.09.22 10:40 Сейчас в теме
(50) Может тогда для примера - где он есть искаропки? Я хоть сравню)
+
52. Артано 762 12.09.22 10:46 Сейчас в теме
(51) Си и потомки (через декремент) , Паскаль/Делфи, Бейсик и потомки. Множество их.
Питон еще вспомнил. В общем, масса примеров - щупайте =)
+
53. ixijixi 1796 12.09.22 11:28 Сейчас в теме
(52) Бегло загуглил. Дошло, спасибо)
+
28. unknown181538 152 08.09.22 18:13 Сейчас в теме
(2) Вариант лаконичны и рабочий, но менее читаемый. Обратный цикл был более прозрачным.
+
4. quazare 3602 08.09.22 09:08 Сейчас в теме
Используйте функцию "РазложитьСтрокуВМассивПодстрок" - так будет "по-книжному"
+
18. DrAku1a 1715 08.09.22 09:38 Сейчас в теме
(4) СтрРазделить() - уже полноценная функция платформы (начиная с версии 8.3.6). До этого были только возможности БСП.
Yashazz; paybaseme; quazare; +3
29. AntonProgma 46 08.09.22 22:59 Сейчас в теме
(18) главное - помнить о её ковартстве и не рассчитывать на многосимвольный разделитель
ixijixi; DrAku1a; Поручик; +3
31. quazare 3602 09.09.22 06:17 Сейчас в теме
(18) вы правы! вообще материал хороший у вас - эдакая гимнастика для извилин.
+
5. MikhailDr 08.09.22 09:09 Сейчас в теме
Постоянно перебираю таблицы через Сч = Сч - 1; Проблемы не вижу, может я чего-то не понимаю?
+
19. DrAku1a 1715 08.09.22 09:45 Сейчас в теме
(5) Во-первых, это не так наглядно и интуитивно понятно, как цикл "Для".
Во-вторых, стоит один раз забыть написать эту самую "Сч = Сч - 1" и запустить код на исполнение... и Вы увидите, что проблема имеет место (или, если не делаете "Сч = Сч - 1" в самом начале цикла "Пока" и в цикле по какому-либо условию будет "Продолжить" - можно, также, получить зацикливание).
+
23. MikhailDr 08.09.22 09:53 Сейчас в теме
(19)
Во-вторых, стоит один раз забыть написать эту самую "Сч = Сч - 1"


Если так рассуждать, то надо от цикла "Пока" отказываться. Ведь там тоже можно вызвать зацикливание, это такой себе довод.

Что до интуитивности то конкретно здесь это вопрос опыта и привычки, для меня это абсолютно интуитивная конструкция.

Я в целом не имею ничего против обратных циклов, это небольшой синтаксический сахар. Но он очень небольшой, есть задачи гораздо более приоритетные в рамках развития платформы.
+
26. DrAku1a 1715 08.09.22 10:36 Сейчас в теме
(23)
Если так рассуждать, то надо от цикла "Пока" отказываться.
Цикл "Пока" хорошо подходит для обработки выборок (Пока Выборка.Следующий() Цикл).
+
60. DrAku1a 1715 19.09.22 08:53 Сейчас в теме
(23)
есть задачи гораздо более приоритетные в рамках развития платформы
можете озвучить?
в первую очередь интересует то, что касается языка 1С. Но и платформенные недоработки, и прочее - тоже интересно.
Как сказано в заголовке, я планирую цикл статей таких написать. Но, если это будет нечто большее, чем ИМХО - думаю, будет интереснее.

Например, я хочу разобрать пару типовых конфигураций и посмотреть почему они такие здоровые. Можно ли их сделать "легче" и что это даст.
dvsidelnikov; +1
61. MikhailDr 19.09.22 09:17 Сейчас в теме
(60) Тут конечно надо хорошо подумать, но навскидку я бы назвал пару вещей

1. Доработка механизма расширений. Тут много всего, в идеале расширения должны полностью повторять весь функционал основной конфигурации. Как пример - добавить тип "ЛюбаяСсылка"

2. Доработка контекстной подсказки в конфигураторе. Например создав таблицу в процедуре вам будет доступна контекстная подсказка только в рамках этой процедуры. Но если передать таблицу в другую процедуру, то там уже подсказка недоступна.
+
62. DrAku1a 1715 19.09.22 10:52 Сейчас в теме
(61) Тип "ЛюбаяСсылка" уже добавлен, но нужен режим совместимости 8.3.20 и выше. Проблема в том, что текущий режим совместимости типовых конфигураций 8.3.17-8.3.18, и с учетом того, как быстро поднимают этот режим - до использования его, например, с УТ 11 или БП 3, ожидать нужно ещё где-то 2 года.

Механизм расширений ещё сырой и активно развивается. Как и всем нововведения 1С, нужно время на адаптацию.

Из моих пожеланий к нему я бы выделил "возможность видеть другие расширения" - т.е. иерархию расширений (механизм "расширение на расширение"), или директиву "использует" с указанием других расширений и их версий и заимствования объектов из других расширений.

По проводу (2), есть мысль что сказать. Тут несколько сложнее ситуация, и связана она с отсутствием типизации параметров (процедур и функций). Это с одной стороны удобно.
+
6. Evg-Lylyk 4614 08.09.22 09:11 Сейчас в теме
(0) По описанному примеру: ИМХО вариант с массивом простой и понятный. Жаль что Удалить() не работает с массивом.
unknown181538; +1
24. SerVer1C 750 08.09.22 09:53 Сейчас в теме
Требуем ООП , LINQ, дженерики и лямбды !!! Ну хотя бы инкремент чтобы завезли (причем в байт-коде он присутствует отдельным оп-кодом).
+
27. triviumfan 93 08.09.22 12:53 Сейчас в теме
Хоть тема и простая, но было интересно) спасибо
+
30. Pavel_Vladivostok 58 09.09.22 05:52 Сейчас в теме
Если таблица объемная, я бы предпочел выбрать не удаляемые строки запросом и скопировать исходную таблицу указав массив правильных строк, избегая при этом циклы вообще.
gybson; +1
32. Артано 762 09.09.22 08:20 Сейчас в теме
(30) Угу. Писал об этом в (7)
+
34. JohnyDeath 301 09.09.22 09:45 Сейчас в теме
Еще вариант:
тз = Новый ТаблицаЗначений;
//.... наполнение тз ....
имяСлужебнойКолонки = "_Удалить_";
тз.Колонки.Добавить(имяСлужебнойКолонки, Новый ОписаниеТипов("Булево"));
Для Каждого строкаТЗ Из тз Цикл
	строкаТЗ._Удалить_ = (строкаТЗ.Номер % 2 = 0);	
КонецЦикла;
отбор = Новый Структура(имяСлужебнойКолонки, Ложь);
тз = тз.Скопировать(отбор);
тз.Колонки.Удалить(имяСлужебнойКолонки);
Показать
+
36. DrAku1a 1715 09.09.22 10:05 Сейчас в теме
(34) А чего мелочиться, давайте сделаем копию таблицы через ТЗ.ВыгрузитьКолонки() и заполним её строками с нечетными числами? (Это, мягко говоря, неоптимально).
+
38. JohnyDeath 301 09.09.22 10:16 Сейчас в теме
(36) возможно такой вариант будет даже более производительный, чем все вышеперечисленные.
Но надо, конечно же, проверять
+
39. DrAku1a 1715 09.09.22 10:31 Сейчас в теме
(38) Насколько я понимаю работу менеджеров памяти, выделять память под новые объекты им несколько сложнее и дольше, чем освобождать (по факту, при работе кода память не освобождается, а просто помечается неиспользуемой). При создании новой колонки, новой таблицы, нового массива - нужно ещё найти место где разместить эти объекты. Но, можно проверить, в этом плане 1С может удивить.
+
37. JohnyDeath 301 09.09.22 10:13 Сейчас в теме
А вообще нет с классическим "GoTo" во втором варианте
сч = 0;
Пока сч<ТЗ.Количество() Цикл
~Перепроверка:
	Если ТЗ[сч].Номер % 2 = 0 Тогда
		ТЗ.Удалить(сч);
		Перейти ~Перепроверка;
	КонецЕсли;
	сч = сч + 1;
КонецЦикла;
Показать
lunjio; +1
40. DrAku1a 1715 09.09.22 10:35 Сейчас в теме
(37) Оператор goto в языках высокого уровня является объектом критики, поскольку чрезмерное его применение приводит к созданию нечитаемого «спагетти-кода» (источник: статья на Википедии). Поэтому, варианты с безусловным переходом мною даже не рассматривались.
maksa2005; +1
41. JohnyDeath 301 09.09.22 10:40 Сейчас в теме
(40) и что здесь черезмерного? По-моему этот код намного проще читается, чем большинство описанных.
Да, goto нежелателен. Но все-таки действовать надо по ситуациям, а не по рекомендациям википедии и ИТС
Хотя этот вариант будет скорее всего самый долгий
brr; lunjio; Артано; +3
42. DrAku1a 1715 09.09.22 11:06 Сейчас в теме
(41) Видимо, неправильно пояснил. Для меня уже за правило стало - не использовать операторы безусловного перехода. Именно из-за критики. Когда-то давно преподаватель информатики озвучил такое мнение: "Квалификация программиста обратно-пропорциональна использованию им оператора безусловного перехода" (это неточная цитата). Написать любой алгоритм возможно без GoTo.
Вот, нашел материал по теме: https://studfile.net/preview/1444532/page:12/
Fox-trot; +1
43. JohnyDeath 301 09.09.22 11:09 Сейчас в теме
(42) ровно как и написать любой алгоритм без обратных циклов )
Артано; +1
44. DrAku1a 1715 09.09.22 11:11 Сейчас в теме
(43) вот только критики обратных циклов не находил ))
Fox-trot; +1
45. Артано 762 09.09.22 11:46 Сейчас в теме
(42) Согласен с Джонни. Если код станет нагляднее и лаконичнее с GOTO, то не вижу оснований фанатично его отрицать. Тот же Дейкстра, считающийся ненавистником безусловных переходов, допускал их ограниченное использование.
brr; +1
67. CheBurator 3119 31.10.22 22:54 Сейчас в теме
(42)
"Квалификация программиста обратно-пропорциональна использованию им оператора безусловного перехода"

этот ваш "перпедователь" видно никогда на ассемблере не программировал. там готу - в порядке вещей, типа
BR 14 - переход по адресу, содержащемуся в 14 регистре...
+
68. DrAku1a 1715 02.11.22 05:56 Сейчас в теме
(67) На то он и ассемблер. Язык низкого уровня, максимально близкий непосредственно к машинному коду.
Речь о языках более высокого уровня, гораздо более абстрактных, не претендующих на максимально быстрый код (хотя и стремящихся к этому), минимальные размеры самого приложения и оптимальности использования памяти в переменных.
+
76. brr 182 05.12.23 16:28 Сейчас в теме
(42)Так себе авторитет.
+
47. Art39_ 12.09.22 00:26 Сейчас в теме
5 вариант интересный, возьму на вооружение, жаль раньше не встречал.
+
46. PerlAmutor 129 09.09.22 17:52 Сейчас в теме
Использую 5-ый вариант цикла наверное уже как год, по поводу и без повода. Однажды увидел в типовой, понравилось.
+
54. Arxxximed 34 12.09.22 19:17 Сейчас в теме
По моему в 1С ооочень много чего не хватает, и приходится эмулировать. Синтаксический сахар для разработчиков 1С это зло )).
За удобствами вам не в 1С.
За удобствами вам в Python
+
55. DrAku1a 1715 13.09.22 03:41 Сейчас в теме
(54) В языке программирование - возможно. Хотя, по мне, синтаксис "вот тут отступ - это значит блок ("для", "если")" - ну, такое... Я не хочу сказать, что 1С лучше чем Python, ровно как и обратное. Свои достоинства и недостатки есть в каждом языке и в каждой среде.
Платформа 1С - это не только и не столько язык программирования. Это скорее - конструктор (конфигуратор), внутри которого много конструкторов поменьше (запросов, форматной строки, печатных форм и т.п.). Язык же - инструмент, который помогает работать созданным в конструкторах механизмам.
Прикрепленные файлы:
ubnkfl; +1
57. Arxxximed 34 14.09.22 12:07 Сейчас в теме
(55) Да, отступы или скобки - на вкус и цвет, мне отступы вполне зашли. Но по сравнению с Цикл КонецЦикла, Если КонецЕсли, КонецФункции... Уж лучше VBAшное END. Меньше писанины. И один черт отступы то есть во всех языках при форматировании )))))

Но суть не про это, а про синтаксический сахар Ну извините стандартное , идущее с незапамятных времен
переменная += 1;
могли бы уже добавить.

Про платформу - Вы правы, но речь идет именно же про язык. Автору не понравилось что нету обратного Цикла
Мне же не нравится что например питоновское СтрТекст[2:-2] приходится писать в Сред(СтрТекст, 2 , СтрДлина(СтрТекст-4)). Долго писать непонятно читать.
+
56. Артано 762 14.09.22 05:51 Сейчас в теме
(54) Примерно то же самое говорили разработчики на 7.7 когда появилась восьмёрка. Я например, игнорировал 1с, пока не вышла 8.2. Только после этого пошел в 1с "на полный штат".
+
63. pm74 199 25.09.22 19:56 Сейчас в теме
внимательно не вчитывался , не заметил такого варианта

Для _сч = (ТЗ.Количество()-1)*-1  По 0 Цикл 
       сч = -_сч;
...
+
64. DrAku1a 1715 26.09.22 07:49 Сейчас в теме
(63) см.
5. Эмуляция обратного цикла с помощью цикла "Для"
pm74; +1
66. Heinz 12.10.22 16:28 Сейчас в теме
(1)Т.е. вы сразу и лямбды попросили, а заодно и функции первого класса.
+
69. heroy 25.11.22 12:07 Сейчас в теме
(66) Замыкания это удобно, открывает путь в новый мир, а по сути это всего лишь синтаксический сахар для шаблона функтор, да, еще нужно 2 шага сделать, анонимные функции и в конце концов лябды, но это все еще сахар
+
70. PerlAmutor 129 29.05.23 06:49 Сейчас в теме
Еще такой вариант встречается часто:

		Количество = Коллекция.Количество();
		Для Номер = 1 По Количество Цикл
			ОбратныйИндекс = Количество - Номер;
			Коллекция.Удалить(ОбратныйИндекс);
		КонецЦикла;
DrAku1a; +1
71. DrAku1a 1715 29.05.23 12:37 Сейчас в теме
(70) Да, и в типовых тоже встречается. Добавлю.
+
73. user1707144 26.10.23 10:50 Сейчас в теме
	Массив = Новый Массив;
	Массив.Добавить("Красный");
	Массив.Добавить("Жёлтый");
	Массив.Добавить("Зелёный");
	
	Индекс = Массив.ВГраница();
	Пока Индекс >= 0 Цикл
		
		Сообщить(Массив[Индекс]);
		Индекс = Индекс - 1;
		
	КонецЦикла;
Показать
+
74. DrAku1a 1715 27.10.23 06:01 Сейчас в теме
(73) см "Попробуем реализовать это через цикл "Пока""
Если индекс уменьшать в конце цикла, то существует шанс получить зацикливание - если тело цикла будет большим (или станет большим со временем), и в теле цикла будет по какому-то условию использоваться "Продолжить":
    Массив = Новый Массив;
    Массив.Добавить("Красный");
    Массив.Добавить("Жёлтый");
    Массив.Добавить("Зелёный");
    
    Индекс = Массив.ВГраница();
    Пока Индекс >= 0 Цикл
        //код
        //код
        //код
        //код
        //код
        //код
        //код
        //код
        //код
        //код

        Если (КакоеТоУсловиеИстинно) Тогда
                Продолжить;
        КонецЕсли;


        //код
        //код
        //код
        //код
        //код
        //код
        //код
        //код
        //код
        //код
        //код
        //код

        Индекс = Индекс - 1;
        
    КонецЦикла;

Показать
+
Оставьте свое сообщение