Programming Type Systems

If you are a programmer who has worked with multiple programming languages, you must have noticed that while some languages, such as Java and C++, use almost similar methods to define their data types, while others, such as Python and Matlab, use completely different methods. This is because those two groups of languages use different type systems.

A type system is defined as tractable syntactic framework for classifying phrases according to the kinds of values they compute. It associates types with each computed value, and, by examining the flow of these values, attempts to prove that no type errors can occur. A type system generally seeks to guarantee that operations expecting a certain kind of value are not used with values for which that operation makes no sense.

Ok, in simpler words, a type system is a way for programming languages to classify values and expressions into types, how it can manipulate those types, and how they interact. Or, in even simpler terms, how data types are assigned to variables, and how they are handled. There are four type systems that programming languages can adopt. ANY programming language you know or have worked with, except two languages, belongs to at least two of the following categories:

Statistically-typed languages: languages in which data types are fixed at compile time, in other words, type checking (verification) is done when the code is compiled. Languages that use static typing include C++, Java, C#, and F#. These languages enforce this by requiring the programmer to explicitly declare all variables with their data types before use. An example of this is the floating point variables declaration in Java:

float f = 1.0f;

Static typing allows data type errors to be caught earlier in the development cycle. Besides verifying data types, static type checkers verify that the checked conditions hold for all possible executions of the program, which eliminates the need to repeat type checks every time the program is executed. Program execution may also be made more efficient by omitting runtime type checks. However, static typing can sometimes reduce code flexibility.

Dynamically-typed languages: languages in which the majority of its type checking is performed at run-time instead of checking at compile-time. Languages that use dynamic typing include JavaScript, PHP, Python, and Tcl. In dynamic typing, the values have types, not the variables; that is, a variable can refer to a value of any type. An example of this in Python:

x = 1
print x
x = "Hello, world!"
print x

This code would produce no errors and print “1” and “Hello, world!” By allowing programs to generate types and functionality based on run-time data, dynamic typing can be more flexible than static typing. However, dynamic typing may result in runtime type errors; at runtime, a value may have an unexpected type, and an operation nonsensical for that type is applied. Also, this operation could occur long after the place where the wrong type of data passed into a place it should not have, which makes the bug difficult to locate.

One thing to notice is that a dynamically-typed language is not necessarily a dynamic language. The term dynamic language means something different, but more on that later. (In a separate post, maybe? ;))

Strongly-typed languages: languages in which data types are always enforced. A data type cannot be treated like another unless it is explicitly converted. Strongly typed languages, such as C, Java, Pascal, and Python specify severe restrictions on how operations involving values having different data types can be intermixed, preventing the compiling or running of source code which uses data in what is considered to be an invalid way, e.g. the division of an inter over a string. To ensure they achieve their purpose, strongly-typed languages apply some or all of the following constraints:

  • The compiler must ensure that operations occur only on operand types that are valid for the operation.
  • An error must occurs as soon as a type-matching failure happens at runtime, or, as a special case of that with even stronger constraints, type-matching failures must never happen at runtime
  • Omitting implicit type conversions- conversions that are inserted by the compiler on the programmer’s behalf.
  • The type of a given data object does not vary over that object’s lifetime.
  • Type conversions are allowed only when an explicit notation, often called a cast, is used to indicate the desire of converting one type to another.
  • Disallowing any kind of type conversion. Values of one type cannot be converted to another type, explicitly or implicitly.

For example, an attempt to add an integer and a string in Python:

x = 1
y = "Hello, world!"
print x + y

will produce the error:

TypeError: unsupported operand type(s) for +: ‘int’ and ‘str’

Weakly-typed languages: languages in which types may be ignore. Weakly-typed languages support either implicit type conversion, ad-hoc polymorphism (overloading) or both. For example, adding an integer and a string in Matlab:

x = 1;
y = 'Hello, world!';
z = x + y

will not produce any error, actually it will produce the result:

z =    73   102   109   109   112    45    33   120   112   115   109   101    34

One last thing I want to talk about is type safety. Type safety can be defined as the use of a type system to prevent certain erroneous or undesirable program behaviour. This can be achieved statically, by catching potential errors at compile time, or dynamically, by associating type information with values at run time and consulting them as needed to detect imminent errors, or using combination of both. A programming language is called “type-safe” if it does not allow operations or conversions that lead to erroneous conditions, such as the previous Python example.

Remember when I said at the beginning of this post that all programming languages, adopt at least two of the four typing schemes, except two languages? Those two languages are the Assembly Language and Forth. Those two languages have been said to be untyped. There is no type checking. It is up to the programmer to ensure that data given to functions is of the appropriate type. Any type conversion required is explicit.

Share

Advertisements

Things That Not All Programmers Know #2: Handling Mouse Wheel In JavaScript

Everyone who has been on the Web even a little knows the importance of the use of mouse wheels, scrolling pages, zooming in Google Maps, mouse wheel gestures in Opera 9 browser, and many more. It is almost impossible now to find a mouse without wheel. However, not many Web applications’ developers know how to make smart use of mouse wheel. Therefore, I decided to make this little tutorial to provide general information on how to handle mouse-wheel-generated events in JavaScript.

There are some images that are not very clear because of page size limitations. You can click on any image to see it in full size.

First, the thing you should know about mouse wheels is that they do not have an absolute system. Therefore, the only way to capture the wheel actions is via a parameter called delta, which is the mouse wheel angle changes. The delta parameter takes positive and negative values; if the wheel is scrolled up- which means the page is scrolled down- delta is positive, if the wheel is scrolled down- which mean the page is scrolled up- delta is negative. The handle function takes on that delta parameter. This function should be modified by you to handle the wheel actions:

High Level Function

The actual values of delta depend on the sensitivity of the mouse. However, for optimization, the code is adjusted so that the values of delta are either -1 or +1. Also note that delta takes different values between the Internet Explorer, Opera, and Mozilla Firefox browsers. For example, in Opera and Firefox, delta takes a different sign than that of Internet Explorer, and in Firefox, the value of delta is always a multiple of 3. Here is the event handler code:

Event Handler Function

The following part is optional. This piece of code is to prevent the default actions caused by the mouse wheel. You may want to do that because you are already handling scrolls somehow:

Handling Default Actions

The initialization code:

Initialization Code

And that is it. Now you can handle mouse wheel actions easily anyway you want using the handle function. Note that this code has been tested only with recent versions of Internet Explorer, Mozilla Firefox, Opera, and Safari browsers. I have no idea if it will work with other browsers or not.

Hope this was useful. I would really love it if you tried it and sent me your feedback. And again, if you know a good programming trick that you believe not many people know, please let me know. Wait for a new programming trick next month. Until then, happy coding!

Things That Not All Programmers Know #1: Cyclic Inheritance

It has been a month since launching Significant Insignificance last October. Before anything I would like to thank everyone who cared enough to visit my blog and read what may seem to others nothing but insignificant thoughts. I hope you enjoyed reading it as much as I enjoyed writing it and promise more of the same.

Today, I decided to add a new series to my blog: “Things That Not All Programmers Know”. To make sure that I always write technical posts, on the first day of every month, I am going to post something (a trick, a tip, a best practice) related to programming that I believe not many young programmers know. This way, everyone- including me- gets to learn something new.

I am going to start this series with something relatively easy: Cyclic Inheritance. First, the definition:

If a class or interface inherits from itself, even directly (i.e., it appears as its super-class or in its list of super-interfaces) or indirectly (i.e., one of its super-class or one of its super-interfaces inherits from it), a cyclic inheritance error is reported.

Ok, this needs an example, consider the following code:

When trying to compile it, you get the error: “cyclic inheritance involving Person“.

This is cyclic inheritance; each class inherits the other: Employee is the subclass of Person, and Person is the subclass of Employee. This relationship is not possible.

Cyclic inheritance can be solved by determining the proper relationship; that is, finding out the right super class and the subclass. In the previous example, Person is the super class, so it should not try to inherit Employee and Employee is the subclass which will inherit Person. Correction is removing “extends Employee” from the Person class signature:

Hope this was useful. If you know any unique programming trick (Java or others) that you believe not many people know, do not hesitate to contact me. And again, for everyone who followed my blog throughout the previous month, thanks a lot for your dedication. This blog would not be alive if it weren’t for your support. Thank you.