{ }codelper

Learn › TypeScript

Functions · 14

Functions

Bundle work under a name, take values and return a result — plus recursion.

A function is a named block of code.
It takes values (parameters) and returns a result.
The example below defines a function that squares a number and a factorial function that calls itself.

import { readFileSync } from "node:fs"; function square(x: number): number {  return x * x;} function factorial(n: number): number {  if (n <= 1) return 1;  return n * factorial(n - 1);} const n: number = Number(readFileSync(0, "utf8"));console.log(square(n));console.log(factorial(n));
stdin
4
stdout
16
24

Key points

  • Wrap code in a function when the same calculation is needed in several places, or to break a long solution into small pieces.
  • When return runs, the function ends right there.
    The lines below it do not run.
  • Passing a number copies the value.
    Changing it with x = 9 inside the function leaves the caller's variable alone.
  • Passing a list shares the same list.
    Adding to it inside the function changes it outside too (a C++ vector is copied when passed).
  • Recursion is a function calling itself.
    It shrinks a big problem into a smaller one of the same shape, and it must have a stopping case (n <= 1 gives 1).
  • Without a stopping case, or when it goes too deep, the program stops with an error or crashes, depending on the language.

How each language writes it

Pythondef square(x): plus indentation.
Without return it returns None.
You can only call it after the def has run (earlier is a NameError).
Recursion stops at about 1,000 levels with RecursionError
JavaScriptfunction square(x) { return x * x; } or const square = (x) => x * x;.
Without return it returns undefined.
A function declaration may sit below the call.
Too deep: RangeError: Maximum call stack size exceeded
TypeScriptJavaScript plus types: function square(x: number): number.
The type checker catches a wrong number of arguments
Javastatic int square(int x) inside a class; void when nothing is returned.
It can be anywhere in the class.
Too deep: StackOverflowError
C#Like Java: static int Square(int x) inside a class, void when nothing is returned.
Too deep a recursion crashes the whole program
C++Return type first, as in int square(int x); void when nothing is returned.
Define it above its use, or declare it first with int square(int x);.
Too deep a recursion crashes the program
CSame as C++
CraykonNo keyword: square(x) { return x * x; }.
It may sit below the call.
After a few thousand levels it stops and says the function was called too deeply

Common mistakes

No stopping case

def factorial(n):
    return n * factorial(n - 1)

→ It calls itself forever and stops with RecursionError. Other languages overflow the stack and stop or crash

Put a stopping case first, such as if n <= 1: return 1.

Calling with a missing argumentJavaScript

function square(x) { return x * x; }
console.log(square());

→ NaN — the missing x is quietly filled with undefined

Pass the right number of values.
Python (TypeError), Java, C#, C, C++, TypeScript (compile error) and Craykon ("2 values are needed but 1 was given") all tell you.

Changed inside the function, but the original is unchangedC++

void add(std::vector<int> v) { v.push_back(9); }

std::vector<int> a = {1};
add(a);

→ a is still {1} — the value went into a copy

To change the original, add &: std::vector<int>& v.

How languages differ
Factorials grow fast.
A 32-bit int holds only up to 12! (computing 13! with int in Java silently gives 1932053504), so the Java, C#, C and C++ examples return 64-bit long/long long (good up to 20!), while Python has no size limit and JavaScript and Craykon may be inexact beyond 2^53.

Practice