God Is Real Unless Declared INTEGER: From a Fortran Joke to Catching Silent Bugs in Python

"In Fortran, God is real unless declared INTEGER." A late-night programmer joke led me into Fortran's implicit typing, the legendary DO10I bug, and a hands-on Debian lab where Python silently returned 0 instead of 60, and flake8 caught my typo twice.

How a joke turned into a lab session

A one-line programmer joke led me to a real lesson about silent bugs. Late one evening I typed an old favorite into a chat with Claude, my AI study partner:

In Fortran, God is real unless declared INTEGER.

I expected a laugh. Instead I got a short history lesson, then a question: did I want to see the same kind of bug in modern Python? I said ok. About half an hour later, I had built a small lab on my Debian machine, watched Python give me a wrong answer with no error, and watched a linter catch my mistake twice.

This post walks through the whole path: the joke, the history behind it, and the hands-on session, typos included.

Concept explainer: why God is REAL in Fortran

Early Fortran guessed a variable’s type from the first letter of its name. You didn’t have to declare anything.

  • Names starting with I, J, K, L, M or N were automatically INTEGER (whole numbers).
  • Every other starting letter meant REAL (floating-point numbers like 3.14).

The rule matched math notation, where i, j, k and n are the usual counters. Programmers remembered it as “INteger”: the letters I through N.

GOD starts with G, so unless you wrote INTEGER GOD, God was REAL. The pun works because “real” means both a floating-point number and “exists.”

The bug hiding in the joke

Implicit typing had a dark side. A misspelled variable didn’t cause an error. Fortran quietly created a brand-new variable instead.

Fortran also ignored spaces. A famous, partly legendary story describes a loop written as DO 10 I = 1.10 when 1,10 was intended. One period instead of a comma, and the compiler read it as assigning 1.10 to a new REAL variable named DO10I. No loop, no error.

Careful Fortran programmers learned to start every program with:

IMPLICIT NONE

That line turns off the guessing. Every variable must be declared, so typos get caught.

The same trap in Python

Python doesn’t make you declare variables either, but it decides type differently. The type comes from the value you assign, not the name. x = 5 is an int; x = 5.0 is a float.

The misspelling problem survived, though. Assign to totl when you meant total, and Python silently creates a new variable. No error, just a wrong answer.

Python has no IMPLICIT NONE. The closest safety net is a linter: a tool that reads your code without running it and flags patterns that usually mean mistakes. That’s what I set out to test.

Lab journal: the terminal session

Everything below ran on my Debian desktop, one command at a time.

1. A practice folder

(base) lvydvy@Debian:~$ mkdir typo-demo
(base) lvydvy@Debian:~$ cd typo-demo
(base) lvydvy@Debian:~/typo-demo$ pwd
/home/lvydvy/typo-demo

mkdir creates a folder, cd (change directory) steps into it, and pwd (print working directory) confirms where I am.

2. The first surprise: (base)

That (base) in my prompt meant conda was active. Conda is another Python environment manager. Creating a venv on top of it would stack two environment layers and tie the venv to conda’s Python. So I switched conda off for this terminal only:

(base) lvydvy@Debian:~/typo-demo$ conda deactivate
lvydvy@Debian:~/typo-demo$ which python3
/usr/bin/python3

which shows exactly which program a command will run. /usr/bin/python3 is Debian’s own Python.

What if I hadn’t known to do that? Nothing would have broken outright. But the venv would quietly depend on conda, and it gets easy to install a package in one place and run code from another. The real lesson: always check which python3 and which pip after activating anything.

3. The second surprise: I skipped a step

lvydvy@Debian:~/typo-demo$ python3 -m venv venv
lvydvy@Debian:~/typo-demo$ which python3
/usr/bin/python3
lvydvy@Debian:~/typo-demo$ which pip
/usr/bin/pip

The venv was created, but I forgot to activate it. The which checks caught it: still /usr/bin, no (venv) in the prompt. Had I run pip install here, Debian would have refused with an externally-managed-environment error, which protects the system Python.

lvydvy@Debian:~/typo-demo$ source venv/bin/activate
(venv) lvydvy@Debian:~/typo-demo$ which python3
/home/lvydvy/typo-demo/venv/bin/python3
(venv) lvydvy@Debian:~/typo-demo$ which pip
/home/lvydvy/typo-demo/venv/bin/pip

source puts the venv’s bin folder at the front of my PATH. Same commands, different programs.

4. Installing the linter

(venv) lvydvy@Debian:~/typo-demo$ pip install flake8
...
Successfully installed flake8-7.4.1 mccabe-0.7.0 pycodestyle-2.15.0 pyflakes-4.0.3

flake8 bundles three checkers: pyflakes (logic problems), pycodestyle (formatting) and mccabe (code complexity).

5. The buggy program

def add_prices(prices):
    total = 0
    for p in prices:
        totl = total + p  # typo: should be "total"
    return total


print(add_prices([10, 20, 30]))
(venv) lvydvy@Debian:~/typo-demo$ python3 typo_demo.py
0

The answer should be 60. Python printed 0 with no warning. total never changed, because every result went into totl. This is the modern DO10I.

6. The linter catches it

(venv) lvydvy@Debian:~/typo-demo$ flake8 typo_demo.py
typo_demo.py:4:9: F841 local variable 'totl' is assigned to but never used

That’s file, line 4, column 9, error code F841 (the F codes come from pyflakes). flake8 doesn’t know what I meant. It only noticed a variable that gets written and never read, which is almost always a typo.

7. Fixing it, and making a new typo

My first fix went wrong. I typed an extra letter:

(venv) lvydvy@Debian:~/typo-demo$ python3 typo_demo.py
0
(venv) lvydvy@Debian:~/typo-demo$ flake8 typo_demo.py
typo_demo.py:4:9: F841 local variable 'totall' is assigned to but never used

Python stayed silent again. flake8 caught the new typo instantly. It doesn’t care which typo you make; it catches the pattern.

Second try, checking with cat before running:

(venv) lvydvy@Debian:~/typo-demo$ python3 typo_demo.py
60
(venv) lvydvy@Debian:~/typo-demo$ flake8 typo_demo.py
(venv) lvydvy@Debian:~/typo-demo$

60, and silence from flake8. In the terminal, silence means clean.

One leftover: the comment # typo: should be "total" was still there. Linters don’t read comments for meaning, so a stale comment can mislead the next reader. It’s worth deleting.

Lessons learned

  1. Silent bugs are the worst bugs. Python ran “successfully” and gave a wrong answer. Nothing told me anything was wrong.
  2. Verify, don’t assume. Two quick which commands caught a skipped activation before it caused trouble. It’s the same instinct as in security work: confirm what’s actually running.
  3. Watch your prompt. (base) and (venv) tell you which environment you’re in. I’d never paid attention to (base) before.
  4. Linters catch patterns, not intentions. flake8 caught two different typos without knowing what I meant. It’s the closest thing Python has to Fortran’s IMPLICIT NONE.
  5. Old jokes carry real history. A 1950s design choice and a 2026 Python bug turned out to be the same problem.

Connections to my studies

Black Hat Python. In the sniffer chapter, decoding IP headers with ctypes or struct.unpack means declaring each field’s exact type and size. Raw packet bytes carry no type information, so a wrong type gives garbage. That’s the Fortran lesson in reverse: there, the compiler guessed types; here, I have to state them precisely. Running flake8 on those scripts as I write them is an easy habit to add.

Static analysis in security. flake8 reads code without running it. Security tools like Bandit do the same thing for Python, hunting for risky patterns such as hardcoded passwords or unsafe eval() calls instead of typos.

AWS DVA-C02. The verification habit carries over to the cloud. Before trusting a deployment, confirm which credentials, region and runtime are actually in use, not the ones you think are.