使用指令字串(Using Evaluation)
一般來說要執行 Octave 的指令可以由命令列視窗直接輸入,或讓 Octave 直接執行儲存在檔案中的程式,然而有時候會需要直行儲存在字串變數中的指令,這時候就可以使用 eval()
函數。
eval (try, catch)
eval(try, catch)
函數會將字串 try
的內容視為 Octave 的指令來執行,若執行失敗,則會再執行字串 catch
的內容。try
的內容是在目前的變數環境(Context)中執行的,因此所有的結果都會保留在目前的變數環境中。例如:
eval("a = acos(-1);");
這樣會在目前的變數環境中建立一個變數 a
,其值為 3.1416
。
若有錯誤發生時,就會執行 catch
的內容,例如:
eval ('error ("This is a bad example");', 'printf ("This error occurred:\n%s\n", lasterr ());');
輸出為
This error occurred: This is a bad example
由函數名稱呼叫(Calling a Function by its Name)
feval()
函數會以包含函數名稱的字串呼叫指定的函數,這個特性可以讓使用者指定函數,此函數會呼叫第一個參數所指定的函數,並將第二個以後的參數傳入此函數。
下面這個範例是使用牛頓法尋找指定函數的解:
function result = newtroot (fname, x) # usage: newtroot (fname, x) # # fname : a string naming a function f(x). # x : initial guess delta = tol = sqrt (eps); maxit = 200; fx = feval (fname, x); for i = 1:maxit if (abs (fx) < tol) result = x; return; else fx_new = feval (fname, x + delta); deriv = (fx_new - fx) / delta; x = x - fx / deriv; fx = fx_new; endif endfor result = x; endfunction
這個範例主要的目的只是說明如何使用 feval()
函數而已,實際上的的函數應該還要加入一些安全檢查的機制,例如判斷 fname
所指定的函數是否真的存在等。
feval (name, ...)
feval(name, ...)
函數會執行名稱為 name
的函數,從第二個之後的參數都會被傳入此函數中,例如:
feval ("acos", -1)
這樣會執行 acos(-1)
,輸出為
ans = 3.1416
由於 Octave 中沒有類似像 C 語言的函數指標功能,因此要傳遞函數唯一的方式就是使用函數名稱,再配合 feval()
函數來執行。
另外有一個類似功能的函數 run()
,此函數可以執行使用者的指令稿。
run (f) run f
run(f) 函數會執行目前目錄的指令稿f
,若f
包含其路徑,則 Octave 會先變換目前的目錄至該路徑再執行,執行完成後再返回原目錄。
在不同的變數環境中執行(Evaluation in a Different Context)
使用指令字串時,在指令中的變數值都是由儲存在 Octave 的符號表(symbol table)中,而在呼叫函數時 Octave 會將目前的符號表暫時儲存起來,另外產生一個新的提供呼叫的函數來使用,這個新的符號表會包含呼叫函數時所傳入的變數,另外再加上一些內建的變數,例如 nargin
等,任何在函數中的算式都是使用新的符號表。 有時候使用者會需要在呼叫函數時,在函數中取得或變更目前符號表中的變數,也就是類似 C 語言中的指標(pointer),這個時候可以使用 evalin()
與 assignin()
函數。
evalin (context, try, catch)
evalin(context, try, catch)
函數與 eval()
函數類似,但可以透過 context
參數指定變數環境,此參數可以使用的選項有:
"caller"
:上一層的變數環境,也就是呼叫此函數的呼叫者。"base"
:位於最上層的命令列變數環境。
下面我們以範例說明 evalin()
函數的使用方式,首先定義兩個函數 func1()
與 func2()
,並在最上層與 func1()
中都定義一個 test_var
變數:
test_var = "base"; function func1 test_var = "from func1"; func2(); endfunction function func2 evalin("base", "test_var"); evalin("caller", "test_var"); endfunction
這時候若執行
func1()
輸出為
test_var = from base test_var = from func1
當 func1()
呼叫 func2()
時,第一個 evalin()
函數的 context
參數是指定為 "base"
,因此會取得最上層的 test_var
,而第二個 evalin()
函數的 context
參數則是設為 "caller"
,所以其取得的是函數呼叫者 func1()
函數之中的 test_var
。
assignin (context, varname, value)
assignin(context, varname, value)
函數可以將變數環境 context
中的變數 varname
指定為 value
,context 可用的選項與 evalin()
函數相同。例如在自行定義的 func3() 函數中以 assignin()
函數在最上層的命令列變數環境中新增一個變數 new_var
,並指定其值:
function func3 assignin("base", "new_var", "new value"); endfunction
執行 func3()
函數之後,就會多了一個名為 new_var
的變數:
func3();
new_var
輸出為
new_var = new value