ans
). Во втором случае функция не имеет выходных параметров, а, например, предназначена для вывода результатов расчета (построение гра- фика, таблицы значений и т.п.).
По умолчанию все переменные, описанные в теле функции, являются
локальными.
Простейшим случаем использования внутренних встроенных функций является сценарий, состоящий из одной функции. Рассмотрим пример созда- ния сценария с описанной внутри него одной функцией
fun(x)=ax
2
+x/2
и одним
62 входным параметром, сохранения этого сценария в
sce
-файле, загрузки и об- ращения к нему из Командного окна.
Для этого необходимо выполнить следующие шаги:
1) Загрузить текстовый редактор SciNotes.
2) Описать сценарий со встроенной функцией
fun(x)
в редакторе.
3) Сохранить сценарий в
sce
-файл под именем
РИС1256
4) Загрузить сценарий в Командном окне командой
exec
5) Выполнить (вызвать) функцию
fun(x)
На рис. 1.2.5-7 показаны окно редактора SciNotes после написания сце- нария, содержащего функцию
fun(x)
, записанного в файл
РИС1526.sce.
Ниже приведено содержимое Командного окна, из которого происходит загрузка файла
-
сценария
РИС1526, двукратное обращение к встроенной функции
fun(x)
и в котором отображаются результаты ее вы выполнения.
При выполнении команды
fun(x)
, функция принимает один фактиче- ский входной параметр
x=5
(переменная
x
должна быть предварительно опре- делена), вычисляет с использованием встроенной в сценарий функции значе- ние по соответствующей формуле и возвращает его через выходной пара- метр
ans
. Второе обращение в функции показывает возможность использова- ния функции
fun
в операторе присваивания. Здесь в качестве параметра
x
использовано числовое значение, а результат выполнения присваивается пе- ременной
y
--> // Загрузка файла РИС12507.sce и выполнение функции fun
--> exec('РИС12507.sce',0);
-->
--> clear
--> x = 5; // Определение значения параметра х
--> fun(х) // Вычисление функции fun(x) при х = 5
ans =
27.5
-->
--> y = fun(4) // Использование функции в операторе присваивания y =
18.
Рис. 1.2.5-7 Окно SciNotes и Командное окно
63
Тело функции может включать в себя любые выражения Scilab, функции ввода/вывода,
операторы управления, комментарии, пустые строки и вложен- ные функции и многое другое.
Обратите внимание, что любые переменные, которые определены в функциях, хра-нятся в своих локальных Рабочих областях данных каждой функции, то есть от-дельно от Рабочей области Обозревателя переменных, в которой хранятся только пе-ременные, определенные в Командном окне и сценариях. В следующем примере, приведенном на рис. 1.2.5-8, представлено опи- сание сценария, включающего одну встроенную функцию с несколькими вы- ходными параметрами. Заметим, что список выходных параметры в заголовке функции заключен в квадратные скобки, а сами параметры отделены друг от друга запятыми. Загрузим файл-сценарий
РИС1527.sce и вызовем функцию
quadeq, которая должна по заданным коэффициентам квадратного уравнения вычислить его корни.
--> //
Загрузка файла РИС12508.sce и выполнение функции quadeq--> exec('РИС1258.sce', 0);
-->
--> clear
--> //
Матрицы с заданными коэффициентами трех уравнений --> A = [1 3 5]; B = [2 4 6]; C = [1 2 4];
--> [X1, X2] = quadeq (A, B, C) //
Обращение к функции quadeq X2 =
-1. -0.6666667 - 0.4714045i -0.6 - 0.663325i
X1 =
-1. -0.6666667 + 0.4714045i -0.6 + 0.663325i
Рис. 1.2.5-8 Содержимое окна
SciNotes и
Командного окна после загрузки сценария
РИС1257 и выполнения функции
quadeq В двух рассмотренных выше примерах сценарии
РИС1257 и
РИС1258 были созданы в редакторе
SciNotes,загружены и вызваны на выполнение из
Ко-мандного окна, куда и были выведены результаты.
Чтобы запустить на выполнение сценарий из окна редактора
SciNotes, достаточно нажать кнопку (
Выполнить) или выбрать команду
Выполнить 64 в одноименном элементе меню. В результате в строке
Командного окна по- явится команда
exec c указанием полного пути к файлу, а курсор устанавлива- ется в начале следующей строки.
Следует помнить, что переменные, созданные внутри функции, являются локальными и действуют только в пределах этой функции. Переменные, созданные в пространстве вне функций, являются глобальными и доступны во всех функциях данного файла и те-кущей рабочей сессии. В одном файле, созданном в редакторе, который является, по сути дела, всегда сценарием, может быть описано сразу несколько функций. Эти функ- ции могут
общаться между собой посредством имен функций, а также
вход-ных и
выходных параметров.
Общая структура сценария, содержащего несколько встроенных внут- ренних функций сценария, может быть следующей:
//
Имя Сценария и его назначение Тело сценария ... functionf1 ТелоФункцииf1end …
functionfm ТелоФункцииfmend // end сценария Эта структура и некоторые другие вопросы, касающиеся области види- мости данных при использовании нескольких функций, будут рассмотрены подробно в
п. 1.2.6.
1.2.6. Общая структура функций и сценариев. Области видимости переменных Общая структура кода сценарияВ предыдущем разделе были даны правила описания сценариев и внут- ренних встроенных в них функций, а также приведены соответствующие при- меры их описания, где в каждом
sce-файле содержалось по одной функции.
Однако в каждом сохраненном
sce-файле могут находиться описания более чем одной независимой функции, причем в каждую из них может быть вло- жена другая функция (рис 1.2.6-1).
65
--> //
Загрузка и выполнение вложенных функцией --> exec('РИС12601.sce', 0);
--> clear
--> x = 2;
--> r = mvf(x) r =
2.
Рис. 1.2.6-1 Пример реализации вложенных функцией
Как уже отмечалось, в сценарии программные коды
независимых функ-ций должны располагаться одна за другой, когда как
вложенные функции располагаются внутри функций.
На рис 1.2.6-2 показано сначала обращение из
Командного окна к функции
vstfun, использующей функции
vfun1 и
vfun2, расположенные в сце- нарии, а затем отдельно к функции
vfun2.
Этот пример показывает, что все остальные функции, при подключении сценария командой
exec становятся до- ступными для использования в
Командном окне.
66
--> // Загрузка сценария РИС12602 и обращения к vstfun, vfun1 и vfun2
--> exec('РИС12602.sce', 0);
-->
--> clear
--> y = vstfun(2) //Обращение к vstfun2(2), а из нее кvfun1(2) иvfun2(2) y =
2.
-->
--> f=vfun1(2), f = vfun2(2) //Независимое обращение к vfun1(2) и vfun2(2) f =
0. f =
2.
Рис. 1.2.6-2 Пример обращения к функциям сценария
Следует помнить, что перед обращением к любому сценарию, сохраненному в sce-
файле, этот файл должен быть загружен командой exec.
Имя функции как тип переменной
Одно из достоинств языка Scilab является то, что функции являются ти- пом переменных. Это означает, что мы можем хранить функции в переменных и использовать переменные как функции. В компилируемых языках эта воз- можность часто называется «указатель на функцию».
В следующем примере (рис 1.2.6-3) определим функцию
f
. Затем, уста- новим содержимое переменной
fp
равным функции
f
. Наконец, мы можем ис- пользовать функцию
fp
как обычную функцию.
67
--> // Загрузка сценария РИС12603 и обращения к функции f
--> exec('РИС15303.sce', 0);
-->
--> clear
--> fp = f fp =
[y] = fp(t)
-->
--> fp(1) ans =
2.
Рис. 1.2.6-3 Пример использования указателя на функцию
Эта возможность позволяет использовать широко распространённый ин- струмент языков программирования, известный как функция обратного вы-
зова (
callback
).
Функция обратного вызова – это функция, которая передается другой функции в качестве параметра. При этом передается указатель (ссылка) на эту функцию. В свою очередь другая функция, вызывает переданную через пара- метр функцию.
Поскольку функции являются переменными можно устанавливать зна- чения этих переменных несколько раз. Для того, чтобы предупредить пользо- вателей от нежелательного переопределения функций, при переопределении может появляться сообщение-предупреждение, как показано в примере на рис
1.2.6-4.
--> // Загрузка сценария РИС12604 и переопределение функций
--> exec('РИС12604.sce', 0);
-->
--> clear
--> f = f1 f =
[y] = f(x)
-->
--> f = f2
Предупреждение: переопределение функции: f.
68
Используйте funcprot(0) чтобы не выводить это сообщение--> f =
--> [y] = f(x)
Рис. 1.2.6-4. Получение предупреждения о переопределении функции
В данном случае нет причин защищать себя от присвоения переменной
f нового значения, в Scilab имеется простой способ отключить на время пре- дупреждение. Функция
funcprot позволяет заблокировать режим защиты функций:
pr=funcprot() –
получить текущий режим защиты функций;
funcprot(0) – нет сообщений, когда функция переопределена
;
funcprot(1) – выдает предупреждение о переопределении функции
(по умолчанию);
funcprot(2) – выдает ошибку, когда функция переопределена
Scilab позволяет переопределить любые функции (даже библиотечные), но это вызывает ошибку и выводится соответствующее сообщение. В следую- щем примере (рис. 1.2.6-5) функция
rand определена как обычная функция, проверим, можем ли мы вызвать её как любую другую функцию, определён- ную пользователем.
--> //
Загрузка сценария РИС12605 и переопределение функций rand --> exec('РИС12605.sce', 0);
--> clear
--> rand()
Предупреждение: переопределение функции: rand. Используйте funcprot(0) чтобы не выводить это сообщение -->
--> funcprot(0)
--> y = rand(1) y =
2.
Рис. 1.2.6-5 Переопределение встроенный библиотечной функции
rand, описанной в сценарии
РИС15305Появилось сообщение о том, что функцию
rand переопределили. То есть функция
rand уже существует в Scilab, что может быть легко проверено коман- дой
help rand. Действительно, встроенная функция
rand позволяет генериро- вать случайные числа, и мы, конечно же, не хотим ее терять и переопределить.
69
В данном случае ошибка очевидна, но на практике ситуации могут быть го- раздо более сложными, поэтому переопределять функции надо очень осто- рожно.
Видимость переменных
Как известно, переменные, созданные в процессе выполнения сессии, хранятся в области Обозревателя переменных, кроме тех, которые описаны в функциях. То есть переменные, описанные внутри функций, хранятся в своих локальных областях памяти. Поэтому функция может получить доступ к пере- менным только в том случае, если данные передаются в качестве аргументов.
Это позволяет защитить целостность данных. Сценарий, представленный на рис. 1.2.6-6 содержит три независимые функции со своими локальными пере- менными. Загрузив сценарий, и вызвав функцию
vstfun
из Командного окна,
можно видеть, что переменные функций являются локальными и недоступны как из Командного окна, так и из сценария.
--> // Загрузка сценария РИС12606
--> // и обращение к функции vstfun
--> clear
--> exec('РИС12606.sce', 0);
-->
--> x = 2;
--> r = vstfun(x) r =
8.
Рис. 1.2.6-6 Отображение данных сессии в окне Обозреватель переменных
В окне Обозреватель переменных отобразились только две переменные
(
r
и
x
), используемые в Командном окне. Таким образом, локальные перемен- ные не доступны ни командной строке, ни другой
sce
-функции.
70
Один из способов получить доступ к переменным локальных функций объявить переменные глобальными (
global
). Глобальные переменные хра- нятся в своей области глобальных переменных. Особенность глобальных пе- ременных состоит в том, что они видны тем объектам текущего сеанса, где они описаны как глобальные.
Однако использовать глобальные переменные опасно, поскольку:
1) любая функция может получить доступ и обновить глобальную пере- менную, в этом случае другие функции, использующие эту перемен- ную, могут получить неожиданные результаты.
2) «новая» глобальная переменная может случайно получить то же са- мое имя, что и «старая» (уже существующая) глобальная переменная.
Это приводит к ошибке, которая трудно диагностируется.
Прежде чем обращаться к глобальным переменным функции из команд- ной строки их необходимо объявить. Для этого предназначена функция
global
,
имеющая следующий формат:
global
(
СписокГлобальныхПеременных
)
где в
СписокеГлобальныхПеременных
через запятую перечисляются имена гло- бальных переменных, заключенные в кавычки, например,
global('a','b','x')
Если
СписокГлобальныхПеременных
содержит одну переменную, то допускается создание списка без скобок и кавычек.
Создадим, например, в командной строке глобальную переменную
x
, присвоив ей значение
2
. Теперь рассмотрим пример, приведенный на рис.1.2.6-7.
--> // Загрузка сценария РИС12307 и обращение к функциям f1 и f2
-->
--> clear
--> exec('РИС12307.sce');
--> a = 1;
--> f1() // Обращение к функции f1
--> a a =
71 4.
--> f2() //
Обращение к функции f2 --> a a =
4.
Рис.1.2.6-7 Пример, иллюстрирующий область видимости переменных
Обратите внимание, что при обращении к функции
f1, переменная
а из- менила свое значение, а при обращении к функции
f2 значение
а осталось прежним. Дело в том, что и в командной строке, и в функции
f1, переменная, а объявлена глобальной, то есть она является видимой для
f1. В функции
f2 переменная
а является локальной, то есть невидимой для функции
f2, таким образом, это две разные переменные, расположенные в разных областях опе- ративной памяти.
В Scilab имеется еще ряд функций для работы с глобальными перемен- ными, имеющими тот же формат, что и функция
global:
clearglobal –
уничтожает глобальные переменные списка;
isglobal – проверяет, является ли переменная глобальной;
gstacksize – определяет размер области глобальных переменных
В любом языке программирования использование глобальных перемен- ных усложняют понимание программ, кроме того они менее защищены от из- менений.
Поэтому если есть возможность, данные в функции лучше переда- вать через параметры.
1.2.7 Контрольные вопросы 1)
Какие объекты Scilab Вам известны?
2)
Как называются символы
. , : ; () [] {} // % $ ' " = и в ка- ково их назначение в Scilab?
3)
Что означает в Scilab «определить данные»?
4)
Какой символ служит для переноса части командной строки на сле- дующую строку?
5)
Для чего используются системные встроенные функции:
whos, who, who_user, typeof, typeи
clear?
6)
Как в Scilab представлены комплексные числа?
7)
Какие системные константы Вам известны?
8)
Из каких элементов строятся числовые арифметические выраже- ния?
9)
Каков приоритет действий в арифметических выражениях?
10) Какой символ используется для запрета вывода результата вычисле- ний на экран?
11) Какие типы переменных используются в Scilab?
72 12) Чем характеризуются матрицы?
13) Как создать вектор-строку?
14) Как создать вектор-столбец?
15) Какая функция служит для определения длины вектора?
16) Каким образом создать вектор с постоянным шагом?
17) Требуется ли при работе с векторами и матрицами предварительное объявление их размера?
18) Какой символ используются для разделения элементов матрицы в строке, а какой для разделения ее строк?
19) Какие команды предназначены для заполнения матрицы случай- ными числами, распределенными по равномерному или нормаль- ному закону распределения?
20) Формат команд выбора минимального и максимального значения элемента матрицы.
21) Как записать выражение для решения матричных уравнений?
22) Какие поэлементные матричные операции Вам известны?
23) Как происходит преобразование данных к арифметическому типу?
24) Из каких элементов состоят логические выражения?
25) Как представлены в Scilab строки символов?
26) Что такое форматированный вывод данных?
27) Для чего используется функция