When scalar becomes an array, aka. type coercion in AFL

Since the subject of data types surfaced in this thread: Send orders to IB on next bar (Intraday)

Here are some comments regarding data types in AFL.

While some users who familiarized a bit with array handling in AFL may think that everything is an array in AFL, that is not the case.

The data type depends on value assigned to variable. If you assign scalar (number) the variable type will be scalar (floating point number, 4 bytes long).

So if you assign a number to variable like this:

var1 = 6; // var1 is scalar, NOT an array, consumes just single float value (4 bytes)

AmiBroker automagically does transformations for you so you don't need to worry BUT at the same time it always tries NOT to use/allocate array when it is not needed. For example if you write

level = 50; // level is NOT array, it is scalar (4 bytes)
Buy = Close > level; // here array is compared to SCALAR, resulting in True/False Buy array

AmiBroker allows you to mix arrays and scalars in expressions doing all the work for you:

var1 = (LastValue( High ) + LastValue( Low ))/2; // var1 will be SCALAR (4 bytes)
var2 = var1 + Close; // adding scalar to array gives array
// var1 is still scalar (it is NOT converted to array)

AmiBroker allows you to use scalar everywhere where you can use array. AmiBroker has polymorphic functions like IIF that return different types depending on types of inputs, like this:

result1 = IIF( LastValue( Close > Open ), 7, 5 ); // result1 will be SCALAR value 7 or 5 depending on just last bar condition
result2 = IIF( Close > Open, 7, 5 ); // result2 will be array of values 

As you can see same function IIF returns scalar or array depending on inputs.

Thanks to ability to treat scalar as arrays when array type is expected, AmiBroker will allow you to use subscript on variable that is scalar

var1 = 5;
printf("%g", var1[ 0 ] ); // even though var1 is scalar you still can treat it as array
// var1 will still be scalar 

AmiBroker does not allocate memory for array until it is absolutely necessary.

Only if you WRITE to individual element, AmiBroker will convert the type:

var1 = 5;
printf("%g\n", var1[ 0 ] ); // even though var1 is scalar you still can treat it as array
var1[0] = 6; // now var1 becomes array (because of assignment of individual element)

Once variable is upsized to array, it stays so (at least until you overwrite it with some other value).

Generally all the above details are not that important for 'regular' user. The only situation when scalar vs array becomes important is when somebody tries to use array in flow control statements. Flow control statements require scalar values to make the decision (conditional jump) as explained in http://www.amibroker.com/guide/a_mistakes.html

22 Likes

Very, very good explanation.
I think that there's only one detail missing: Arrays in Amibroker always have BarCount elements, i.e., in the last example, the assignment

var1[0] = 6;

creates an array with BarCount values, beginning with var1[0] and ending with var1[BarCount-1].

1 Like

No, LeoCV is correct.

var1 becomes an array with size BarCount and first element holding 6.

LeoCV did not mean that var1 creates a copy of BarIndex() function. He meant that size of var1 is BarCount and array subscripts going from 0 to Barcount-1.

Do yourself a favour and get the type of var1 yourself.

var1[0] = 6;
printf( "type of var1: %s", typeof(var1) );

726


On the other hand a var2 such as this one is of type number.

var2 = 6;
printf( "\ntype of var2: %s", typeof(var2) );

422

6 Likes

Yes @LeoCV was right. Classic one-dimensional arrays in AFL have BarCount elements. Matrices (that technically - under the hood - are just arrays with 1 or 2 dimensions) can have any size.

2 Likes

@fxshrat and @Tomasz you are right, I did misunderstood when @LeoCV wrote "BarCount values".

I hope someone can delete my post, it is a waste that may needlesly confuse someone (like me).

EDIT: Ha! It was easy for me to delete it.

Thanks @fxshrat,

I was coding something the other day, and needed to know whether the variable was a scalar or array, and couldn't find a suitable function by searching AB help, so I created the following:

// -----------------------------------------------------------------------------
		function IsScalar(inpExpr)
/* 
Determine whether the expression is a scalar (constant) or not, ie. the value is the same for
every element of the array.
*/
// -----------------------------------------------------------------------------
{
	// By comparing the current value with the prior one, and doing that for all elements of the array
	// we can then determine whether the value is constant over time.
	tmpA	= Ref(inpExpr, -1) ;
	tmpA[0]	= inpExpr[0] ;
	return LastValue(Cum(tmpA == inpExpr)) == BarCount ;
}

, but it looks like typeof() would have been better, and I obviously didn't search hard enough. :blush:

Does AFL support character arrays?

var1 = 5;
printf("%g\n", var1[ 0 ] ); // even though var1 is scalar you still can treat it as array
var1[0] = 6; // now var1 becomes array (because of assignment of individual element)

var2="Sell";
var2[0] = "Buy";   // <<< type mismatch
var2[1] = "Sell"; 
var2[2] = "Buy"; 

No, see why not.
But to do what you intend to do (output of Buy/Sell text in Exploration column) you may use AddMultiTextColumn.

1 Like

YES it does. Character array is a STRING.

string_is_an_array_of_characters = "That is in fact array of characters";

In addition to strings, you can also have literal arrays filled with character (ASCII code) values like this

// an array that holds numerical values of character codes
array_of_character_codes[ 0 ] = 'a'; // that is an ASCII character, not string
array_of_character_codes[ 1 ] = 'b'; // ditto, note single quote (') usage

But your example code is NOT about character arrays. Your example is about array of arrays of characters, i.e. arrays of strings. This is different from what you asked in first sentence. As @fxshrat already pointed out, you can get tables/arrays of strings using OSAKA plugin (Arrays of strings - #2 by Tomasz) or you can easily achieve the same with new-line separated list of strings

1 Like

@LinusVanPelt,

Sorry, my response was a bit lazy post.

When I wrote

I referred to your code example showing try of creating array of strings (array of character arrays).


So to not confuse here is more precise response:

Yes, AFL does support character arrays as pointed out by @Tomasz.

But no, it does not support to create array of character arrays (array of strings) as you tried to do in your code example, see why not (and alternatives) .

2 Likes