Data and types.
We have built a foundation for thinking about programs. We understand state, instructions, sequences, branches, and repetition. We understand input, output, and failure.
Now we enter a new phase. We will learn about data. What data is. How we represent it. How types help us work with data safely and correctly.
This is Phase 1. Data and structure.
What is data?
Data is information represented in a form a program can work with.
Think about all the information in the world. Names. Numbers. Dates. Locations. Images. Sounds. Text. All of this can be data if we can represent it in our program.
But a program cannot work with ideas directly. It cannot understand "John" as a name the way humans do. It works with representations. Specific patterns of bits. Specific structures in memory.
Data is the bridge between the real world and the program. We take information from the world, represent it as data, process it, and produce results.
Understanding data means understanding how to represent information in a way programs can manipulate.
How do we represent information as data?
Consider a person's age. In the real world, age is a concept — how long someone has lived. In a program, we might represent age as a number: 25.
Consider a person's name. In the real world, a name is a word we use to identify someone. In a program, we might represent it as a sequence of characters: "Alice".
Consider whether someone is a student. In the real world, this is a status — either they are enrolled or not. In a program, we might represent it as a boolean: true or false.
In each case, we take something from the real world and choose a representation. The representation is not the thing itself. It is a model, an approximation that captures the aspects we care about.
Choosing good representations is a fundamental skill. A poor representation makes everything harder. A good representation makes problems easy to solve.
Now, what is a type?
A type classifies data. It tells us what kind of data we have and what we can do with it.
Consider the number 25. Is it an age? A temperature? A count? The bits in memory are the same. But the meaning is different. And the valid operations might be different.
Types make this explicit. We do not just have "25". We have "25 as an integer" or "25.0 as a decimal number" or "25 as an age".
Types tell us: What values are valid. What operations are valid. How the data is stored.
Without types, programs would be chaos. Any operation on any data. Adding a name to a number. Multiplying a boolean by a date. Nonsense.
Types prevent nonsense. They enforce rules about what you can do with what data.
Think of types as constraints.
When you declare that a value has a certain type, you are making a promise. This value will always be of this type. It will never be something else.
The program can rely on this promise. If a value is typed as an integer, the program knows it can perform arithmetic. If a value is typed as text, the program knows it can concatenate strings.
These constraints might feel limiting. You cannot put a string where an integer is expected. But these constraints protect you.
They prevent you from doing things that do not make sense. They catch mistakes before the program runs. They make programs more predictable and reliable.
Constraints are not restrictions. Constraints are guarantees.
Different types support different operations.
Numbers support arithmetic: addition, subtraction, multiplication, division. You can compare them: greater than, less than.
Text supports concatenation: joining strings together. You can find the length. You can extract substrings.
Booleans support logical operations: and, or, not.
Collections support operations like adding elements, removing elements, searching, and iterating.
When you know the type of data, you know what you can do with it. The type defines the interface — the set of valid operations.
Trying to perform an operation that the type does not support is an error. You cannot divide text by a number. You cannot concatenate integers. These operations do not make sense for those types.
Types enforce meaningful operations.
Types also determine how data is stored in memory.
An integer might be stored as 32 bits. A different kind of integer might use 64 bits. Text might be stored as a sequence of bytes representing characters.
This matters because storage affects what values are possible.
A 32-bit integer can represent numbers up to about two billion. Need bigger numbers? Use a 64-bit integer or a special big-number type.
A single character might be stored differently in different encodings. Understanding the type helps you understand the limitations.
You do not always need to think about storage. But when dealing with very large data, memory constraints, or interoperability with other systems, it matters.
Types hide many storage details while still constraining what is possible.
What happens when types are misused?
A type error occurs when you try to use data in a way that violates its type.
Assigning a string to a variable that expects an integer: type error.
Calling a method that does not exist on that type: type error.
Passing the wrong number of arguments to a function: type error.
Type errors can be caught at different times.
Some languages check types before running — at compile time. You cannot even run the program if there are type errors. This is static typing.
Other languages check types while running — at runtime. The program starts, but crashes when a type error is encountered. This is dynamic typing.
Both approaches have trade-offs. Static typing catches errors earlier. Dynamic typing offers more flexibility. But in both cases, type errors indicate that something is wrong.
Types serve another purpose: documentation.
When you see that a function takes an integer and returns a string, you immediately know something about how to use it. The types tell you what to provide and what to expect.
When you see a variable typed as a list of users, you know what it contains without reading all the code that created it.
Types are documentation that the compiler or interpreter can check. Unlike comments, types cannot lie. If the code says a value is an integer, it is an integer. The type system enforces this.
This makes code easier to understand. You can look at the types and understand the shape of the data, even without understanding all the logic.
Well-chosen types communicate intent.
Let us be clear about what types do and do not prevent.
Types prevent certain kinds of errors. Using data in ways that violate its type. Passing the wrong kind of value. Performing invalid operations.
Types do not prevent all errors. You can still have the wrong logic. You can still have bugs in your algorithm. You can still misunderstand the requirements.
An integer type ensures you have an integer. It does not ensure you have the right integer.
Types are a safety net, not a guarantee of correctness. They catch a category of mistakes — type mistakes. Other categories require other techniques.
But catching type mistakes automatically is valuable. It eliminates a whole class of bugs without requiring you to test for them explicitly.
Let us summarize.
Data is information represented in a form a program can work with.
Types classify data. They tell us what kind of data we have.
Types determine what operations are valid. Each type supports a specific set of operations.
Types determine how data is stored. This affects what values are possible.
Types act as constraints and guarantees. They prevent nonsense operations.
Type errors occur when data is used in ways that violate its type.
Types serve as documentation. They communicate what data flows through the program.
Types prevent certain errors automatically. They catch type mistakes at compile time or runtime.
Understanding data and types is fundamental to writing correct programs.