指令稿檔案(Script Files)

指令稿檔案(Script Files)可以包含(幾乎)任何的 Octave 指令,執行指令稿時 Octave 會將其中的指令讀入後執行,就跟直接在命令列中輸入一樣,這樣可以讓使用者很方便的執行一連串的指令。

指令稿檔案與函數檔案不同,其第一行指令不可以為 function 關鍵字開頭。在指令稿檔案中可以定義多個函數,並且一次將這些函數載入(只有載入,沒有執行),由於第一行指令(不包含註解或空白行)的開頭不可以是 function,所以必須執行別的指令,若沒有需要執行其他的指令,可以加入一行沒有作用的指令,例如:

# Prevent Octave from thinking that this
# is a function file:

1;

# Define function one:

function one ()
  ...

若指令稿中第一個指令以 function 關鍵字開頭,Octave 會嘗試將其編譯後並執行之,並且產生一些警告訊息。

為了使 Octave 可以正確的載入指令稿檔案,可以將指令稿檔案命名為 .m 檔案,放置在載入路徑中,然後在 Octave 中輸入其主檔名,Octave 就會將其載入,其載入的規則與函數檔案相同。

Octave 在執行函數之前,並不會去檢查其中的指令是否有定義,例如 Octave 在編譯下面這個指令稿檔案時是不會出現問題的:

# not a function file:
1;
function foo ()
  do_something ();
endfunction
function do_something ()
  do_something_else ();
endfunction

這個指令稿檔案先定義 foo() 函數,而 foo() 函數中呼叫 do_something() 函數,雖然在定義 foo() 函數時 do_something() 函數還沒有被定義,但是因為 Octave 並沒有去執行 foo() 函數,所以此時 Octave 還不需要 do_something() 函數的定義,等到隨後 do_something() 函數定義之後,再執行 foo() 函數時,do_something() 函數已經有定義了,所以這樣寫是沒有問題的。

指令稿檔案除了命名為 .m 檔然後輸入其主檔名將其載入外,也可以使用 source() 函數載入指令稿檔案。

source (file)

source(file) 函數可以載入指令稿檔案 file,這與直接執行 .m 指令稿名稱相同,但此 file 的名稱沒有限制(可以是 .txt 或其他的檔案名稱)。

函數握把 、行內函數與匿名函數(Function Handles, Inline Functions and Anonymous Functions)

在撰寫程式時有時候會需要將函數以變數的形式傳遞,例如將一個函數指定為另一個函數的傳入參數,這時就可以利用下面介紹的方法。

函數握把(Function Handles)

函數握把(function handle)是一個指向函數的指標,其定義方式為

@function-name

例如:

f = @sin;

這樣會建立一個指向 sin() 函數的函數握把 f

函數握把主要用於將一個函數傳遞給其他的函數(例如:quad()fsolve() 函數)使用,例如:

f = @sin;
quad (f, 0, pi)

輸出為

ans =  2

若要呼叫函數握把所指向的函數,可以使用 feval() 函數或是直接使用函數握把並加入參數,若沒有輸入參數,則還是要加上小括號 (),例如:

f = @sin;
feval (f, pi/4)

輸出為

ans =  0.70711
f (pi/4)

輸出為

ans =  0.70711
functions (fcn_handle)

functions(fcn_handle) 函數會傳回一個包含函數握把 fcn_handle 相關訊息的資料結構(struct)。

func2str (fcn_handle)

func2str(fcn_handle) 函數會傳回一個字串,內容為函數握把 fcn_handle 所指向的函數名稱。

str2func (fcn_name)

str2func(fcn_name) 函數會將包含函數名稱的字串 fcn_name 轉為函數握把。

匿名函數(Anonymous Functions)

匿名函數(Anonymous Functions)就是沒有函數名稱的函數,其定義方式為:

@(argument-list) expression

expression 中所使用的變數若不在傳入參數 argument-list 中,則會由目前的變數環境中抓取。匿名函數主要用於定義一個不需要名稱的函數,例如定義一個函數並將此函數傳入 quad() 函數中:

f = @(x) x.^2;
quad (f, 0, 10)

輸出為

ans =  333.33

sin() 函數以匿名函數包裝:

quad (@(x) sin (x), 0, pi)

輸出為

ans =  2

betainc() 函數包裝成 quad() 函數可以形式:

a = 1;
b = 2;
quad (@(x) betainc (x, a, b), 0, 0.4)

其中 betainc() 函數的參數 ab 會從目前的變數環境中取得,輸出為

ans =  0.13867

行內函數(Inline Functions)

行內函數(Inline Functions)是指使用 inline() 函數從一個包含程式主體(body)的字串所建立的函數,例如:

f = inline("x^2 + 2");

這樣會建立一個 f() 函數,其可接受一個輸入參數,例如 f(2)

inline (str)
inline (str, arg1, ...)
inline (str, n)

inline() 函數會由包含程式主體的字串 str 建立行內函數,若只有指定一個 str 參數,則函數的參數會自動由 str 中取出,而參數的順序會依照英文字母的順序排序,而在擷取參數時 ij 會被忽略,因為 ij 也代表複數的虛部,使用起來容易造成混淆。所有加上小括號的名稱都會被視為函數。

參數 arg1, ... 可以指定參數的名稱。參數 n 為一個正整數,指定參數的個數為 n,若指定為 n 則所有的參數為 "x", "p1", ..., "pn"

argnames (fun)

argnames(fun) 函數會傳回包含行內函數 fun 的所有參數名稱的字串巢狀陣列。例如:

f = inline("x^2 + 2");
argnames(f)

輸出為

ans =

{
  [1,1] = x
}
formula (fun)

formula(fun) 函數會傳回行內函數 fun 的內容,例如:

f = inline("x^2 + 2");
formula(f)

輸出為

ans = x^2 + 2
char(fun)formula(fun) 是相同的。
vectorize (fun)

vectorize(fun) 函數會將行內函數 fun 轉為向量化的函數,即將 */ 等運算子替換為 .*./ 等運算子。例如:

f = inline("x^2 + 2");
vectorize(f)

輸出為

ans =

f(x) = x.^2 + 2
symvar (s)

symvar(s) 函數會從包含函數主體的字串 s 中擷取出所有的函數參數,並以巢狀陣列傳回,一般的常數會被忽略(例如:piNaNInfepsij),若沒有找到任何參數,則傳回空的巢狀陣列。例如:

symvar("x^2 + 2 + y")

輸出為

ans =

{
  [1,1] = x
  [2,1] = y
}