Abstract: There is still a lot of confusion about what LLMs actually "are." A very helpful mental model to understand LLMs a bit better is to recognize the distinction between code and data, and when this distinction breaks down. In this article, I introduce you to what code and data formally are, and how LLMs completely defy this seemingly neat distinction. I also include some recommendations for any social scientist working with data that can be drawn from these reflections.


Table of Contents

Last week, I stumbled upon a Reddit post in which a user asked the community “What are LLMs made of? Code, or something else?” And I believe this to be a great question, because it is one that looks innocent until you really start to look at it. And understanding what code and data is, and how they relate, is important beyond understanding how LLMs work. They have a deep meaning for doing data science, too.

In this article, I want to explain what code formally is, and what data is, why the distinction between both is not always easy, and how LLMs drive this inability to cleanly delineate between them to the extreme.

A Definition of Code

Now, first and foremost, I’m not a formal computer scientist, and as such my definition is likely lacking a bunch of nuances that CS researchers might find essential. I try to keep it somewhat on an ELI5 (“Explain like I’m 5 [years old]” for the non-Redditors among you) level since my audience here is to a large extent social scientific, and not specifically nerdy computer-geeks.

Let’s start with the Wikipedia-definition, since that already covers a lot of ground:

In communications and information processing, code is a system of rules to convert information—such as a letter, word, sound, image, or gesture—into another form, sometimes shortened or secret, for communication through a communication channel or storage in a storage medium.

As you can see, “code” is quite an abstract concept. What is important here is that code is a “system of rules to convert information.” Since I’m speaking only about (computer) code, a.k.a. software, or programs, we can simplify this to a system of rules to convert data. Understanding this is simple. Let’s assume you have a big dataset on farm sizes in acres but, like me, you have no way to visualize how big, say, 10 acres are. But you are able to estimate meters (and then squaring them), so that you can get at least an estimate as to how big a number of acres really is. So you decide to write some code, or a function, that automates this conversion across your entire dataset.1

From Wikipedia, we can get a bunch of odd conversions (sorry, I’m a European metrician, what the hell is a furlong?!), and also that one acre is approximately 4,047 m^2^. So, we can write a simple function to do that conversion and spit out one side so that us Europeans can make a mental model of the area.

We can do that, say, in R:

a2m <- function (acres) {
    m2 <- acres * 4047
    one_side <- sqrt(m2)
    return(one_side)
}

a2m(10)
# Returns 201.1716, so 10 acres are
# as large as a square with ca.
# 200 meters on each side.

Or we can do it in Python:

from math import sqrt

def a2m (acres):
    m2 = acres * 4_047
    one_side = sqrt(m2)
    return one_side

a2m(10)

Or in JavaScript:

function a2m (acres) {
    m2 = acres * 4_047
    one_side = Math.sqrt(m2)
    return one_side
}

a2m(10)

This should demonstrate one important part of code: You can write the same code in whichever language you want. As long as you use the correct functions, any language can transform any piece of data the exact same way.

And that’s why code is called a “system of rules”: You define some rules that should be applied to some data to transform it from one representation into another. Here, the rules are quite simple:

  1. Convert the number of acres into square meters by multiplying with 4,047.
  2. Calculate a square root to retrieve the length (in meters) of one side of a square of that area.
  3. Return that one side.
  4. (Be able to somewhat visualize in your head how large the number of acres is.)

Now, of course, this example works for me, because I can roughly estimate how long 200 meters are. Your mileage may differ. But what is important is that you can apply this principle to whatever data you have. For example, sociologists oftentimes have to z-transform2 data points. That is also a process that takes in a number (your data), and applies a set of rules to arrive at another number that represents something different.

So let’s talk a bit more about data.

A Definition of Data (and why it’s sometimes code)

Data is, broadly speaking, any type of information that you can then transform using your codes into another representation. This could be acres as in the example, but it could also be age, income, social class, etc.

In statistics, we frequently convert income using a logarithm to convert the distribution in our dataset into a normal distribution. That is done because income is typically distributed in a long-tail distribution, where most incomes cluster to the left side of a histogram, with a few exorbitant incomes that taper out very far towards the right side of the histogram.

We also often have to dichotomize values. For example, say we have six levels of educational attainment in a dataset (primary school, high school, college, B.A., M.A., PhD). These are typically encoded in six distinct numbers (typically 1-6 or 0-5). If we are only interested in the distinction between “high school” education and “higher” education, we may transform that data so that the numbers 1, 2, 3 are encoded as 0 and 4, 5, 6 are encoded as 1 indicating that a person has indeed enjoyed “higher” education going beyond high school.

The list of potential transformations of our data goes on. But, crucially, we typically have some numbers and need to convert them before we can run our regressions. A useful heuristic is that data is all the numbers in your Excel files, while code is all the R-code we typically write to convert the data (and then stuff it into an OLS-regression).

But there’s a catch: sometimes our data ends up merging with the code.

Think again about the example I provided earlier: What exactly does 4,047 represent? Is it a piece of code? Is it a rule? Or is it, in actuality, a data point?

A bit below the “approximately 4,047 m^2^”, Wikipedia provides a more nuanced definition:

By inference, an “international acre” may be calculated as exactly 4,046.8564224 square metres but it does not have a basis in any international agreement.

Okay, so we should use the number 4,046.8564224 instead of 4,047 to be extra precise, right? Well, that’s the thing: It depends. Formally, the conversion factor is a data point and not really a piece of code. It’s not a rule to use precisely 4,047 or 4,046 and a few to convert. Only the fact that we have to multiply acres by some constant is a rule. The constant is a piece of data.

This becomes more clear with currencies. Most of our smartphones and computers are capable of quickly converting one currency to another. If you’re on a Mac, summon spotlight (or use Spotlight on your iPhone), and type in “1000JPY in GBP” and it will dutifully convert ¥1,000 into £4.61. At least that’s what my computer just gave me. If the Japanese economy just collapsed in between me writing and you reading this article, you may get a totally different number.

Currency conversion factors are always flexible. Your computer, or phone, or smart fridge — whatever you use to run this conversion — everything will pull in new conversion data at some more or less frequent interval to give you a somewhat accurate conversion between currencies. The code to do the conversion, however, never changes.

What I did in the earlier example was that I hard coded a data point into my code, making it unchangeable. If I did the same with a currency, and gave you some program that could convert Japanese Yen into British Pound, then it would stop being accurate because the conversion rate would drift over time.

With the conversion between acres and square meters, however, this implementation will probably be right for the foreseeable future (until someone decides to convert acres into British stones, then to yards, and back to acres, to completely change how big an acre is). That’s why it’s relatively safe to hardcode such a conversion factor, but not a currency conversion.

The most famous example of a hard-coded piece of data that I know of is this lovely piece of code, now called the “fast inverse square root” (taken from Wikipedia):

float Q_rsqrt( float number )
{
	long i;
	float x2, y;
	const float threehalfs = 1.5F;

	x2 = number * 0.5F;
	y  = number;
	i  = * ( long * ) &y;                       // evil floating point bit level hacking
	i  = 0x5f3759df - ( i >> 1 );               // what the fuck?
	y  = * ( float * ) &i;
	y  = y * ( threehalfs - ( x2 * y * y ) );   // 1st iteration
//	y  = y * ( threehalfs - ( x2 * y * y ) );   // 2nd iteration, this can be removed

	return y;
}

I have not changed any of the comments, but they accurately depict a picture of the thought process of someone reading this code who understands it. This code was used in the video game Quake III, and it provides an insanely fast way of calculating the inverse quare root of a number.

Strictly speaking, there is a mathematical formula to calculate the inverse square root, a code, or system of rules how to start with a number and turn it into its inverse quare root. But Quake III was released in 1999. Back then, computers were ridiculously slow compared to modern standards (trust me, I’ve been there. They were awfully slow). So slow that the developers of Quake III decided that it would be too computationally demanding to actually calculate the inverse square root of numbers. Instead, someone simply tried to compress the formula in such a way that, instead of writing code like a normal person, one could simply do this weird bit-shift3 with 0x5f3759df and save a lot of CPU cycles. Essentially, instead of running a bunch of functions, one would simply throw this weird number into the mix, and end up getting a shortcut to calculate the inverse square root much faster and still with decent accuracy.

And this weird little trick worked. It worked very well — for the purposes of this one game. By now, this trick doesn’t work as well anymore, but back then it probably made all the difference.

To conclude this section: Data is something that is being turned from one representation into another using code. But sometimes data can end up written verbatim in the code, which makes it strictly speaking a part of the code (unless someone explicitly changes the number), which is a phenomenon called “hard coding” a value (read: a data point).

Code, Data, and LLMs

Now you may wonder: What does any of that have to do with LLMs? LLMs have neither code nor data, they have trained parameters!

Well, that’s the simple fact that OpenAI and Anthropic want you to focus on. Who has the most parameters? 200 billion? 300 billion? How about 1.5 trillion? But this is a gross oversimplification, and one thing that hides a lot of important facts from the naked eye — especially when we wish to use these models in our social scientific research.

Recall that code is essentially just a system of rules for how to transform information; and data is pieces of information that we wish to transform. Lastly, recall that data sometimes can end up being a part of code, so there is not always a clear distinction between what a piece of data is, and what just code is.

LLMs are the logical conclusion of what happens if you blur this already vague distinction between data and code to the max. LLMs are typically stored inside a simple file. Imagine a Word document, but comically large. A good example of such a file type is GGUF, which is a file type invented specifically to store LLMs. This is how they are typically packaged if you can download them, e.g., on Huggingface. This file contains all the parameters of the model, every piece of training data that it has somehow encoded into its parameters.

These parameters are, by any definition, strictly data points. For example, 1.546234 is a parameter that possibly occurs in several models somewhere, even though I just invented this number. That’s the model’s data.

However, this data makes no sense if you don’t know what to do with it. Because these parameters need to be applied in the correct order. Recall that LLMs are essentially just very big matrix multiplications. You take your text, turn it into embeddings (large vectors of numbers), and then start multiplying them with sets of parameters, one after another, until at the end, the model spits out a new token. Repeat this process a few hundred times and you have a (hopefully correct) answer.

You can’t run these calculations in an arbitrary order. I could not take, say, the parameters of the Gemma 4 model and stuff them into a Qwen model and expect it to produce sensible output.

Language models do not start from the parameters. They start from defining its architecture. There are various ways of how to define a series of matrix transformations that is capable of learning language patterns and, eventually, produce intelligible text. The most basic models are pure decoder models, that is, they use an architecture derived from the original transformer model. (If you want to learn more about the transformer architecture, I have a handy guide.) A “decoder layer” is just a very specific chain of several matrix multiplications that have been empirically shown to be able to encode some meaning of language.

But if you wanted to train your own LLM, you could also choose to use a so-called “Mixture of Experts,” or MoE architecture. In that case, you would not just stack up a bunch of decoder layers until you arrive at 200 billion numbers being multiplied back and forth. Instead, you would split up all those parameters into separate “blocks” of calculations, with the hopes that some of them learn, say, more STEM-coded knowledge, and others would learn more everyday party knowledge.

Once you have defined which architecture you want, you already know the amount of parameters you would have to adjust to train your model. That’s where this number comes from. But at this point, all of them are just — literally — random numbers. You now have to adjust these numbers so that the prompt “Who is the current chancellor of Germany?” would make the model generate the text “Friedrich Merz.” To do so, you train the model with stellar amounts of data. Once that training is done, the parameters are such that, if you provide some initial prompt to the model, it will (hopefully) produce a correct response.

If you were to retroactively change the architecture of the model, that is, the order in which these parameters are used to turn your prompt into an answer, the model would likely produce complete gibberish, because the parameters have been adjusted to work in the very specific architecture of the model.4

This is why LLMs somehow defy the distinction between code and data. They specify some code, that is, rules by which the input text should be transformed to produce a sensible answer, and at the same time the data, which is, to some extent, hard coded into the code. The code would not work without the data, and the data would not work without the code. But the data is not simply a bunch of hard coded numbers, it is an integral part of the model itself. If trained just slightly different, the code would not be able to produce a bunch of numbers that result in sensible text.

Why This Distinction Matters for Social Scientists

Now, to conclude this explainer that has gone a bit off the rails, let me end with a few points on why this distinction matters greatly for social scientists.

First, if you write some code to analyze some data, you should be aware that you are making decisions at every point of the road. Whenever you decide to transform data in a specific way, whenever you write up rules (“code”) that turn data from one representation into the other, you change what the data means. Turning a categorical variable into a binary one is a common step, but it needs to be theoretically motivated. Every line of code you write encodes a decision on your end. Even if you do something very common (such as dichotomizing a network), that is a decision on your part that may not survive the peer review process (ask me how I know).

Second, it is very simple to “hard code” your data. Even more so as a social scientist. Because we are commonly working with static data that, once collected, doesn’t change, it is very simple to write a system of rules (again, “code”) that only works for this data. If we aren’t using meters in our analysis and only convert the acres to meters for our own understanding, it is fine to choose a coarse conversion factor. But if you use this in your analysis, you need to motivate even the hard coded conversion factor. Otherwise, your research is much less defensible. It is very easy to forget that code is in principle generalizable, but the code that we as social scientists write, is often heavily tied to the data we work with. So beware if you copy and paste code from one research project into the other. Your assumptions about the code may be different.

And third, always keep in mind the fact that LLMs are essentially just a big spaghetti of data-con-code. Every LLM encodes (1) a system of rules to (2) use specifically adjusted data (parameters) which (3) have been formed by a very specific training regime that will (4) reproduce a very particular and not at all generalizable part of societal cultural knowledge.5

Recognizing the sometimes blurry distinction between data and code is extremely helpful in producing a data analysis that you fully understand and can defend in the face of reviewers. And it will make your analyses much more confident, since you understand what is going on in your code and data.

One final example: In one of my dissertation papers I received the suggestion to use a particular form of error terms in my regressions, called Panel-Corrected Standard Errors (PCSE). Unfortunately, I could not get it to work. The reason? The corresponding R-package was developed by political scientists who typically work with much smaller datasets than I do. So the code was unoptimized to such a degree that it would simply buckle under the load of my data. The developers of the package made a bunch of decisions that work well for the intended use-case of their code, but which broke with my data. So even if you don’t hard code some specific values into your code, it may still be tightly bound to your own data, and not work with other data.

That’s how quickly assumptions baked into both code and data can become a liability.

Always remember: Most of your code is inseparable from your data, even if you don’t realize it. Code and data are two separate concepts — until they aren’t.


  1. If you want to know how I came up with such a contrived example, please watch the 2026 season of “Jet Lag the Game.” 

  2. Fun fact: There are loads of different definitions of performing a z-transform. I learned one that is used to convert a bunch of arbitrarily large numbers into a fixed number domain, say from 0-100. There is also a z-transform in signal processing, and one that’s commonly used in statistical tests. 

  3. An explainer of that is beyond the scope of this article, and much less interesting to the target audience of it. 

  4. Now, before anybody comes at me: I’m aware that one can both quantize and distill models in such a way that you change some parameters or even the architecture and still have the model produce sensible output. The importance with this is that this process is typically a very careful one, because if you do it wrong, you end up “lobotomizing” the model. My point still stands that you can’t just arbitrarily rip out sets of parameters and stuff them into a different architecture and expect it to just work. 

  5. I have a paper in the works which will expand on this in great detail. 

Suggested Citation

Erz, Hendrik (2026). “LLMs and the Blurry Distinction Between Code and Data”. hendrik-erz.de, 24 Jul 2026, https://www.hendrik-erz.de/post/llms-and-the-blurry-distinction-between-code-and-data.

Send a Tip on Ko-Fi

Did you enjoy this article? Send a tip on Ko-Fi

← Return to the post list