Từ khóa trong AFL (AmiBroker Formula Language)
Vòng lặp (Loops)
do, câu lệnh do-while
Từ khóa do là một phần của câu lệnh do-while.
Câu lệnh do-while
Câu lệnh do-while cho phép bạn lặp lại một câu lệnh hoặc câu lệnh hợp thành cho đến khi một biểu thức cụ thể trở thành sai.
Cú pháp do-while
do statement while ( expression );
Biểu thức trong câu lệnh do-while được đánh giá sau khi phần thân của vòng lặp được thực thi. Do đó, phần thân vòng lặp luôn được thực thi ít nhất một lần.
Biểu thức phải có kiểu số hoặc boolean. Quá trình thực thi diễn ra như sau:
-
Phần thân câu lệnh được thực thi.
-
Sau đó, biểu thức được đánh giá. Nếu biểu thức là sai, câu lệnh do-while kết thúc và điều khiển chuyển sang câu lệnh tiếp theo trong chương trình. Nếu biểu thức là đúng (khác không), quá trình sẽ lặp lại từ bước 1.
Ví dụ về câu lệnh do-while
x = 100;
do
{
y = sin( x );
x--;
} while ( x > 0 );
Trong ví dụ này, hai câu lệnh:
y = sin( x );
x--;
được thực thi, bất kể giá trị ban đầu của x. Sau đó, biểu thức x > 0 được đánh giá. Nếu x lớn hơn 0, phần thân của câu lệnh sẽ được thực thi lại và x > 0 sẽ được đánh giá lại. Phần thân câu lệnh sẽ được thực thi lặp lại miễn là x vẫn lớn hơn 0. Việc thực thi câu lệnh do-while sẽ kết thúc khi x trở thành 0 hoặc âm. Phần thân của vòng lặp luôn được thực thi ít nhất một lần.
while, câu lệnh while
Từ khóa while là một phần của câu lệnh while (mô tả dưới đây) và câu lệnh do-while.
Câu lệnh while
Câu lệnh while cho phép bạn lặp lại một câu lệnh cho đến khi một biểu thức cụ thể trở thành sai.
Cú pháp while
while ( expression ) statement
Biểu thức phải có kiểu số học (numeric/boolean). Quá trình thực thi diễn ra như sau:
- Biểu thức được đánh giá.
- Nếu biểu thức ban đầu là sai, phần thân của câu lệnh while sẽ không bao giờ được thực thi, và điều khiển chuyển từ câu lệnh while sang câu lệnh tiếp theo trong chương trình.
- Nếu biểu thức là đúng (khác không), phần thân câu lệnh được thực thi và quá trình sẽ lặp lại từ bước 1.
Ví dụ về câu lệnh while
i = 10;
while( i < 20 )
{
Plot( MA( Close, i ), "MA" + WriteVal( i, 0 ), colorBlack + i );
i = i + 1;
}
Ví dụ trên sẽ vẽ các đường trung bình động (Moving Averages) với các chu kỳ từ 10 đến 19.
Trong ví dụ này, biến i bắt đầu từ 10 và tăng dần cho đến khi giá trị của i đạt 20. Mỗi lần l ặp, một đường trung bình động (MA) với chu kỳ i được vẽ trên đồ thị. Câu lệnh while sẽ tiếp tục thực thi cho đến khi i đạt giá trị 20.
for, câu lệnh for
Từ khóa for được sử dụng để khai báo câu lệnh for.
Câu lệnh for
Câu lệnh for cho phép bạn lặp lại một hoặc nhiều câu lệnh phức tạp một số lần xác định.
Phần thân của câu lệnh for được thực thi từ 0 lần đến nhiều lần cho đến khi điều kiện tùy chọn trở thành sai.
Cú pháp
for ( init-expression ; cond-expression ; loop-expression ) statement
Quá trình thực thi của câu lệnh for diễn ra như sau:
init-expression: Được đánh giá để xác định giá trị khởi tạo cho vòng lặp. Không có hạn chế về kiểu củainit-expression.cond-expression: Được đánh giá trước mỗi vòng lặp. Biểu thức này phải có kiểu số học. Ba kết quả có thể xảy ra:- Nếu
cond-expressionlà đúng (khác không), câu lệnh được thực thi; sau đó,loop-expression, nếu có, sẽ được đánh giá. Quá trình này lặp lại với việc đánh giá lạicond-expression. - Nếu
cond-expressionlà sai (0), quá trình thực thi của câu lệnh for kết thúc và điều khiển chuyển sang câu lệnh tiếp theo trong chương trình.
Ví dụ về câu lệnh for
myema[ 0 ] = Close[ 0 ];
for( i = 1; i < BarCount; i++ )
{
myema[ i ] = 0.1 * Close[ i ] + 0.9 * myema[ i - 1 ];
}
Ví dụ trên lặp qua tất cả các giá trị trong mảng Close để tính toán trung bình động hàm mũ (Exponential Moving Average - EMA).
Sự linh hoạt của câu lệnh for
loop-expression có thể là bất kỳ loại biểu thức nào mà bạn muốn. Bạn có thể tạo ra không chỉ các chuỗi số học thông thường mà còn các chuỗi số học mũ.
Ví dụ:
Tăng giá trị i lên 3 trong mỗi lần lặp:
for( i = 0; i < BarCount; i = i + 3 ) // tăng 3 mỗi lần lặp
Tạo chuỗi số mũ với giá trị i bắt đầu từ 1 và nhân đôi sau mỗi lần lặp:
for( i = 1; i < BarCount; i = i * 2 ) // tạo chuỗi 1, 2, 4, 8, 16, 32, ...
Điều kiện / Điều khiển dòng chảy (Flow control)
if, else
Từ khóa if, else là một phần không thể thiếu trong câu lệnh if-else.
Cú pháp Câu lệnh if, else
if( expression )
statement1
[else
statement2]
Từ khóa if thực thi statement1 nếu biểu thức expression là đúng (khác không); nếu có else và biểu thức là sai (bằng không), thì nó thực thi statement2. Sau khi thực thi statement1 hoặc statement2, điều khiển sẽ chuyển sang câu lệnh tiếp theo.
Ví dụ 1
if ( i > 0 )
y = x / i;
else
{
x = i;
y = abs( x );
}
Trong ví dụ này, câu lệnh y = x / i; được thực thi nếu i lớn hơn 0. Nếu i nhỏ hơn hoặc bằng 0, giá trị của i sẽ được gán cho x và abs(x) sẽ được gán cho y. Lưu ý rằng câu lệnh trong phần if kết thúc bằng dấu chấm phẩy.
Ví dụ 2
if ( i > 0 ) /* Không có dấu ngoặc */
if ( j > i )
x = j;
else
x = i;
Phần else trong ví dụ này được liên kết với câu lệnh if bên trong. Nếu i nhỏ hơn hoặc bằng 0, không có giá trị nào được gán cho x.
Ví dụ 3
if ( i > 0 )
{ /* Với dấu ngoặc */
if ( j > i )
x = j;
}
else
x = i;
Trong ví dụ này, dấu ngoặc bao quanh câu lệnh if bên trong giúp làm cho phần else thuộc về câu lệnh if ngoài cùng. Nếu i nhỏ hơn hoặc bằng 0, giá trị của i sẽ được gán cho x.
Những hiểu lầm phổ biến
Câu hỏi: Tại sao tôi gặp lỗi cú pháp khi viết: if( H > Ref(H,-1) )?
Trả lời: Câu lệnh if-else thay đổi luồng thực thi (ngược lại với hàm IIF vốn đánh giá tất cả các đối số và hoạt động trên mảng) và bạn không thể viết:
if ( H > Ref(H,-1) )
Vì câu lệnh này không có nghĩa. Nó sẽ được hiểu là "Nếu mảng High lớn hơn mảng High bị dịch chuyển một bar". Câu lệnh điều khiển luồng (như if-else) cần một giá trị boolean duy nhất để quyết định luồng thực thi. Nếu bạn viết H (hoặc High), điều này có nghĩa là mảng (toàn bộ mảng). Còn nếu bạn viết H[i] thì đó là phần tử thứ i của mảng. Toán tử chỉ mục [ ] cho phép bạn truy cập vào các phần tử riêng lẻ của mảng.
Thay vào đó, bạn cần viết:
for( i = 1; i < BarCount; i++ )
{
if ( High[ i ] > High[ i - 1 ] )
{
x[ i ] = High[ i ];
}
else
{
x[ i ] = Low[ i ];
}
}
Điều này sẽ dịch thành "cho mỗi bar i, gán phần tử thứ i của mảng High vào phần tử thứ i của mảng x nếu phần tử thứ i của mảng High lớn hơn phần tử trước đó, nếu không thì gán phần tử thứ i của mảng Low vào mảng x".
Với cách cũ, bạn có thể thực hiện điều này trong một dòng bằng cách sử dụng hàm IIF:
x = IIf( High > Ref( High, -1 ), High, Low );
Điều này hoạt động vì IIF làm việc với các mảng như được mô tả trong hướng dẫn.
Tóm tắt:
Như bạn có thể thấy, trong nhiều trường hợp, ngôn ngữ công thức cũ của AFL cung cấp cách viết gọn gàng hơn. Câu lệnh điều khiển mới nên được sử dụng khi nó thật sự mang lại lợi ích. Trong 80% trường hợp, AFL cũ sẽ cung cấp công thức ngắn nhất. Chỉ 20% còn lại cần script, và những trường hợp này giờ có thể được mã hóa trong AFL nhờ các câu lệnh for/while/if-else mới.
switch, case, default
Từ khóa switch là một phần không thể thiếu trong câu lệnh switch. Câu lệnh switch và case giúp kiểm soát các phép toán điều kiện và nhánh phức tạp. Câu lệnh switch chuyển điều khiển đến một câu lệnh trong cơ thể của nó.
Cú pháp Câu lệnh switch, case
switch ( expression )
{
case constant-expression1 : statement;
case constant-expression2 : statement;
...
case constant-expressionN : statement;
default : statement;
}
Điều khiển sẽ chuyển đến câu lệnh có giá trị của case constant-expression khớp với giá trị của switch(expression). Câu lệnh switch có thể bao gồm bất kỳ số lượng case nào, nhưng không được phép có hai giá trị case constant-expression giống nhau trong cùng một câu lệnh switch. Việc thực thi các câu lệnh trong thân câu lệnh bắt đầu từ câu lệnh đã chọn và tiếp tục cho đến khi kết thúc hoặc đến khi có câu lệnh break chuyển điều khiển ra ngoài thân câu lệnh.
Sử dụng break
Câu lệnh break được sử dụng để kết thúc việc xử lý một trường hợp cụ thể trong câu lệnh switch và chuyển đến phần cuối của câu lệnh switch. Nếu không có break, chương trình sẽ tiếp tục đến case tiếp theo, thực thi các câu lệnh cho đến khi gặp câu lệnh break hoặc đến cuối câu lệnh.
Câu lệnh default
Câu lệnh default được thực thi nếu không có case constant-expression nào khớp với giá trị của switch(expression). Nếu câu lệnh default bị bỏ qua và không có case nào khớp, thì không có câu lệnh nào trong thân câu lệnh switch được thực thi. Chỉ có một câu lệnh default có thể tồn tại. Câu lệnh default, nếu có, phải đứng ở cuối. Nếu không, nó có thể được thực thi trước khi gặp các điều kiện ở dưới nó.
Ví dụ
for( n = 0; n < 10; n++ )
{
printf("Current n = %f\n", n );
switch(n) {
case 0:
printf("The number is zero.\n");
break;
case 3:
case 5:
case 7:
printf("n is a prime number\n");
break;
case 2:
printf("n is a prime number\n");
case 4:
case 6:
case 8:
printf("n is an even number\n");
break;
case 1:
case 9:
printf("n is a perfect square\n");
break;
default:
printf("Only single-digit numbers are allowed\n");
break;
}
}
Lưu ý quan trọng
Giá trị của switch expression và case constant-expression có thể là bất kỳ kiểu dữ liệu nào. Tuy nhiên, giá trị của mỗi case constant-expression phải là duy nhất trong thân câu lệnh switch. Nếu không, trường hợp đầu tiên khớp sẽ được sử dụng.
break là cách để tránh việc tiếp tục qua các nhánh case khi không cần thiết, giúp kiểm soát luồng thực thi rõ ràng hơn.
Tham khảo
Để biết thêm chi tiết, bạn có thể tham khảo Wikipedia: Switch statement.
break
Từ khóa break là một phần của câu lệnh switch và có thể sử dụng trong các câu lệnh vòng lặp như for, do-while, và while.
Cú pháp break
break;
Từ khóa break dùng để kết thúc vòng lặp hoặc câu lệnh switch ngay lập tức. Nó chuyển điều khiển đến câu lệnh ngay sau vòng lặp con hoặc câu lệnh switch đó.
Chức năng của break
- Trong vòng lặp: Câu lệnh
breakđược sử dụng để thoát khỏi vòng lặp trước khi điều kiện kết thúc vòng lặp được kiểm tra. - Trong câu lệnh
switch: Từ khóabreakđược sử dụng để kết thúc một nhánh mã của câu lệnhswitch, thường là trước khi gặp nhãncase.
Ví dụ về break trong vòng lặp
i = 0;
while ( i < 10 )
{
i++;
// break ở bước 5
if( i == 5 )
{
break;
}
printf("Bước " + i );
}
Trong ví dụ trên, vòng lặp sẽ in ra các bước từ 1 đến 4, nhưng khi giá trị của i đạt 5, câu lệnh break sẽ được kích hoạt, thoát khỏi vòng lặp.
Tóm lại break
- Sử dụng trong vòng lặp:
breakgiúp bạn thoát khỏi vòng lặp trước khi vòng lặp tự động kết thúc. - Sử dụng trong câu lệnh
switch:breakkết thúc một nhánhcasetrong câu lệnhswitch, giúp tránh việc tiếp tục thực thi các câu lệnh không cần thiết sau khi một trường hợp đã được xử lý.
continue
Từ khóa continue là một phần tùy chọn trong các câu lệnh for, do-while và while.
Cú pháp continue
continue;
Từ khóa continue dừng lại vòng lặp hiện tại và bắt đầu một vòng lặp mới.
Bạn chỉ có thể sử dụng câu lệnh continue bên trong một vòng lặp while, do...while, hoặc for. Khi thực thi câu lệnh continue, vòng lặp hiện tại sẽ bị dừng lại và luồng chương trình sẽ quay lại phần đầu của vòng lặp. Điều này có tác dụng khác nhau tùy theo loại vòng lặp:
-
Vòng lặp
whilevàdo...while: Kiểm tra điều kiện của vòng lặp, và nếu điều kiện đúng, vòng lặp sẽ được thực thi lại. -
Vòng lặp
for: Thực thi biểu thức gia tăng, và nếu điều kiện kiểm tra đúng, vòng lặp sẽ tiếp tục.
Ví dụ về continue trong vòng lặp
i = 0;
while ( i < 10 )
{
i++;
// Bỏ qua bước 5
if( i == 5 )
{
continue;
}
printf("Bước " + i );
}
Trong ví dụ trên, vòng lặp sẽ in ra các bước từ 1 đến 4 và từ 6 đến 10, nhưng khi giá trị c ủa i đạt 5, câu lệnh continue sẽ được kích hoạt, và vòng lặp sẽ bỏ qua bước 5.
Tóm lại continue
-
Sử dụng trong vòng lặp:
continuegiúp bỏ qua phần còn lại của vòng lặp và bắt đầu vòng lặp mới. -
Ảnh hưởng trong các vòng lặp:
-
Trong vòng lặp
whilevàdo...while,continuesẽ kiểm tra lại điều kiện và thực thi vòng lặp nếu điều kiện đúng. -
Trong vòng lặp
for,continuesẽ thực thi biểu thức gia tăng và kiểm tra điều kiện lại để quyết định có tiếp tục vòng lặp hay không.
-
Hàm (Functions)
function: khai báo một hàm
Từ khóa function bắt đầu định nghĩa một hàm do người dùng tự định nghĩa.
Hàm do người dùng định nghĩa cho phép đóng gói mã nguồn của người dùng thành các module dễ sử dụng mà có thể tái sử dụng ở nhiều nơi m à không cần sao chép mã nguồn mỗi lần.
Định nghĩa Hàm
Một hàm phải có một định nghĩa. Định nghĩa hàm bao gồm phần thân hàm — mã nguồn sẽ được thực thi khi hàm được gọi.
Định nghĩa hàm thiết lập tên và các thuộc tính (hoặc tham số) của hàm. Định nghĩa hàm phải xuất hiện trước khi hàm được gọi. Định nghĩa bắt đầu với từ khóa function, tiếp theo là tên hàm, dấu ngoặc đơn mở, sau đó là danh sách tham số tùy chọn, và cuối cùng là dấu ngoặc đơn đóng. Sau đó là phần thân hàm được bao trong dấu ngoặc nhọn.
Lệnh gọi hàm chuyển điều khiển thực thi từ hàm gọi sang hàm được gọi. Các tham số, nếu có, được truyền theo giá trị đến hàm được gọi. Việc thực thi lệnh return trong hàm được gọi sẽ trả về điều khiển và có thể là một giá trị cho hàm gọi.
Nếu hàm không có câu lệnh return (không trả về giá trị gì), thì nó được gọi là một thủ tục (procedure).
Ví dụ về định nghĩa hàm
// hàm dưới đây là bộ làm mượt bậc 2
function IIR2( input, f0, f1, f2 )
{
result[ 0 ] = input[ 0 ];
result[ 1 ] = input[ 1 ];
for( i = 2; i < BarCount; i++ )
{
result[ i ] = f0 * input[ i ] +
f1 * result[ i - 1 ] +
f2 * result[ i - 2 ];
}
return result;
}
Plot( Close, "Price", colorBlack, styleCandle );
Plot( IIR2( Close, 0.2, 1.4, -0.6 ), "function example", colorRed );
Trong đoạn mã trên, IIR2 là một hàm do người dùng tự định nghĩa. Các tham số input, f0, f1, f2 là các tham số chính thức của hàm. Khi gọi hàm, các giá trị đối số được truyền vào các biến này. Các tham số chính thức hoạt động như các biến cục bộ.
Sau đó, chúng ta có các biến result và i là các biến cục bộ. Các biến cục bộ chỉ có thể được nhìn thấy trong hàm đó. Nếu một hàm khác sử dụng cùng một tên biến, chúng sẽ không bị xung đột với nhau.
procedure: khai báo một thủ tục
Từ khóa procedure bắt đầu định nghĩa một thủ tục do người dùng tự định nghĩa.
Thủ tục là một hàm không trả về giá trị nào (không có câu lệnh return).
Tham khảo phần trợ giúp về từ khóa function để biết thêm chi tiết.
return: trả về giá trị từ hàm
Từ khóa return cho phép trả về giá trị từ một hàm.
Ví dụ:
function RiseToAPowerOf2( x )
{
return x ^ 2;
}
Cuối hàm, ta có thể thấy câu lệnh return được sử dụng để trả về kết quả cho hàm gọi. Lưu ý rằng hiện tại câu lệnh return phải được đặt ở cuối hàm.
Tham khảo phần trợ giúp về từ khóa function để biết thêm chi tiết.
local: biến cục bộ
ừ khóa local khai báo biến cục bộ trong hàm do người dùng định nghĩa. Biến cục bộ là biến chỉ có thể được truy cập và sử dụng bên trong hàm đó.
Do AFL mặc định không yêu cầu khai báo biến, quyết định xem biến nào được coi là biến cục bộ hay toàn cục phụ thuộc vào nơi nó được SỬ DỤNG ĐẦU TIÊN.
Tuy nhiên, bạn có thể ép buộc AFL yêu cầu tất cả các biến phải được khai báo bằng cách sử dụng từ khóa local hoặc global trong từng công thức, bằng cách đặt câu lệnh sau ở đầu công thức:
SetOption("RequireDeclarations", True );
Nếu một định danh (biến) được sử dụng đầu tiên BÊN TRONG định nghĩa hàm, thì nó sẽ được coi là biến CỤC BỘ. Nếu một định danh (biến) được sử dụng đầu tiên BÊN NGOÀI định nghĩa hàm, thì nó sẽ được coi là biến TOÀN CỤC.
Hành vi mặc định này có thể được ghi đè bằng cách sử dụng các từ khóa local và global (được giới thiệu từ phiên bản 4.36).
Ví dụ 1: Biến cục bộ và toàn cục
k = 4; // biến toàn cục
function f( x )
{
z = 3; // biến cục bộ
return z * x * k; // 'k' ở đây tham chiếu đến biến toàn cục k (được sử dụng lần đầu ở ngoài hàm)
}
z = 5; // biến toàn cục có tên giống với biến cục bộ trong hàm f
"The value of z before function call :" + WriteVal( z );
// Sau khi gọi hàm
// giá trị của biến toàn cục z
// không bị thay đổi bởi hàm vì
// biến toàn cục z và biến cục bộ z là riêng biệt và
// tham số được truyền theo giá trị (không phải tham chiếu)
"The result of f( z ) = " + WriteVal( f( z ) );
"The value of z after function call is unchanged : " + WriteVal( z );
Ví dụ 2: Sử dụng từ khóa local và global để ghi đè các quy tắc khả năng truy cập mặc định
VariableA = 5; // biến toàn cục
function Test()
{
local VariableA; // biến cục bộ với tên giống biến toàn cục
global VariableB; // biến toàn cục không được định nghĩa trước
// có thể dùng để trả về nhiều giá trị từ hàm
VariableA = 99;
VariableB = 333;
}
VariableB = 1; // biến toàn cục
"Before function call";
"VariableA = " + VariableA;
"VariableB = " + VariableB;
Test();
"After function call";
"VariableA = " + VariableA + " (not affected by function call )";
"VariableB = " + VariableB + " (affected by the function call )"
global: biến toàn cục
Từ khóa global khai báo biến toàn cục bên trong hàm do người dùng định nghĩa. Biến toàn cục là biến có thể được truy cập và sử dụng cả bên trong hàm và bên ngoài hàm (tại cấp công thức toàn cục).
Do AFL mặc định không yêu cầu khai báo biến, quyết định xem một biến được coi là cục bộ hay toàn cục phụ thuộc vào nơi biến đó được SỬ DỤNG ĐẦU TIÊN.
Tuy nhiên, bạn có thể ép buộc AFL yêu cầu tất cả các biến phải được khai báo bằng cách sử dụng từ khóa local hoặc global trong từng công thức, bằng cách đặt câu lệnh sau ở đầu công thức:
SetOption("RequireDeclarations", True );
Nếu một định danh (biến) được sử dụng đầu tiên BÊN TRONG định nghĩa hàm, thì nó sẽ được coi là biến CỤC BỘ. Nếu một định danh (biến) được sử dụng đầu tiên BÊN NGOÀI định nghĩa hàm, thì nó sẽ được coi là biến TOÀN CỤC.
Hành vi mặc định này có thể được ghi đè bằng cách sử dụng các từ khóa local và global (được giới thiệu từ phiên bản 4.36).
Ví dụ 1: Biến cục bộ và toàn cục
k = 4; // biến toàn cục
function f( x )
{
z = 3; // biến cục bộ
return z * x * k; // 'k' ở đây tham chiếu đến biến toàn cục k (được sử dụng lần đầu ở ngoài hàm)
}
z = 5; // biến toàn cục có tên giống với biến cục bộ trong hàm f
"The value of z before function call :" + WriteVal( z );
// Sau khi gọi hàm
// giá trị của biến toàn cục z
// không bị thay đổi bởi hàm vì
// biến toàn cục z và biến cục bộ z là riêng biệt và
// tham số được truyền theo giá trị (không phải tham chiếu)
"The result of f( z ) = " + WriteVal( f( z ) );
"The value of z after function call is unchanged : " + WriteVal( z );
Ví dụ 2: Sử dụng từ khóa local và global để ghi đè các quy tắc khả năng truy cập mặc định
VariableA = 5; // biến toàn cục
function Test()
{
local VariableA; // biến cục bộ với tên giống biến toàn cục
global VariableB; // biến toàn cục không đư ợc định nghĩa trước
// có thể dùng để trả về nhiều giá trị từ hàm
VariableA = 99;
VariableB = 333;
}
VariableB = 1; // biến toàn cục
"Before function call";
"VariableA = " + VariableA;
"VariableB = " + VariableB;
Test();
"After function call";
"VariableA = " + VariableA + " (not affected by function call )";
"VariableB = " + VariableB + " (affected by the function call )"
Kiểu Biến (Variable Type)
static: Biến tĩnh
Từ khóa static cho phép khai báo biến tĩnh.
Cú pháp static
static identifier;
Hoặc:
static identifier1, identifier2, identifier3, ...;
Từ khóa static khai báo biến identifier là một biến tĩnh.
Biến tĩnh đã khai báo có thể và nên được sử dụng như các biến "thông thường", không c ần phải gọi các hàm (Static*).
LƯU Ý QUAN TRỌNG: Từ khóa static chỉ có sẵn khi bạn sử dụng câu lệnh sau ở đầu công thức:
#pragma enable_static_decl(prefix)
prefix là tiền tố được thêm tự động vào tên biến tĩnh thực tế để tránh xung đột tên. Tiền tố này nên là một chuỗi hằng (như trong Ví dụ 1).
Bạn cũng có thể khai báo biến tĩnh với tiền tố duy nhất bao gồm chartID, interval hoặc symbol hiện tại. Để làm điều này, hãy sử dụng các token thời gian chạy {chartid}, {interval} hoặc {symbol} trong chuỗi tiền tố. Chúng sẽ được thay thế trong thời gian chạy bằng các giá tr ị tương ứng (xem Ví dụ 2).
Ví dụ 1: Khai báo biến tĩnh với tiền tố cố định
// pragma dưới đây là yêu cầu để kích hoạt hỗ trợ cho khai báo tĩnh
// nó cũng định nghĩa tiền tố được thêm vào các biến khai báo bằng từ khóa static
// chỉ một tiền tố cho mỗi công thức.
#pragma enable_static_decl(prefix)
// Đây là một ý tưởng tốt để sử dụng quy tắc đặt tên nhất quán
// giúp phân biệt các biến tĩnh đã khai báo với các biến khác
// Chúng tôi khuyên bạn nên sử dụng dấu gạch dưới '_' trước tất cả các biến tĩnh đã khai báo
// để dễ dàng nhận diện trong mã nguồn
// Một lựa chọn khác có thể là tiền tố `s_`
static _myvar; // biến này cũng có thể được truy cập bằng "prefix_myvar"
printf( "Biến này thực sự là tĩnh %g", _myvar++ );
// Hãy nhớ rằng, để tăng tốc độ, biến tĩnh chỉ được đọc một lần khi khai báo
// và chỉ được lưu một lần - khi công thức thực thi xong
// Cách này giúp các biến tĩnh khai báo có cùng tốc độ với các biến thông thường (không có sự phạt tốc độ)
Ví dụ 2: Khai báo biến tĩnh theo chartID
// Ví dụ 2 - nếu bạn muốn khai báo biến tĩnh theo `chartID`
#pragma enable_static_decl "myprefx{chartid}"
static x; // biến tĩnh này thực sự sẽ có tên là myprefixIDx, trong đó ID là chartID hiện tại
typeof: Kiểu dữ liệu của một biến
Toán tử typeof được sử dụng để xác định kiểu dữ liệu của một toán hạng. Cú pháp như sau:
typeof(operand)
Toán tử typeof trả về một chuỗi chỉ ra loại của toán hạng chưa được đánh giá. Toán hạng có thể là chuỗi, biến, định danh hàm, hoặc đối tượng mà bạn muốn xác định loại.
Khi cung cấp định danh, nó phải được cung cấp một cách độc lập, không có các toán tử số học, không có đối số bổ sung và không có dấu ngoặc.
Nếu bạn muốn kiểm tra loại của giá trị trả về bởi một hàm, bạn phải gán giá trị trả về đó cho một biến và sau đó sử dụng typeof( biến ).
Các giá trị trả về có thể có:
- "undefined" - định danh chưa được định nghĩa
- "number" - toán hạng đại diện cho một số (scalar)
- "array" - toán hạng đại diện cho một mảng
- "string" - toán hạng đại diện cho một chuỗi
- "function" - toán hạng là một định danh hàm tích hợp
- "user function" - toán hạng là một hàm do người dùng định nghĩa
- "object" - toán hạng đại diện cho một đối tượng COM
- "member" - toán hạng đại diện cho phương thức thành viên hoặc thuộc tính của đối tượng COM
- "handle" - toán hạng đại diện cho Windows handle
- "unknown" - loại của toán hạng không xác định (không nên xảy ra)
Toán tử typeof cho phép, trong số các chức năng khác, phát hiện các biến chưa được định nghĩa theo cách sau:
if( typeof( somevar ) == "undefined" )
{
// khi somevar chưa được định nghĩa, mã này sẽ được thực thi
}
Đoạn code mẫu sau đây hiển thị kết quả của hàm typeof() trong một số tình huống phổ biến:
printf( typeof( test ) + "\n" ); // biến chưa được định nghĩa
printf( typeof( 1 ) + "\n"); // số nguyên (literal number)
printf( typeof( "checking" ) + "\n"); // chuỗi (literal string)
printf( typeof( x ) + "\n"); // biến kiểu mảng (array variable)
printf( typeof( y ) + "\n"); // biến kiểu số (scalar variable)
printf( typeof( MACD ) + "\n"); // định danh hàm (function identifier)
printf( typeof( testfun ) + "\n" ); // định danh hàm người dùng (user function identifier)