指令稿檔案(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()
函數的參數 a
與 b
會從目前的變數環境中取得,輸出為
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
中取出,而參數的順序會依照英文字母的順序排序,而在擷取參數時 i
與 j
會被忽略,因為 i
與 j
也代表複數的虛部,使用起來容易造成混淆。所有加上小括號的名稱都會被視為函數。
參數 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
中擷取出所有的函數參數,並以巢狀陣列傳回,一般的常數會被忽略(例如:pi
、 NaN
、 Inf
、 eps
、 i
或 j
),若沒有找到任何參數,則傳回空的巢狀陣列。例如:
symvar("x^2 + 2 + y")
輸出為
ans = { [1,1] = x [2,1] = y }