Skip to content

Telling a Job What to Work On

A job that takes a value and hands one back, so one job can do a whole family of things.

  • Foundations

The divider from Unit 2 does the same thing every time. That is fine for a divider. Most jobs are not like that: you want the same work done to a different value each time.

So you give the job something to work on.

Handing a value in

Put a name in brackets after the job’s name. That name stands for whatever the caller hands over:

Code
DEFINE greet(who)
  SHOW "Hello, ", who
END

CALL greet("Sam")
CALL greet("Ada")
Output
Hello, Sam
Hello, Ada

One job, two results. Inside greet, the box who holds whatever came in with the call: "Sam" the first time, "Ada" the second.

That box belongs to the job. It holds its value while the job runs and means nothing outside, so a who anywhere else in your program is a different box that happens to share a name.

Handing a value back

A job can also give an answer. RETURN hands a value to whoever called, and the job stops there:

Code
DEFINE double(n)
  LET n = n * 2
  RETURN n
END

LET x = double(5)
SHOW x
Output
10

double(5) runs the job with n set to 5, and the RETURN sends 10 back. That answer lands where you wrote the call, so LET x = double(5) puts 10 in x. The assignment changes the job’s local n before it returns.

Notice the two shapes are different on purpose. CALL greet("Sam") does a job and expects nothing back. You use double(5) for its answer, so it sits where a value belongs.

The caller keeps its own value

Our notation passes a copy of a numeric value. Reuse double with a caller variable that also happens to be called n:

Code
LET n = 5
LET result = double(n)
SHOW n, " and ", result
Output
5 and 10

At the call, the caller’s n is 5. The job gets its own n, also 5. Changing that local copy to 10 leaves the caller’s n at 5. The returned 10 is stored in result. To replace the caller’s value, we would write LET n = double(n).

With n = 3, what do LET result = double(n) and LET n = double(n) leave in the caller?

The first leaves n = 3 and stores 6 in result. The second puts the returned 6 into the caller’s n. Updating the local parameter and assigning the returned value in the caller are separate steps.

This example uses numbers. Do not infer how a real language passes a list, shares memory or makes copies from the spelling of a parameter name.

Say what the caller can rely on

Compare greet with double. Before tracing either call, predict which one changes the display and which one supplies a number we can use in another calculation.

Compare their promises
Job Input Result for the caller Other effect
greet A name No returned value Displays a greeting
double A number Twice that number Does not print anything

We can check double(0) without drawing a screen: it should return 0. Changing it to print the answer instead would break LET x = double(5), even if 10 looked right on screen. The caller needs the result, not just a visible effect.

This small agreement is a contract: what goes in, what comes back and what else changes. Later, a drawing or sound routine also needs to say which state it changes and whether its work is finished when it returns.

Our pseudocode gives parameters local names. A machine language may pass them in registers or shared memory instead. Sinclair BASIC’s GO SUB does not create these local parameter boxes, and its RETURN resumes the caller without returning an expression. We carry the idea across, then explain how that language implements it.

For a concrete contrast, Write the repeated job once traces Sinclair BASIC’s numbered GO SUB and RETURN. Read its return-point explanation without running the preceding game. BASIC’s ordinary variables are shared with the subroutine; it does not supply this example’s local parameter copy or expression result automatically.

When it’s wrong, see why

  • The job always does the same thing. You named a value in the brackets but used a different name inside the job. The name in the brackets is the one that holds what came in.
  • You get nothing back. The job has no RETURN, or the program reached the END without passing one. A job with nothing to hand back is one you CALL instead.
  • You called it without the value it needs. CALL greet() does not meet this job’s contract: we must supply a name. Our notation does not invent a value for who; a real language defines how it reports or handles a missing argument.

What you’ve learnt

  • A job can take a value: the name in brackets holds whatever the caller hands over.
  • RETURN hands a value back, and the answer lands where you wrote the call.
  • A job you CALL does something. A job you use for its answer goes where a value goes.
  • The names inside a job belong to the job.

What’s next

We now have a useful set of ideas for building programs: instructions, order, output, memory, input, arithmetic, decisions, loops, lists and named jobs. One thing remains, and it is the most useful of all. In Unit 4 we find out what to do when a program does the wrong thing.