Are You Scared of Strongly Typed Languages?

Part 1: Why do types matter?

I realize that the ratio of Senior Devs to Junior Devs is very low, especially in web development. This lack of senior leadership shows in a lot of technology decisions made on web projects. This is just an opi…


This content originally appeared on DEV Community and was authored by The Sharp Ninja

Part 1: Why do types matter?

I realize that the ratio of Senior Devs to Junior Devs is very low, especially in web development. This lack of senior leadership shows in a lot of technology decisions made on web projects. This is just an opinion that is cultivated by starting as a web developer in 1995 and doing just about every kind of project since then with startups to global industry powerhouses.

One constant has been the usage of languages with strong typing increases with the maturity of the dev team, and especially its leadership. I have also been doing C# for over 20 years continuously, so I've never worked anywhere that allowed Node or Python or Ruby to be used on the back end, although I have done a lot of projects mixing C# and JavaScript and even VBS and JavaScript for over two decades. When I got a chance to learn Angular a few years ago it was the first time I felt productive on doing web dev because types mean something with TypeScript.

Like most guys of my vintage, my first programming forays were with Microsoft BASIC, a language that is arguably more important than C in the history of computing because for most of GenX, having a home computer meant having a Commodore brand computer. All of Commodore's 8-bit computers used a boot ROM that had the Kernel, Screen Manager, and Microsoft BASIC built into it. I'm calling it Microsoft BASIC even though the boot banner says Commodore Basic. The reason is that in the 1970's, Jack Tramiel, CEO of Commodore Business Machines, solicited a contract with Bill Gates to provide the operating system for Commodore's first computer, the PET 2001. Tramiel was a hard negotiator and secured rights to replicate that Operating System on as many computers as he wanted for $50,000. This deal made Microsoft a viable company, but Commodore would go on to include this OS on nearly 30,000,000 computers. So, just out of respect for the work that Bill and Paul Allen did, I'm calling it Microsoft BASIC.

Anyways, MS BASIC was a Strongly Typed language, despite being interpreted.

10 DIM A%: A% = 1
20 DIM B: B = 1.0
30 DIM C$: C$ = "1"
40 DIM D%(10)
50 DIM E(10)
60 DIM F$(10)

Here we have the who range of types supported by MS BASIC.

  • Line 10: A% is an integer initialized with 1
  • Line 20: B is a floating point initialized with 1.0
  • Line 30: C$ is a string initialized with "1"
  • Line 40: D%(10) is an integer array of 10 elements
  • Line 50: E(10) is a floating point array of 10 elements
  • Line 60: F$(10) is a string array of 10 elements

This was all the types available, and there were not structures of any kind. We learned to code with a minimum palette of types and some phenomenal results happened, including many commercial games.

If you tried to assign a number directly in a string you would get an error.

Cannot place number in string.

What this does is teaches you how to be intentional.

image

Being intentional is a way of thinking where you make decisions based on the outcome you intend to happen. In other words, you have a plan.

So, when I'm writing my program, my intention is to store the number 3.1417 into a variable named PI. 3.1417 is a floating-point number, so I don't need to add any modifiers to the variable name:

10 DIM PI: PI = 3.1417

For better, or for worse, MS BASIC was lenient about placing floating point values into an INTEGER. It would not complain at all, but unless it was intentional, you wouldn't like the outcome.

Does that Circumference look correct?

Uh oh, our circumference is wrong because we were not intentional in our actions and placed the value in the wrong type. Fortunately, modern languages warn about loss of data when putting a float in an integer, but in the 1970's and 1980's, that wasn't a thing.

However, we see our error right away and easily fix it.

Now the Circumference is correct.

Looking at this example, you may think, "Dynamic typing solves that problem." But does it? Let's look at some examples of being unintentional with a dynamically typed language.

for(let i = 0; i !== 3; i += 1.1) {
    console.log(i)

    if(i > 3) 
    {
        console.log("Could match not i to 3!")
        break
    }
}
/* results

0
1.1
2.2
3.3000000000000003
Could match not i to 3!

*/

Here we initialize our loop counter i with an integer. And for the first iteration, it is an integer. But then things go off the rails when I accidentally add a float to the integer and store the result back into the counter. Now my counter is a float. Worse, it can never match our exit criteria for the for loop, meaning this would run forever! This is the worst possible result because the user interface would be locked up if we are on the main thread and would have no way to know what's happening until the number overflows the variable, which would take a very long time.

These are the reasons that being intentional in your code are so important. We are all human, so we will have lapses in our intentional processes, and when that happens, strongly typed languages help us prevent these kinds of bugs.

The Grandaddy of most Typed Languages is C. What does this code do in C?

#include <stdio.h>

int main()
{
    for(int i = 0; i != 3; i += 1.1) {
        printf("i: %i \n", i);

        if(i > 3) 
        {
            printf("Could match i to 3!");
            break;
        }
    }

    return 0;
}
/*

i: 0 
i: 1 
i: 2 

*/

Here we see that C has helped us stay intentional through strictly adhering to the specified type, just like MS BASIC did when we used integer to hold circumference.

Newer languages, such as C# 9, go even further.

using System;

public class Program
{
    static void Main()
    {
        for(int i = 0; i != 3; i += 1.1) 
        {
            Console.WriteLine($"i: {i}");

            if(i > 3) 
            {
                Console.WriteLine("Could match i to 3!");
                break;
            }

        }
    }
}

Compiling this results in:

Compilation error (line 7, col 29): Cannot implicitly convert type 'double' to 'int'. An explicit conversion exists (are you missing a cast?)

Now we have no chance to introduce a bug based on going from floating point to an integer because C# treats any data loss as an error.

fn main() {
    let mut i:i32 = 0;

    loop {
        println!("i: {0}", i);

        i += 1.1;

        if i == 3 {
            break;
        }           
    }
}

Here we have the Rust version of this loop. Like, C#, Rust is concerned with data hygiene and throws an error trying to compile it.

error[E0277]: cannot add-assign `{float}` to `i32`
 --> main.rs:7:5
  |
7 |         i += 1.1;
  |           ^^ no implementation for `i32 += {float}`
  |
  = help: the trait `std::ops::AddAssign<{float}>` is not implemented for `i32`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.
exit status 1

The error is different because the philosophies of the languages are different. In C#, the compiler is strictly saying that it won't automatically convert a double to an int. Period. Rust, on the other hand, simply doesn't implement a language feature that could have resulted in an error, so you are notified that that specific use case is intentionally not implemented.

If I change to using i = 1.1 in Rust, a different error occurs.

error[E0308]: mismatched types
 --> main.rs:7:7
  |
7 |         i = 1.1;
  |             ^^^ expected `i32`, found floating-point number

error: aborting due to previous error

For more information about this error, try `rustc --explain E0308`.
exit status 1

Rust is now telling use error[E0308]: mismatched types because Rust considers ints and floats to be fundamentally distinct types. And if there's not any implementation of std::ops::AddAssign<T> that matches the type for 1.1, then the expression is simply invalid and cannot be compiled. It's impossible to get this bug into production with either C# or Rust.

Next time we'll look at some of the typed-vs-untyped arguments and try to place them into context from the perspective of the Senior Developer with Unpopular Opinions.


This content originally appeared on DEV Community and was authored by The Sharp Ninja


Print Share Comment Cite Upload Translate Updates
APA

The Sharp Ninja | Sciencx (2021-08-24T14:13:57+00:00) Are You Scared of Strongly Typed Languages?. Retrieved from https://www.scien.cx/2021/08/24/are-you-scared-of-strongly-typed-languages/

MLA
" » Are You Scared of Strongly Typed Languages?." The Sharp Ninja | Sciencx - Tuesday August 24, 2021, https://www.scien.cx/2021/08/24/are-you-scared-of-strongly-typed-languages/
HARVARD
The Sharp Ninja | Sciencx Tuesday August 24, 2021 » Are You Scared of Strongly Typed Languages?., viewed ,<https://www.scien.cx/2021/08/24/are-you-scared-of-strongly-typed-languages/>
VANCOUVER
The Sharp Ninja | Sciencx - » Are You Scared of Strongly Typed Languages?. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2021/08/24/are-you-scared-of-strongly-typed-languages/
CHICAGO
" » Are You Scared of Strongly Typed Languages?." The Sharp Ninja | Sciencx - Accessed . https://www.scien.cx/2021/08/24/are-you-scared-of-strongly-typed-languages/
IEEE
" » Are You Scared of Strongly Typed Languages?." The Sharp Ninja | Sciencx [Online]. Available: https://www.scien.cx/2021/08/24/are-you-scared-of-strongly-typed-languages/. [Accessed: ]
rf:citation
» Are You Scared of Strongly Typed Languages? | The Sharp Ninja | Sciencx | https://www.scien.cx/2021/08/24/are-you-scared-of-strongly-typed-languages/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.