Computer Sciencefor Theatre & Technical Direction

Class 2 of 6 Unit 1 · The machine and the language 4 hours · 2 at the keyboard

Inside the Language

Source to running, types, references, floating point, patchers and blocks, and where each language came from.

Teach mode Working rules

A programming language is not a way of talking to a computer. It is a way of writing down a decision so precisely that a machine can carry it out without you in the room.

Logic gym#

Fifteen minutes, on paper, in pairs. Same rule as Class 1: say the answer out loud, in a full sentence, before you check it. A vague guess that could be retrospectively right is the habit this gym exists to break.

1. What does it print#

a = "12"
b = 3
print(a * b)

Say what happens in Python. Then say what happens if you write the same three lines in JavaScript. They differ, and neither is a mistake by the language. Say which one you would rather have when the value came out of a spreadsheet, and why.

2. Two names, one thing#

a = [1, 2, 3]
b = a
b.append(4)

What is in a? Now draw it: two boxes with names in them, one box with a list in it, and arrows. The drawing is the answer. Anybody who can draw this correctly will never be surprised by this class of bug again, and anybody who cannot will be surprised by it for years.

3. The comparison that is false#

0.1 + 0.2 == 0.3 is false. Before anybody explains why, answer a different question: name three other places in a show where two numbers that should be equal will not be. A timecode. A fader. A measured distance. What do all three have in common?

4. Count it out loud#

Fixtures at eight channels each, starting at address 1.

  • Which fixture is on 57?
  • What is the last address used by fixture 12?
  • How many fit before the universe runs out, and what is the address of the first one that does not?

Say all four before anybody opens anything. Then say what changes if the start address is 101.

5. Read the signature, judge the function#

def patch(fixtures, start, footprint, universe=1, skip=None, force=False):

You have not seen the body. From the signature alone: what does this probably do, what are the two parameters you would ask about before calling it, and which one would you refuse to use until somebody explained it?

That refusal is a professional skill. A function whose behaviour you cannot predict from its signature is one you should not be calling near an audience.

What the gym is for#

Every item is the same move: hold the state, run it forward, commit. Class 1 did it with behaviour. This class does it with values, and the difference is that here you also have to hold what type each thing is, which is the part that catches people for about a fortnight and then never again.

What happens between typing and running#

You write text. Text does nothing. Something has to turn it into the fetch-arithmetic-store-decide loop from Class 1. Four steps, in every language that has ever existed.

1. Lexing. The text is chopped into tokens. level = level + 5 becomes: name, equals, name, plus, number. Spaces disappear. This is why indentation matters in Python and not in C: Python's lexer emits tokens for it and C's throws it away.

2. Parsing. The tokens are assembled into a tree that carries the structure. 2 + 3 * 4 becomes a tree where the multiply hangs below the add, which is precisely why the answer is 14 and not 20. A syntax error is this step failing: the parser reached a token that cannot follow the last one and has no idea what you meant.

3. Compiling. The tree becomes instructions. This is where languages split:

  • Compiled ahead of time, like C or C++ or Rust: the whole program becomes machine code for one kind of processor, before it ever runs. Fast, and you must build it again for a different chip.
  • Compiled to bytecode, like Python, Java or C#: instructions for a pretend machine, which a runtime then executes. Portable, slower, and it can tell you a great deal when it goes wrong.
  • Just in time, like JavaScript in a browser or in Node: starts interpreting, notices which parts run often, and compiles those to machine code while running. This is why the first pass through an animation is slower than the hundredth.

4. Executing. The instructions run, on a real CPU, one at a time, very fast.

Why a technical director cares about step 3#

Because it decides what you can do at 23:40.

A compiled language means somebody must rebuild the firmware and reflash the device, which needs their toolchain, their source, and their availability. An interpreted language means the source is on the machine, and can be read and changed in place with a text editor.

That is the practical difference between "the supplier can fix it on Tuesday" and "we can look right now". It is worth asking, in procurement, before it is 23:40.

LanguageKindWhere you meet it in a show
C / C++Compiled ahead of timeArduino sketches, console firmware, media server internals
PythonBytecode, interpretedAutomation scripts, Raspberry Pi show control, data wrangling
JavaScript / TypeScriptJIT compiledBrowser panels, Node tools, Remotion, Companion modules
LuaBytecode, interpretedEmbedded scripting in consoles and media servers
C#Bytecode, JITWindows show tools, Unity-based projection work

Values, and what a type is for#

Everything a program handles is a value: a number, a piece of text, a truth, a collection. A type is the answer to "what can I do with this, and what does it mean?"

The important types, and the show-floor version of each:

TypeWhat it holdsWhere it bites
IntegerA whole number, exactlyChannel 512, frame 1440, universe 3
FloatA number with a fractional part, approximatelyFade times, positions, dB, anything continuous
StringText, in a specific encoding"512" is not 512, and everything from a file is text first
BooleanTrue or falseIs the door open, is the fixture patched
List / arrayAn ordered collectionCue stack, channel list, frames of an animation
Dictionary / mapLook something up by a keyFixture by address, cue by number
None / nullThe absence of a valueThe return value of a lookup that found nothing

The one that costs the most time in production work is the third row. Everything that arrives from a file, a network message, a form or a serial port arrives as text. A DMX address read from a CSV is "512", four characters, and "512" + 1 is either an error or "5121" depending on the language. Neither is what you wanted.

addr = "512"          # from a CSV
print(addr + 1)       # TypeError in Python
print(int(addr) + 1)  # 513, which is what you meant

JavaScript will not error. It will helpfully produce "5121", and your patch will be wrong two hundred rows later with nothing having gone visibly wrong.

Static and dynamic, and which one you want at 23:40#

A statically typed language checks types before running. int addr = "512"; will not compile in C, and the error arrives on your laptop, in daylight, weeks before the show.

A dynamically typed language checks while running. Python discovers the problem the moment it reaches that line, which might be during the show, on the one branch nobody tested.

Neither is better in general. But there is a rule that holds up in this industry:

The more a piece of code runs unattended in front of an audience, the more you want its mistakes to happen before it ships. Firmware for a prop: static. A script you run yourself on the get-in: dynamic is fine, because you are standing there.


Do it now: everything arrives as text#

Seven cases, and only the first is the one you would have written. The other six are a spreadsheet that went through three people, which is every patch you will ever be handed.

Notice what the last case is defending against. Returning NaN for "twelve" does not fail; it succeeds with a value that poisons everything downstream, and the fault surfaces four functions later in code that is not wrong. Convert at the edge, once, and refuse what will not convert.


References, and the bug where two names are one thing#

Here is the surprise that catches everybody once, and catches some people annually.

default_cue = {"level": 0, "time": 3.0}

cue_1 = default_cue
cue_2 = default_cue

cue_1["level"] = 255

print(cue_2["level"])   # 255. Not 0.

cue_2 was never touched. It reads 255 anyway.

The reason: a variable does not contain the dictionary. It contains a reference to it, an arrow pointing at one object in memory. Three names, one object. Change it through any of them and all three see it, because there is only one thing there.

The same code with numbers behaves the way you expected, because assigning a number copies the value. So the rule is not intuitive and cannot be guessed:

  • Simple values (numbers, booleans, and in most languages text) behave as copies.
  • Collections (lists, dictionaries, objects) behave as references.

In production code this appears as: every fixture in the rig getting the same values, because they were all built from one template that was never copied. Or an "undo" that does not undo, because the snapshot you saved was a reference to the thing you then changed. The symptom is always the same and worth memorising: something you did not touch changed.

The cure is to copy explicitly when you mean a copy:

import copy
cue_1 = copy.deepcopy(default_cue)   # now it is genuinely its own dictionary

Do it now: two names, one object#

This is the most famous bug in Python and it exists, in a different costume, in this language too. The exercise gives you a broken makeCue and four cases. Three of them pass while it is broken, which is the actual lesson: the test that catches this is the one that makes two of the thing, and "make two of it" belongs in your head as a reflex.


Floating point, and the 0.1 + 0.2 problem#

>>> 0.1 + 0.2
0.30000000000000004
>>> 0.1 + 0.2 == 0.3
False

This is not a bug in Python. Every language on every machine you will ever touch does this, because they all use the same IEEE 754 standard, and it follows from something simple.

A float is stored in binary. In binary, one tenth is a recurring fraction, the way one third is in decimal: 0.0001100110011... forever. The machine has 53 bits of significand, so it stores the closest value it can and stops. The error is about one part in 10¹⁶, and adding two of them makes it visible.

The consequences that reach a show:

Never compare floats with equals. if position == 12.0 may be false when the position is 12.000000000000002. Compare with a tolerance instead:

if abs(position - 12.0) < 0.001:

Do not accumulate. Adding 0.1 a hundred times does not give 10.0, it gives 9.99999999999998, because a hundred small errors add up. Multiply instead: t = i * 0.1. This one matters for animation, where a frame time added repeatedly drifts and a frame number multiplied does not. Class 6 is built on that fact.

Use integers for money, addresses and frames. Anything counted rather than measured should be an integer. Frame 1440 is exact. 57.6 seconds at 25 fps is not.

Where it does not matter. A fade time of 3.0000000000000004 seconds is 0.4 femtoseconds off, and your fixture's own resolution is a hundred thousand million times coarser. Knowing when precision is irrelevant is as professional as knowing when it is not.


Do it now: a comparison that survives the machine#

Six cases, and the last three are the interesting ones. A tolerance that swallows a whole percent is not a tolerance, it is a bug being helpful. Pick a number you can defend, write down what it is a fraction of, and put the reason next to it in the code.


Control flow: the four shapes#

Every program ever written is made of four shapes, and the tree from the parser is just these nested.

Sequence. One thing after another, in order.

Branch. if, else. A decision, taken once, on a condition. The condition is where the bug usually is: > instead of >= is one fixture out of five hundred, or one frame out of ten thousand.

Loop. while or for. Repeat. Two questions, always: what changes each turn, and what makes it stop? A loop whose stop condition can never be reached is a hang, which is failure mode two from Class 1.

Call. Run a named piece of code elsewhere and come back with a result. This is the one that makes programs comprehensible to humans, because it lets you stop holding all of it in your head.

Functions, and reading a signature#

def fade(fixture, target, seconds=3.0):
    """Fade one fixture to a level over a time. Blocks until finished."""

Read that line before you read anything else. It tells you:

  • Name. What it claims to do.
  • Parameters. What it needs: a fixture, a target, and optionally a time that defaults to 3.0.
  • Defaults. Which arguments you may leave out, and what happens if you do.
  • Return. What comes back. Nothing here, which is itself information.
  • The docstring. In this case one crucial word: blocks. This function does not return until the fade is finished. Call it for eight fixtures in a row and you have a 24 second cue during which nothing else in your program happens, including the emergency stop check.

Reading the signature and the first line of the docstring, before reading the body, is the single highest-value reading habit in this course. It is also how you review AI-generated code fast in Class 4: the signature tells you what it promises, and the body tells you whether it kept the promise.


Programming you do not type#

Most of the programming done in this industry is not typed. It is patched, wired and dragged, and a student who thinks that is not really programming will be wrong about something they will do every week for the rest of their career.

Go back to the parser from the top of this class. It turned your text into a tree: nodes with operations in them and edges carrying values between them. Execution walks that structure.

Now notice what a patcher is. TouchDesigner, Max/MSP, Pure Data, vvvv, Notch, Unreal Blueprints, Node-RED, Grasshopper: every one of them is that same graph, with the parsing step removed because you built the graph directly.

Text and boxes-and-wires are two notations for the same thing. The difference is the editing surface, not the semantics. There is no sense in which one is real programming and the other is not, and everything in this course applies unchanged to both.

Where you will actually meet it#

EnvironmentWhat it isWhere it turns up
TouchDesignerNode-based real-time video and controlProjection, interactive installations, media systems
Max/MSP, Pure DataAudio and control patchersSound design, instrument building, interactive audio
Unreal BlueprintsVisual scripting over a game engineVirtual production, LED volumes, previz
Notch, vvvvReal-time graphics node graphsTouring video, camera-tracked content
Node-REDWiring events between devices and servicesBuilding systems, MQTT, small show integrations
Bitfocus CompanionTrigger and action rules, not a graphStream decks, integration glue, cue triggering
GrasshopperParametric geometry over RhinoScenic, rigging geometry, fabrication
Ladder logic (IEC 61131-3)A graphical language for PLCsAutomation. The thing that moves scenery and lifts people
Console effect and macro editorsWhatever the manufacturer builtLighting, media servers

The last two rows deserve a pause. Ladder logic is a graphical programming language, it is what runs safety-rated automation, and it is a standard rather than a toy. If your career goes towards automation you will read more ladder than Python, and the four questions are the same questions.

Scratch, MakeCode and the block languages#

Blocks (Scratch, MakeCode, Blockly, micro:bit) are the teaching version of the same idea, and they are worth understanding rather than dismissing.

What they remove is syntax error as an obstacle. A block that will not fit cannot be dropped there, so a beginner spends their attention on sequence, branch, loop and call rather than on a missing semicolon. That is a real pedagogical win, and it is why they work: what is hard about programming was never the punctuation.

What they do not remove is anything in this course. A Scratch project has state, does something on each pass, assumes things, and behaves some way when it is wrong. If you are ever teaching this to someone with no background, or building a workshop for a young audience, blocks are the right first notation and the ideas transfer directly.

What each notation is actually better at#

Do it now: the same program, both ways#

Build anything. A fade, a chase, a condition. Then watch the panel on the right while you build.

That panel is not a translation and it is not a simplification. It is your program written out in three notations, generated from the same tree the runtime just walked. Blocks are not programming for beginners; they are programming with the spelling removed, which is exactly what a patcher window, a ladder diagram and a cue stack also are. Nobody using Max, TouchDesigner or a PLC thinks of themselves as writing code, and all three of them are.

The question worth arguing before you leave this section: what does the text version give you that the blocks do not? There are at least four answers and one of them is the reason every large system ends up in text.

Visual is better at: dataflow and signal, where the picture is genuinely the structure. Seeing state, because the value on a wire can be displayed on the wire. Real-time work where you are tuning by feel. And being read by somebody who does not write code, which in a production meeting is worth a great deal.

Text is better at: everything to do with keeping the work, which is Class 3. And it is worth being specific about why, because this is the trade nobody mentions when they demo a patch:

  • Version control. Most patcher files are one binary or one enormous generated file. git diff tells you the file changed and nothing about what changed. Two people cannot merge two versions of a patch; one of them loses their afternoon.
  • Search. You cannot grep a patch for every place an address is used.
  • Review. "Send me the diff" has no answer. Reviewing a patch means opening it and looking.
  • Reuse. Copying a subpatch is copying, not referencing. Fix the bug in one and the other four still have it.
  • Scale. Every patcher above about a few hundred nodes has the same disease, and it has a name in every one of those communities: spaghetti. The cure is discipline about subpatches, and it is the same discipline as functions.

None of that makes visual programming wrong. It makes it a tool with a known cost, and the professional move is to know the cost before the show rather than during the handover.

The four questions, in a patcher#

They do not change. They point at different things:

QuestionIn textIn a patcher
What state does it hold?VariablesWhat is stored inside the nodes, and what is only on a wire
What happens each pass?One turn of the loopOne cook, one frame, one scan of the ladder
What does it assume?Types and inputsWhat each wire is carrying, and what happens if it is empty
What when it is wrong?Exception, or worseWhat a node outputs when its input is missing, and what the rest does with that

The third row is the one that bites. In a lot of node environments an unconnected input silently becomes zero, or black, or the last value, and nothing anywhere reports it. That is failure mode four from Class 1, carry on regardless, built into the tool as the default.


Going deeperHello world, ten times#

Read this before the class rather than in it. It is a comparison rather than a demonstration, and you can read it faster than anybody can say it. Bring one question.

The traditional first program prints two words. It is a silly program and it is a genuinely useful comparison, because the ceremony around the one line tells you what the language cares about.

/* C, 1972 */
#include <stdio.h>

int main(void) {
    printf("Hello, world\n");
    return 0;
}
// Arduino, which is C++ with the awkward parts hidden
void setup() {
  Serial.begin(115200);
  Serial.println("Hello, world");
}
void loop() {}
# Python, 1991
print("Hello, world")
// JavaScript, 1995
console.log("Hello, world");
-- Lua, 1993
print("Hello, world")
// Java, 1995
public class Hello {
    public static void main(String[] args) {
        System.out.println("Hello, world");
    }
}
// C#, 2000
Console.WriteLine("Hello, world");
// Go, 2009
package main

import "fmt"

func main() {
    fmt.Println("Hello, world")
}
// Rust, 2010
fn main() {
    println!("Hello, world");
}
# The shell, older than most of the above
echo "Hello, world"

And in a patcher there is no text at all: a message box containing Hello, world with a wire into a print object, which is two clicks and tells you something about that notation too.

What the ceremony is telling you#

C needs a header and a return code because it is a systems language from a world where the operating system needed to know whether your program succeeded, and where nothing is included unless you ask for it. That austerity is why it still runs the chip in your prop fifty years later.

Arduino needs a setup and a loop because the thing it runs on does one job forever and there is no operating system underneath to hand control back to. The shape of the program is the shape of the machine.

Python needs one line because it was designed on the principle that reading code is more common than writing it, and that the obvious way should be the short way.

Java needs a class, a public static void main and an array of arguments because it was built on the position that everything is an object, in an era of large teams and enterprise codebases where uniformity mattered more than brevity.

Go needs a package declaration and an import because it was made at Google for very large teams and very fast builds, and both come from being strict about structure and dependencies.

Rust's println! has an exclamation mark because it is a macro, expanded and checked at compile time. Almost everything unusual about Rust comes from moving checks earlier, into the compiler, where a mistake costs a build rather than a show.

Read the ceremony as a statement of values. A language that makes you write more before you can print two words is usually buying you something later: a guarantee, a build time, a team of forty people who can all read it.


Going deeperwhere each one came from, and what it owns now#

Languages are not fashion. Each one exists because somebody had a problem that the languages of the day could not solve, and each one dominates a field because that field has that problem.

LanguageMadeThe problem it was made to solveWhat it owns now, and why
Assembly1940s onWriting machine instructions by hand was error-prone. Give them namesAlmost nothing, by hand. You read it in a disassembly when firmware has gone badly wrong
Fortran1957Scientists needed to write formulas rather than instructions. The first widely used high-level languageHeavy numerical computing, still, because fifty years of trusted libraries do not get rewritten
C1972Writing an operating system in assembly was unmaintainable. Portable, close to the metal, no hidden costFirmware, kernels, embedded. Your Arduino, your console's guts, and almost everything below them
C++1985C plus abstraction for large programs, without giving up the speedMedia servers, game engines, audio software, anything real-time where every millisecond is counted
Python1991Scripting that was actually pleasant to read. Explicitly designed against clevernessAutomation, data, scientific work, AI tooling, Raspberry Pi show control. It won because it is readable by people who are not programmers
Lua1993A tiny language to embed inside another applicationScripting inside consoles, media servers and games. You do not choose Lua; Lua is what is in the box
Java1995Write once, run anywhere, in an era of incompatible machinesEnterprise systems, Android, large back ends. Chosen for the ecosystem and the hiring pool more than the language
JavaScript1995Make a web page do something. Designed in ten days, and it showsEvery browser on earth, plus Node on the server. It owns the web by being the only option there
C#2000Microsoft's answer to Java, better designed and tied to WindowsWindows show tools, Unity, a lot of AV control software
Go2009Very large teams, very fast builds, easy concurrencyNetwork services and infrastructure. The tools your show network runs on are often written in it
Rust2010Memory safety without a garbage collector, so systems code stops having a whole class of bugSlowly replacing C and C++ where safety matters. Increasingly in audio and media tooling
TypeScript2012JavaScript grew up and needed the static type checking from earlier in this classAny browser or Node codebase past a few thousand lines, which is most of them now
Ladder logic1960sLet electricians program controllers using the relay diagrams they already readIndustrial and entertainment automation. What moves scenery, and what is certified for it

The pattern worth taking away#

Read that table by the middle column rather than the right one. Each language is an answer to a constraint of its moment: no memory, no speed, no compiler, no team, no safety.

A language dominates a field when its original constraint is that field's constraint. C owns embedded because it was made for machines with nothing to spare, and a microcontroller still has nothing to spare. Python owns automation because it was made for readability, and a script's real cost is somebody reading it in two years. Lua owns embedded scripting because it was made small enough to fit inside another program, and it still is.

So when somebody tells you a language is outdated, the useful question is not how old it is. It is whether the constraint it was built for still exists. For the machine in your prop, every one of C's constraints is still true, which is why a language from 1972 is the right answer in 2026 and will still be the right answer for a long time.


Which language, which notation, and why it is rarely your choice#

Numbers from this class#

ThingValue
Steps from source text to executionFour: lex, parse, compile, execute
Why 2 + 3 * 4 is 14Precedence is in the tree the parser builds
Bits in a double-precision float significand53
Relative error of a doubleAbout 1 part in 10¹⁶
0.1 + 0.2 in any IEEE 754 language0.30000000000000004
Safe float comparisonabs(a - b) < tolerance
Range of an 8-bit unsigned integer0 to 255, which is one DMX slot
Range of a 16-bit unsigned integer0 to 65535, which is 16-bit pan or tilt
DMX universe size512 slots
What arrives from a file, network or serial portText, always, until you convert it
Simple values on assignmentCopied
Collections on assignmentReferenced, not copied
The four shapes of control flowSequence, branch, loop, call
The first thing to read in any functionIts signature, then one line of the docstring
What a patcher isThe parser's tree, edited directly, with the parsing step removed
Ladder logicA graphical language in IEC 61131-3, and what runs safety-rated automation
What block languages removeSyntax errors, not any of the four questions
Where a patch is weakestVersion control, search, review, reuse and scale
An unconnected input in most node environmentsSilently zero, black or the last value, reported by nothing
C1972, for writing an operating system without assembly
Python1991, for scripting that is pleasant to read
JavaScript1995, designed in ten days, and it owns the browser by being the only option
Lua1993, small enough to embed inside another application
Rust2010, memory safety without a garbage collector
Ladder logic1960s, so electricians could program controllers from relay diagrams
Why a language dominates a fieldIts original constraint is still that field's constraint
What the ceremony around hello world tells youWhat the language decided to buy, and what it charged for it

Self test with model answers

Answer it yourself first, out loud or on paper, then open the answer. Reading the answer without attempting the question teaches you almost nothing.

Note. These are model answers, not the only correct ones. If yours differs and you can defend it with the arithmetic and a measurement, that is worth more than matching the wording.

The four hours, accounted for. This is the lecturer's view of the session, and it is here rather than hidden in a pack because a student who can see where the time goes can see what the class is actually for.

Run of the session #

240 minutes · 130 at the keyboard · 75 on the idea

25203020353020
  1. 10min Open The two surprising results, on the board, explained by the end of the class
  2. 25min The idea Source to running: tokens, tree, bytecode, machine. What a language actually is
  3. 15min Lab · gym Logic gym 2, on paper. Types, references, and the off by one
  4. 20min The idea Values, types, and what a type buys you when a fixture address arrives as text
  5. 15min Break —
  6. 30min Lab A Trace a program by hand on paper, then run it and compare against your trace
  7. 20min The idea References, mutation, and the bug where two names are one object
  8. 35min Lab B Floating point, the shared default, and the patch line that arrives as text
  9. 30min Lab C Write a function with a signature you can defend, and its three failure cases
  10. 20min Lab D The same program in blocks and in text, side by side, and what actually differs
  11. 10min The idea Programming you do not type: patchers, blocks and ladder logic
  12. 10min Close The signature you wrote, read aloud, and what Class 3 does with it

Blocks are an order of work rather than a timetable: a class that runs long at the keyboard is a class that is going well. The minutes are here so you know what you are trading against when it does.

Four hours goes fast, and most of it is at the keyboard. What you do before the class, and in particular whether the software is installed and working, decides whether you spend those hours learning or catching up.

What you must already be able to do#

Answer the four questions from Class 1 about a program somebody hands you: what state it holds, what one pass does, what it assumes, and how it fails. Open a terminal and run python3 --version.

You should have read Foundations as far as binary and hexadecimal. This class does arithmetic in three bases and does not stop to explain them.

Three things to do#

  1. Type six lines into a Python prompt and be surprised twice. Run python3, then enter each of these and write down what came back: 0.1 + 0.2, 10 / 3, 10 // 3, "3" + "4", [1,2] + [3], [1,2] * 3. Two of those do something you did not expect. Bring the two.
  2. Find the loop in something you already use. Open a QLab script, an Arduino sketch, a console's macro language, a spreadsheet formula that fills down. Find the part that repeats and write down what changes on each repetition.
  3. Read one page of documentation for a function you have never used and write, in one sentence, what it takes in and what it gives back. Any language. The skill being practised is reading a signature, and it is the one that transfers to every language you will ever meet.
  4. Read the two extension sections at the end of this class, which are hello world in ten languages and where each language came from. They are reading rather than a lecture: ten minutes, at your own pace, before you arrive. Bring one question about them. The class spends ten minutes on your questions and none on delivering material you can read faster than I can say it.

What to bring#

Laptop with Python 3 running. A text editor you have actually configured: VS Code is the default and is free. The two surprising results from task 1.

The calculations this class asks for, with the working shown. Use them to check your arithmetic, never to replace it: the assessment asks for the method.

Number bases, bits and ranges

Floating point precision

Frames, timecode and duration

The part of this you can only learn by doing it. Everything here runs in this page, keeps your work in this browser, and is marked by tests rather than by anybody. A failed run costs nothing, which is the only condition under which people take the risks that teach them something. 4 more sit inside the class itself, at the point the idea is taught.

Retrieval, not rereading. Everything here is self-graded, stored in this browser only, and reported to nobody.

Spot the myth

Read the code

Numbers drill