Weak Typing
MATLAB is a loosely or weakly-typed language, as well as being dynamically typed, which has a number of real-world implications. The first, and probably most notable, difference between MATLAB and a strongly-typed language is that you never have to explicitly declare the types of the variables you use. For example, the declarations x=5; x='foo' immediately following one another are perfectly acceptable; the first declaration causes x to be treated as a number, the second changes its treatment to a string.
While using a weakly-typed language allows for the ability to do rapid prototyping by reducing the number of lines of code required to declare and use values, functions, and even classes, there are certain perils to be aware of. Most notably, weak, dynamic typing can cause issues when re-using code or changing it. Strongly statically typed programming languages that allow for generic programming, such as Haskell or, to a certain extent, Java and C++, allow the same benefits as a weakly typed language in terms of allowing code to be re-used for values of different types, but only for types that make sense; weakly-typed languages cannot check this, which may give rise to runtime errors.
The fact that MATLAB is a scripted instead of a compiled language also improves the ability to perform rapid prototyping as there is no need to wait for the compiler to check your code. However, given that runtime errors become much more likely, it is important to test your code more thoroughly, and to come up with small datasets to try out so that you can test the code quickly and not have a simulation crash many hours or days into execution. This dynamic between statically and strongly typed languages (like C++ and Haskell) and weakly typed languages such as MATLAB, is another reason that one might want to take advantage of both styles and use the information about FFI APIs discussed in prior sections.
Another pitfall encountered with weak typing involves unexpected user input, which can lead to erroneous results; this can be largely addressed by writing dynamic (runtime) checks on the input (similar to what was done in the exercise), as well as tests. Note that the exercise was in C, which is a statically typed language, but not very strongly typed, so it suffers some of the same pitfalls.
One place where MATLAB differs (perhaps unexpectedly) from third-generation languages like C and FORTRAN is in its treatment of integer scalar variables. Because of MATLAB's weak typing system, it can't distinguish between integer and floating point values so it treats all scalars in the most general way possible--as floating point variables. If you divide 5 by 4 the result in MATLAB is 1.25; in C/FORTRAN it would be 1.
>> x=5;
>> y=4;
>> x/y
ans = 1.2500
However, for integer types, there is a little-known way to be much more specific, and use the same signed and unsigned integers that e.g. C has available. This can be achieved by using a conversion function like 'int#bits' for signed integers or 'uint#bits'; for instance, below we use the 'int8' function to create 8-bit integers, and note that the same division is truncated.
>> x_i8 = int8(4)
x_i8 =
int8
4
>> y_i8 = int8(4)
y_i8 =
int8
4
>> x_i8/y_i8
ans =
int8
1
Now what do you think would happen if you did 'x_i8/y' or 'x/y_i8'? In strongly typed languages this would not typically work without an explicit cast, so it is important to know what to expect in dynamically typed languages like MATLAB.
This leads into another situation where weak typing can lead to unexpected results: with operations between completely unrelated mixed types. Consider what happens when you add 1+'1', that is, the scalar 1 and the character '1'. The surprising result is 50. MATLAB automatically converts the character '1' to its ASCII representation, which is 49 (You can get the ASCII code for any character using the abs() function). After this implicit conversion, MATLAB adds the scalar value of 1 to return 50. While this example is somewhat contrived it can easily arise, especially when passing a function argument where the type is undetermined. Again, to write completely safe weakly-typed code, user input should always be checked before performing operations on it.
>> x=1;
>> y='1';
>> x+y
ans =
50
To see how MATLAB's weak typing combines with its automatic vector operations, we consider a second example, the operation 10+'10'. Here the abs() function first operates on '10', but since it is a string of characters instead of a single character, MATLAB's automatic array operations are used. The abs() function is applied to each character in the character string individually. This results in the array [abs('1') abs('0')] or [49 48]. MATLAB then adds the scalar value 10 to each entry in the array resulting in an array answer of [59 58]. Certainly an unexpected result if (as the code seems to intend) the user was expecting 20 to be returned.
>> x=10;
>> y='10';
>> x+y
ans =
59 58
Not all of MATLAB's built-in operators are necessarily intuitive to users of other dynamically, weakly typed programming languages. In Python (another popular weakly-typed language used for scientific programming), string concatenation is done with the '+' operator when two character string operands are passed to it. MATLAB converts both character strings to numerical arrays containing the ASCII values of the respective character entries, and then adds those arrays together. 'Hello' + 'World' becomes [159 212 222 216 211], not the concatenated string 'HelloWorld'. If the user tries to "add" two character strings having different lengths, MATLAB will report the error message: "Matrix dimensions must agree." Assuming the user's intent was to concatenate strings, this message won't make much sense.
>> 'Hello' + 'World'
ans =
159 212 222 216 211
Since functions can be passed any type of argument, it is important to ascertain what types are being passed before using them. MATLAB provides a number of 'is???()' functions to help. Some examples include isnumeric(), iscell(), iscellstr(), ischar(), isempty(). Where possible, use built-in MATLAB functions. These functions have been designed to work with multiple input types and will throw errors when used with an unrecognized type. You can also use the class() function to get a character array that tells you the type of a value or the type of elements in an array; for instance, class(x) would give 'double' above, but class(x_i8) would give 'int8'.