четверг, 14 апреля 2016 г.

Cache': Передача аргументов

Эта заметка посвящена передаче аргументов в функции на Cache Object Script. Изложение материала предполагает понимание различия между формальными и фактическими параметрами.
Передача параметров делится по отношению к вызывающей стороне (фактические):
  1. По значению
  2. По ссылке
и по отношению в вызываемой функции (формальные):
  1. Простой
  2. С указанием значения по умолчанию
  3. Переменное количество аргументов


При передаче аргумента по значению в вызываемую функцию передается значение указанной переменной / константа / вычисляемое выражение. Может быть только атомарным. Если передается значение переменной, а сама переменная не определена, то возникает ошибка UNDEFINED.

Пример:
f1()
  n a
  s a=123
  d f2(a)
  q
f2(var)
  w var
  q


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

Пример:
f1()
  n a
  d f2(.a)
  s a="" f  s a=$O(a(a)) q:a=""  d
  . w a_":"_a(a),!
  q
f2(var)
  n i
  f i=1:1:10 d
  . s var(i)=i*i
  q


Приведенные примеры показывают применение простого формального аргумента по отношению к вызываемой функции. При приеме формального аргумента с указанием значения по умолчанию указывается это значение через знак равенства:

Пример:
f1()
  n a,b
  d f2(,.b)
  q
f2(var=123,var2="undefined")
  w var,!
  w var2,!
  q
При приеме формального аргумента с указанием значения по умолчанию значение может быть только константой - строка или число. При передаче фактического аргумента по ссылке из него будет взято указанное значение и на стеке все равно будет создана локальная атомарная копия. В случае если передаваемая переменная была неопределена (и передавалась по ссылке) или фактический аргумент был опущен, то вызываемая функция получит значения формальных переменных как было специфицировано.

В Cache 5 в методах классов компилятор поддерживает передачу значений по умолчанию также в виде вычисляемого выражения. Используемый синтаксис:
Method MethodName(Param As Type = { expression })
{
  ...
}
При компиляции такого выражения компилятор генерирует код в виде
s Param=$G(Param,expression)


При приеме переменного количества аргументов вызывающая сторона может указать произвольное количество фактических переменных и опускать произвольные из них. Функция специфицирует, что она намерена принять переменное количество аргументов указанием многоточия после имени формального аргумента. Такой аргумент у функции может быть только один и он должен быть последним в списке формальных переменных. Формальная переменная принимает значение количества указанных на ее месте фактических переменных, а ее подиндексы начиная с единицы с шагом через единицу принимают значения переданных фактических аргументов.

Пример:
f1()
  d f2(12,,,456,,)
  q
f2(vars...)
  n i
  w "n = "_vars,!
  f i=1:1:vars d
  . i $d(vars(i)) w i_":"_vars(i),!
  q
При этом попытка передачи фактического аргумента по ссылке игнорируется, формальный аргумент принимает атомарные значения и создается на стеке. При опускании фактических аргументов или при передаче по ссылке неопределенной локальной переменной формальная переменная принимает неопределенное значение.

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

Пример:
f1()
  d f2(123,)
  d f2(123)
  q
f2(a,b)
  i $d(a) w "a:"_a,!
  i $d(b) w "b:"_b,!
  q
Но передавать в фактических аргументах большее количество аргументов чем число формальных если не используется переменное количество аргументов нельзя.

Несколько особняком стоит безаргументный вызов функций. Формально говоря, безаргументный вариант по стандарту допускается только при вызове через do:
f1()
  d f2
  w $$f3(),!
  q
f2
 w 123,!
 q
f3()
 q 123
Но Cache' 4 поддерживает также вариант:
f1()
  w $$f2,!
  q
f2()
  q 123
А Cache' 5 также и
f1()
  w $$f2,!
  q
f2
  q 123
Какой вариант использовать и стоит ли придерживаться стандарта - конечно, выбор за разработчиком. Но мне бы не хотелось получить образцы такого кода, который бы выглядел как использующий чистый COS и зависел при этом от версии.

Евгений Каратаев

Комментариев нет:

Отправить комментарий