Weakly Typed Languages
Written by Nikos Vaggalis   
Wednesday, 03 November 2010
Article Index
Weakly Typed Languages
VB.NET weak typing
Problems from static typing

 

VB.NET

Let’s take a look at this string and integer addition example from a VB.NET perspective.

Example 6

Module Module1
Sub Main()
Dim a As String = "10"
System.Console.Write(20 + a)
End Sub
End Module

String "10" was implicitly converted to number 10 since the operation was expecting an integer and VB acted weakly typed.

 

Example 7

Now let’s turn “10” into “10a” and observe. It does compile successfully but at the same time throws an exception at runtime:

Module Module1
Sub Main()
Dim a As String = "10a"
System.Console.Write(20 + a)
End Sub
End Module

This produces an exception of type

'System.InvalidCastException' occurred in Microsoft.VisualBasic.dll

Conversion from string "10a" to type 'Integer' is not valid.

The VB compiler checks the types of both variables at compile time since it has the luxury of having this information (since it is a statically typed language) and finds that the expression is comprised of a string, an integer, the "+" operator. The "+" operator works in numeric context hence the string must be converted to an integer. The compiler then looks for a designated built-in type converter and gathers that a string can be converted to an integer implicitly. Hence the operation is deemed to be successful.

However, what it cannot check until runtime is whether the actual value of the string can be converted to a number. Thus while the string "10a" passed the type safety check at compile time, it throws an exception at runtime since "10a" cannot be converted to a number.

We have just introduced a loophole into VB’s type system; although the type check passed at compile time as viable it blew up at runtime.

Which brings us back to the earlier equivalent Perl example where the interpreter when faced with a similar situation had to make a choice; in this case Perl would just turn “10a” into “10” when VB would throw an exception. This is a demonstration that a conversion could fail even in a weakly typed language.

This is an example of implicit conversion; implicit conversion has the notion of working on unrelated types as we just witnessed. We used a string and a number and depending on the context of the operation one was implicitly converted to a data type necessary for the expression to evaluate successfully.

Danger of implicit conversion

Implicit conversions might be a blessing since they provide flexibility and agility as long as you know what you are doing and what to expect. If you don't, then you might be getting face to face with potential pitfalls as the following example will demonstrate.

This is a situation that I encountered myself and is one of the most common issues faced when working with a weakly typed language.

The following is a snippet from a Perl program which calls a module and expects a return value (stored into variable $result) back from the module. It then uses that value in an if statement as to make a decision based on it :

if ($result == ERAR_CHAIN_FOUND) {
#do something
}
elsif   ($result == ERAR_ECREATE) {
#do something
}
elsif ( $result  eq ERAR_MULTI_BRK) {
#do something;
}

ERAR_CHAIN_FOUND, ERAR_ECREATE and ERAR_MULTI_BRK are constants which are imported from the module into the caller and are checked against the $result variable which contains the return value coming off the module.

The problem here lies in that a constant is a scalar value and hence in Perl it can contain either a string or a number hence it can be compared to either data type:

ERAR_CHAIN_FOUND =>
 'found in chain.already processed'
ERAR_ECREATE   => 16
ERAR_MULTI_BRK = >
'multipart but first volume is broken'

The first constant is bound against a string, the second one against a number and the third one against a string.

When the module was returning ERAR_MULTI_BRK (string value 'multipart but first volume is broken') into $result, its relevant ‘if’ block was not being entered and instead the first block

if ($result == ERAR_CHAIN_FOUND) 

was being entered every time!

Initially I did not realize the real reason behind that was behind the behavior and started doing code revision until I realized that the correct ‘if’ block should be :

if ($result eq ERAR_CHAIN_FOUND)

instead of

if ($result == ERAR_CHAIN_FOUND)

Since $result can be either a number or a string, the implicit conversion is dictated by the operator. Thus when $result with the value 'multipart but first volume is broken' is returned and the first block in sequence is checked "if ($result == ERAR_CHAIN_FOUND)" or interpolated "if ('multipart but first volume is broken'

== 'found in chain. already processed')"  the == operator, which works in numeric context , would turn both operands into zeros for the expression evaluation to succeed, thus "if (0==0)" is always true.

By turning the operator from == to eq, which is the correct operator when comparing strings, the issue was resolved; now when ERAR_MULTI_BRK is returned the first block returns false and the correct block is entered.

So the correct code is :

if ($result eq ERAR_CHAIN_FOUND) { 
#do something
}
elsif   ($result == ERAR_ECREATE) {
#do something;
}
elsif ( $result  eq ERAR_MULTI_BRK) {
#do something;
}

It’s one of those issues that can bite you with weakly typed language and again it comes down to DWIM (Do What I Mean) when of course you know what you mean!

<ASIN:1430225491>

<ASIN:143022455X>

<ASIN:0596800959>



Last Updated ( Friday, 09 November 2012 )