Поговорим о создании функций в Octave, но начнём с вызова. Основной способ выполнить функцию - указать её имя и список аргументов, например sin(pi/3). Можно, однако, использовать вызов через feval, при котором всё выражение записывается как список аргументов: feval("sin",pi/3). Ещё вариант - создать псевдоним для имени функции с помощью знака @, например f = @sin. После этого можно использовать вызов f(pi/3) или feval(f,pi/3).
Большинство функций Octave хранит в виде m-файлов, при этом имена файла и функции должны совпадать. Узнать место их размещения можно с помощью команды path. Редактировать список используемых программой директорий можно с помощью следующих функций.
addpath("путь к каталогу") - добавить каталог.
genpath("путь к каталогу") - использует указанный каталог и все вложенные подкаталоги.
rmpath("путь к каталогу") - удаляет каталог из списка.
Теперь о функциях. Простейшее определение функции, которая не принимает аргументов и ничего не возвращает, будет иметь вид
function имя
тело
endfunction
Если мы хотим что-то функции передать, то должны указать список аргументов (в круглых скобках).
function имя (аргументы)
тело
endfunction
Наконец, если мы ожидаем получить какой-то результат, нужно также задать список возвращаемых значений (в квадратных скобках).
function результат = имя (аргументы)
тело
endfunction
Иногда число аргументов функции заранее неизвестно. В этом случае список должен завершаться словом vagargin, которое становится именем вектора, содержащего вводимые значения.
function res = my_avg(varargin)
res = sum(varargin)/length(varargin);
endfunction
Если по каким-то причинам неизвестно количество выходных данных, можно использовать вектор varargout = f (...).
Порой бывает удобно задать значения некоторых аргументов по умолчанию. Если при вызове функции данный аргумент не будет указан, то используется значение, указанное в определении.
function res = sin_amp(t,freq,phi=0)
res = sin(2*pi*freq*t-phi);
endfunction
Т.к. начальная фаза здесь задана по умолчанию, при вызове её можно опустить: sin_amp(0.5,3).
Octave поддерживает рекурсию, т.е. вызов функцией самой себя. Исключение - некоторые встроенные функции, например, lsode. Вот "хрестоматийный" пример факториала
function res = fact (n)
if (n > 0)
res = n * fact(n-1);
else
res = 1;
endif
endfunction
Сложную функцию можно разбить на более простые, записанные в пределах одного m-файла. При этом сначала записывается определение основной функции, а затем вспомогательных (вложенных).
function res = f(x)
res = x * g(x);
endfunction
function res = g(x)
res = x * x;
endfunction
Возможен и другой вариант.
function res = f(x)
res = x * g();
function t = g()
t = x * x;
endfunction
endfunction
Во втором примере вложенная функция имеет доступ к пространству переменных той функции, в которой она определена, поэтому стало возможным опустить список аргументов.
Наконец, если вашими функциями будет пользоваться кто-то ещё, полезно добавить проверку правильности обращения к ним. В частности, длина списка аргументов вызываемой функции хранится в переменной nargin, а списка возвращаемых значений - nargout. Есть функции для проверки типа данных isvector(), isreal() и пр. Если же обнаружена ошибка, завершить выполнение и вывести сообщение можно с помощь функции error("сообщение").
А зачем сделано чтобы имя функции совпадало с именем файла и как можно это отключить?
ОтветитьУдалитьПотому, что функция может быть только отдельным файлом, как в matlab до недавнего времени. Вызывая функцию, интерпретатор обращается к соответствующему файлу. Если имя будет другим, функция просто не найдётся.
УдалитьПотому, что функция может быть только отдельным файлом, как в matlab до недавнего времени. Вызывая функцию, интерпретатор обращается к соответствующему файлу. Если имя будет другим, функция просто не найдётся.
Удалить