1с оператор возврат return не может употребляться вне процедуры или функции
Исполняемые операторы выполняют непосредственную обработку данных. К ним относят системные процедуры и функции, заложенные разработчиками платформы, а также вспомогательные процедуры и функции, описанные разработчиком конфигурации (прикладной задачи).
Под описание системных процедур и функций отведен целый раздел. Здесь же мне хотелось бы рассказать о вспомогательных исполняемых операторах, которые может определять разработчик конфигурации. Основное назначение вспомогательных исполняемых операторов — повторное многократное использование кода и оптимизация модульной структуры конфигурации.
Во встроенном языке 1С:Предприятие 7.7 определены два варианта реализации вспомогательных вычислений:
- Реализация вычислений через процедуры, не возвращающие каких-либо значений;
- Реализация вычислений через функции, возвращающие результат вычислений в точку вызова;
По сути, процедуры и функции представляют собой блоки операторов, заключенные в специальные операторные скобки:
Для вызова оператора достаточно указать его символьный идентификатор:
Поскольку, встроенный язык 1С:Предприятие 7.7 является регистронезависимым, идентификатор оператора можно писать в любом регистре. Но лучше использовать оригинальные имена операторов — это повысит читаемость кода не только для Вас, но и для Ваших последователей.
Программист может располагать процедуры и функции в любом модуле на свое усмотрение. Но хорошим тоном считается расположение общеиспользуемых процедур и функций в глобальном модуле, чтобы в остальных модулях была доступна только одна версия этой процедуры или функции. Все остальные процедуры и функции принято располагать по месту их использования — в программных модулях форм или объектов конфигурации.
Параметры исполняемых операторов
Поскольку процедуры и функции, определяемые разработчиком, могут располагаться в произвольных модулях конфигурации, для передачи данных в исполняемые операторы используются параметры. Для этого в определении процедуры или функции задаются формальные параметры, которыми можно оперировать внутри процедуры или функции:
В качестве параметров могут выступать литералы базовых типов, имена переменных, имена других исполняемых операторов или выражения с их участием.
По-умолчанию, все формальные параметры исполняемого оператора являются обязательными. Это значит, что в вызове процедуры или функции необходимо заменить каждый формальный параметр на фактический.
Если вы перечислите не все фактический параметры, синтаксический анализатор выдаст ошибку: «Недостаточно фактических параметров» .
Необязательные (опциональные) параметры
Несмотря на то, что все формальные параметры являются обязательными, допускается не указывать их значения. В этом случае формальный параметр получит пустое значение (значение неопределенного типа).
Также имеется возможность задать для формального параметра значение по умолчанию одного из простых типов. Для этого в определении параметра, после знака присваивания, указывается литерал значения:
Передача параметров по значению. Передача параметров по ссылке
По-умолчанию, значения всех фактических параметров передаются в процедуру или функцию по ссылке. Это приводит к тому, что изменение формального параметра в теле процедуры или функции, также изменяет значение фактического параметра. Чтобы избежать этого, используется передача параметров по значению. Таким образом, изменение формального параметра не повлечет за собой изменения фактического. Для этого к описанию параметра добавляется ключевое слово Знач :
Предварительное объявление процедур и функций
При этом следует учесть, что предварительное описание должно включать все параметры исходных процедур и функций, включая ключевые слова Знач и Экспорт
Досрочное завершение исполняемого оператора
Для досрочного завершения выполнения операторов в теле процедуры или функции используется оператор Возврат , который передает управление на первый оператор, следующий за процедурой или функцией.
(8) > Вообще, считаю, идеологически правильнее не изменять формальные параметры функцией. Функция в математическом смысле однонаправлена. И у неё четко разделены вход и выход.
Простой пример: код модуля стал очень сложным, хочется раскидать разные части по отдельным функциям.
Вырезаешь куски в отдельные функции, запускаешь проверку синтаксиса смотришь каких переменных не хваттае и тупо кидаешь их в параметры.
(7) Ну вот пример - функция должна вернуть несколько значений, которые потом будут использовать как фильтрующие параметры. Можно вернуть список значений, а можно передать менеджер и сделать временную таблицу
(11) В целом да, но я бы не стал это возводить в абсолют.
(15) В рамках модуля объекта еще туда-сюда.
Более глобальные - не стоит, имхо.
Возврат какого-нибудь списка значений тоже не ахти вариант. Сложней в разборе результата функции. Нет подсказки по возвращаемому значению. Легко перепутать "имена" возвращаемых значений. Было бы понятие типа "структуры" - вопросов бы не возникало.
(18) 1. Это кто с 7.7 не работал в которых структур не было.
2. Обращаться можно по [0],[1]
(19) И что, через полгодика вы вспомните, что функция возвращает в [0]? А тем более, если кто-то другой читать код будет. Варианты типа [0] крайне не рекомендуются во всех приличных местах/языках. Варианты типа ["НомерСтелажа"] тоже, слишком велика вероятность опечатки.
(22) Где написано? В коде вы видите что-то типа:
Ну и как этот код читать? За такое в приличных местах уволить нафиг могут.
Идеологически правильнее наверное структурой, но параметрами так удобно))
(21) Список значений с представлениями позволяет обращаться по имени представления. По сути имитация структуры, которой в семерке нет.
(23) 7.7 - Парам.Получить("Количество")*Парам.Получить("Цена").. как-то так.
(25) (26) Ага-ага. А когда-нибудь потом, через полгодика, вы узнаете, что в каком-то нечасто выполняющемся куске кода вместо "Количество" вы написали "Клоичество". И хорошо еще если эта ошибка будет быстро замечена, а не приведёт к постоянным косякам за большой период.
По моему, функции, изменяющие свои параметры, это плохо, но возврат списка или структуры - еще хуже.
Если бы в языке был соответствующий тип вроде сишного union - тогда метод возврата структуры был бы хорош.
(27) а чем структура плоха? опечатка приведет к исключению
По частоте использования:
1. Структура, например, если нужно получить что-то связанное с объектом (периодические значения), но получать сам объект не имеет смысла.
2. Функция с параметром, определяющим значение чего будет возвращено.
3. Несколько функций.
(28) Исключение в данном случае благо. Может привести к неверной работе алгоритма, без ошибок времени выплонения.
winapi стаил. Функция возвращает истина/ложь (удачно/не удачно). А в параметры кладем значения возврата. В 1с аналог свойство() для структуры.
2. Возврат одного значения и изменение параметров Если структура не класс (семантически), лучше разбить ф-ию.
(33)ни о чём не говорит типовые сейчас достаточно странные люди пишут.
(32) не получиться разбить в связанных значениях
например возвращается также ТекстОшибки
(28) Структура плоха тем что:
1. Нельзя использовать автодополнение, выше вероятность опечатки
2. Что бы при чтении кода понять, какие параметры могут возвращаться, приходится переходить к определению функции и читать комментарии к ней. Если они еще есть.
3. На опечатки нельзя проверить формально, надеемся на то, что упомянутое вами исключение выскочит при тестировании у разработчика, а не повалит у пользователей в том куске, который разработчик недостаточно протестировал.
3.1. А бывают еще любители избыточного использование Попытка Исключение. Получается вообще взрывоопасная смесь.
4. При рефакторинге могут возникнуть большие проблемы по переделке кучи мест в коде. Не решаемые полуинтеллектуальным поиском с заменой и прочими подобными инструментами.
. можно еще продолжать про недостатки, но юзверя звонят.
Если нужно вернуть все перестановки какого -либо множества, то лучше сделать так, чтобы следующая перестановка возвращалась на основании предыдущей без изменения каких либо параметров.
Если нужно вернуть линейный размеры объект - тогда лучше структура (а еще лучше - сам объект)
А если нужно вернуть сто случайных значений от 0 до 1, то лучше всего возвращать массив.
Т.е. что лучше зависит от контекста вопроса больше, чем от самого вопроса.
Если функции надо вернуть несколько РАЗНЫХ значений, не объединенных семантически в какое-то целое, значит у тебя косяк в архитектуре и это две функции, а не одна.
А, если эти значения - это атрибуты какого-то одного объекта, то возвращай структуру да и всё.
(38)
> 1. Нельзя использовать автодополнение, выше вероятность опечатки
Автодополнение в 1с много где нет? это вопрос тестирования
> 2. Что бы при чтении кода понять, какие параметры могут возвращаться, приходится переходить к определению функции и читать комментарии к ней. Если они еще есть.
Для этого можно в начале функции инициировать структуру, которая нужно вернуть независимо от успешности функции
> 3. На опечатки нельзя проверить формально, надеемся на то, что упомянутое вами исключение выскочит при тестировании у разработчика, а не повалит у пользователей в том куске, который разработчик недостаточно протестировал.
Это совсем другой вопрос - вопрос тестирования.
> 3.1. А бывают еще любители избыточного использование Попытка Исключение. Получается вообще взрывоопасная смесь.
> 4. При рефакторинге могут возникнуть большие проблемы по переделке кучи мест в коде. Не решаемые полуинтеллектуальным поиском с заменой и прочими подобными инструментами.
Например какие проблемы?
функция возвращает ссылку на объект
если вернуть ссылку не получилось, то также нужно вернуть текст ошибки
(47) При данном примере оптимальнее всего возвращать сылку отдельным параметром, а ошибку - результатом функции. (если ошибка пустая - значит параметр содержит ссылку)
От ситуации зависит. п.1 будет следующим по убыванию
Функция должна возвращать одно значение. Если даже это структура.
(48) А возвращать в параметрах ещё отстойней.
(52) Кратко пересказать книжки М.Фаулера и Р.Мартина ?
(47) Если функция не нашла значение потому что его нет - возвращается пустое значение, если возникла ошибка из-за неверных параметров, функция должна генерить исключение. Как это исключение будет обрабатывать вызывающая сторона - уже пофиг. Если вызывающая сторона подходит ответственно к параметрам вызова функции, она не должна париться над текстом в принципе.
(54) Там много опирается на то, что функция должна делать что-то одно. А если функция должна делать что-то одно, откуда взяться чему-то второму что можно вернуть?
(53) не нужно пересказывать, просто аргументируйте своими словами
(58) См(55). Если не убедил - просто посмотри как работает типовая Справочник.XXX.НайтиПоКоду() и аналогичные. Ни одна функция в здравом уме не возвращает текст ошибки и т.п.
(59) а если речь идет о взаимодействии между системами?
1с - драйвер оборудования
1с - 1с по веб-сервсису
и т.п.
Чаще всего использую возврат структуры, но бывает, что в параметрах возвращал значение, а сама функция возвращала статус успешное завершения функции.
(61) Тогда Попытка + ВызватьИсключение особенно часто используются.
В общем случае, возврат нескольких значений - это массив, соответственно, структура, список и т.п. это более упрощённое понимание массива.
Но, реального возврата нескольких значений из функции всё равно нет - вы возвращаете один объект. И, самое главное, что он создаётся, а потом разрушается, что медленнее, чем если передавать эти несколько параметров в функцию или процедуру по ссылке.
Удобство структуры и списка значений в том, что можно указывать имена значений, что не требует следить за их порядком.
Передача же параметров в вызов функции по значению проще для читателя, так как он понимает, что будет возвращено и может не подставлять переменные для тех значений, которые ему не нужны.
Структура/Неопределено.
Т.к считать параметры в каждом вызове - напрягает.
при желании и процедурой можно значения возвращать ))) (вернее получать в переменную)
(8) Математически операция А = А + 1 недопустима. Так что не стоит математику переносить на программирование.
(10) В Си процедур не бывает. Только функции с возвратом типа void. Так что и мешанины быть просто не может.
(27) Ну создавай структуру с нужными строками в общем модуле отдельной функцией. Тогда очепятка или будет везде, или нигде.
Вставлю своё имхо:
Когда нужно передавать по ссылке и там менять:
1. Когда меняешь движения, дописываешь данные в таблицу, список.
2. Когда у тебя есть большая структура, которая содержит несколько параметров, которые ты будешь использовать и тебе нужно дополнить её.
3. Когда передаёшь "Отказ" и там меняешь его на Ложь.
4. Когда передаёшь форму и добавляешь на неё свои элементы.
5. Когда передаёшь МенеджерВременных таблиц.
Это то, что смог вспомнить.
Во всех остальных случаях нужно возвращать.
(76) это ты описываешь, больше процедуры чем функции, по логике
(72) Я знаю. Именно это и создает мешанину в мозгах, когда сишник садится писать на более структурированных языках. У него уже в прошивке отложилось что функция может и должна менять параметры.
(79) В Си как раз все замечательно. Объявил параметр const - значит менять нельзя. Не объявил - значит он может быть изменен. Потому что с учетом требований с скорости работы может потребоваться и результат вернуть, и параметры поменять.
(79) (80) В Си как раз всё просто - если параметр передан по значению (засунут в стек), то в функции будет его копия, а если по указателю, то в функции будет указатель на переменную, которую по указателю можно менять.
А вот в Си++ появились ссылки, когда передаётся как бы значение, но внутри это реализовано как указатель - то есть то, что мы имеем в 1С, если не написали Знач.
И не забываем, что написав Знач, мы получим копию строки - и, если она очень длинная, то можно получить существенное замедление работы.
(83) Дык а если надо и параметры изменить, и значение вернуть? Что использовать? А если надо вернуть значение, параметры не менять, но поменять не параметры (например, добавить записи в базу)? Деление на процедуры и функции чисто условное, иначе сам ЯП не давал бы менять параметры в функции.
но мне кажется структура отбирает больше памяти, чем просто переменные.
А лучше бы не давал. С точки зрения парадигмы функционального программирования изменение формальных параметров - жуткая ересь)
(88) А ты с многопоточным программированием и реентрантностью работал? Когда один и тот же код и одни и те же переменные могут использоваться одновременно несколькими потоками? И тогда единственный способ не конфликтовать потокам - это передавать указатель на некую структуру со всем контекстом потока в качестве параметра функции? И, соответственно, параметр там в процессе работы меняется.
(89) А с распределёнными вычислениями?
Процедуре передавать аргументы по ссылке можно.
В Джаве например вообще нельзя передаваемые параметры менять, только возвращать
(90) В том-то и дело, что как только начинается реальная жизнь - вся академичность летит к чертям. Так зачем все усложнять? В процедуре априори должен выполняться код, который не может сгенерировать ошибку (возврат результата через перереданные параметры - это же неакадемично, для возврата результата предназначена функция). Много такого кода в реальных задачах?
(91) Это помогло ей завоевать звание тормозящей и памятежрущей.
(91) Но, в той же java прекрасно как параметры передаются объекты-контейнеры (BOX) в которых можно менять содержимое, не меняя самого контейнера, то есть так они реализовали указатели.
Что касается передачи параметра в функцию по указателю, то в том же Си всё остаётся на уровне функции - указатель, как бы мы его не меняли, обратно не возвращается, то если является обычным входным параметром, а вот про то, на что он указывает, никто не говорил - его можно менять, получая доступ к ячейке памяти по указателю.
(88) Начнём с того, что во многих языках деление на процедуры и функции чисто условно, так как и те и другие могут иметь как выходные так и выходные параметры.
Просто у функции есть основной параметр, который только выходной.
А если смотреть на низком уровне, то все высокоуровневые процедуры и функции - это вызов кода, возвращающего код ошибки исполнения, а все параметры и результаты хранятся в отдельной области памяти.
(93) Там просто сборка мусора работает тогда, когда памяти стало очень мало - в результате - если память есть, то её будут жрать, пока не надоест. Но, есть ключи запуска, где всё это можно ограничить. И ваша java побыстрее 1С будет.
1. Часть 2, Глава 5, Универсальный отчет
Установим курсор в верхнюю левую ячейку поля табличного документа и выполним Таблица 4 Встроенные таблицы 4 Вставить сводную таблицу. Система добавит в табличное поле сводную таблицу и откроет окно полей сводной таблицы (рис. 5.65).
Для того чтобы в сводную таблицу вывести данные, нам потребуется написать несколько строк в модуле формы. Откроем модуль формы отчета и добавим в текст переменную, которая нам понадобится (листинг 5.17).
Листинг 5.17. Объявление переменной
После этого создадим обработчик события формы отчета При открытии и добавим в него следующий текст (листинг 5.18):
Листинг 5.18. Обработчик события формы отчета При открытии
Этим текстом мы устанавливаем сводной таблице в качестве источника данных схему компоновки данных и устанавливаем ей настройки компоновщика настроек.
Запустим 1С:Предприятие в режиме отладки и откроем отчет Универсальный. На экране появится форма отчета и окно выбора полей сводной таблицы (рис. 5.66).
Делаю всё так, но у меня в окошке Поля сводной таблицы ничего нету.
2. Часть 2, Глава 5, Универсальный отчет 2
На примере создания второго универсального отчета мы рассмотрим способы непосредственного управления настройками системы компоновки и возможность формирования макетов на основе вариантов стандартного оформления.
Для более легкого понимания мы будем использовать практически тот же самый запрос по регистру накопления Продажи. Таким образом, можно сказать, что в этом отчете мы просто покажем другой вариант управления настройками системы компоновки.
Создадим новый объект конфигурации Отчет с именем Универсальный2. Откроем его основную схему компоновки данных, создадим новый набор данных – запрос и запустим конструктор запроса. Выберем все поля из виртуальной таблицы регистра накопления Продажи.Обороты и нажмем OK. На закладке Ресурсы конструктора схемы компоновки данных нажмем >> и убедимся, что система подобрала три ресурса: ВыручкаОборот, КоличествоОборот и СтоимостьОборот.
На закладке Настройки создадим новую группировку Детальные записи (не выбирая поле группировки).
Теперь на закладке Формы окна редактирования отчета Универсальный2 с помощью конструктора создадим основную форму отчета и отредактируем ее.
Растянем форму и расположим в ней две надписи с именами Поля и Порядок и с заголовками Поля: и Порядок: соответственно (рис. 5.69).
Под каждой надписью расположим табличное поле с именами ТабличноеПолеПоля и ТабличноеПолеПорядка, в обоих случаях не забудем установить флаг Вставить командную панель Это позволит нам добавить командные панели, источниками действий которых будут назначены созданные нами табличные поля (рис. 5.70).
Где этот флаг "Вставить командную панель"? В свойствах табличного поля я его не нашёл.
Следует сказать, что в системе 1С:Предприятие 8 имеется небольшой набор уже готовых макетов оформления для использования системой компоновки данных. Они содержатся в объекте БиблиотекаМакетовОформленияКомпоновкиДанных.
Поместим еще одну надпись с именем Оформление и заголовком Оформление, а под ним расположим поле выбора с именем ПолеВыбораОформление (рис. 5.72) без подписи.
В свойствах нашего поля выбора откроем окно Строки списка выбора и заполним его именами макетов из библиотеки макетов оформления компоновки данных (см. рис. 5.73).
У меня вместо того, что отображено на рисунке 5.73 отображается следующее:
Соответственно, запуская этот отчет - я ничего не получаю.
ЗЫ. картинки из книги я тут не приводил, т.к. надеюсь, что у людей читающих эту тему есть данная книга, а если нету, то её можно скачать здесь
Перем БазаAccess, Cmd, Rs, СтрокаЗаписи;
Для Каждого СтрокаТаблицы ИЗ ТаблицаЗагрузки Цикл
Если НЕ СтрокаТаблицы.Пометка Тогда
Продолжить;
КонецЕсли;
ИмяТаблицы = СтрокаТаблицы.ИмяТаблицы;
СпрТаблицы = Справочники.ТаблицыАксесс.НайтиПоНаименованию(ИмяТаблицы, Истина);
Если СпрТаблицы.Пустая() Тогда
СпрОбъект = Справочники.ТаблицыАксесс.СоздатьЭлемент();
СпрОбъект.Наименование = ИмяТаблицы;
Иначе
СпрОбъект = СпрТаблицы.ПолучитьОбъект();
КонецЕсли;
ТабДок = Новый ТабличныйДокумент;
ПоляТаблицы = РазложитьСтрокуВМассивПодстрок(СтрокаТаблицы.СписокКолонок, ",");
СчетчикПолей = 0;
Для Каждого ПолеТаблицы ИЗ ПоляТаблицы Цикл
СчетчикПолей = СчетчикПолей + 1;
ТабДок.Область(1, СчетчикПолей).Текст = ПолеТаблицы;
КонецЦикла;
ТабДок.Область(1, 1, 1, СчетчикПолей).Шрифт = Новый Шрифт(,,Истина);
СпрОбъект.Таблица = Новый ХранилищеЗначения(ТабДок, Новый СжатиеДанных());
СпрОбъект.Записать();
Читайте также: