This section will talk about basic programming concepts, if you want the easiest way to start programming I would look into the Python section, which will detail how to use python for all these concepts. This section covers programming more holistically, and will be more difficult than just learning a language to start with.

Programming Languages

Computers communicate using electrical signals, these signals are then abstracted into binary. This allows programmers to control these signals in easier to work with ways. Programming languages are built on top of layers and layers of existing firmware and operating systems. Programming languages let you define programs (also called applications or binaries) that run in order to do something. Anything you run on your electronic devices today is the result of a programming language.

Markup vs Programming languages

Programming languages are Turing complete, this is a fancy name for meaning it can be used to do whatever you want. The intention with programming languages is to create programs/apps that do things. Markup languages instead define what should show up. For example the language that is used in PDF’s or on webpages are markup languages. They don’t actually do any processing, instead it tells the computer where to draw things on the screen that you want to show the user.

Source Code, Binaries, and scripts

Source code are the actual files a programmer works with to create binaries. Binaries (not to be confused with binary) are software that can be run by a computer. The source code is essentially an easily readable set of instructions, which the computer then compiles (using a compiler) into ā€œmachine codeā€, which is what the computer then actually runs. Binaries are also called:

  • applications, or apps
  • scripts
  • executables or execs

Pseudocode

For this section I will use Pseudocode, this is a fancy name for ā€œI don’t want to write real codeā€. Essentially it will be a mix of code syntax and plain English to make it easy to read. It also lets me explain topics and syntax from multiple language at once.

Compiled vs interpreted

There are various different types of languages. Compiled languages (like go, C, Rust, etc.) require you to compile your code. This process takes a few steps usually, and results in a binary that is pure machine code. This means once it’s compiled any similarly configured system can just run the binary. This means the flow of your development is:

  1. Write source code
  2. compile
  3. Run the resulting binary

Typically compiled languages have the tradeoff of taking longer to be able to initially run your code, however they are typically also more optimized than the other option, which is interpreted languages. Interpreted languages (Java, python etc) instead allow you to compile your code into an intermediate language (or Bytecode. From there if people have the language installed they can execute the intermediate language. This is usually faster than compiling to machine code because the language doesn’t care about having to make sure everything necessary to run is included. Instead it just includes what is necessary for people to run who have the language installed already.

So for example if you write a go program and compile it for windows you can send the resulting executable to someone on windows running the same architecture, and it will work. If you instead write in Java then the result you send them can only be run in java, or you have to include the entire java runtime for them to be able to run it.

Python takes this a step further where to run python code you actually can’t compile it at all, to run python code you have to use the python binary, and it will then do the Bytecode and machine code conversions on the fly for you when you run the program.

Runtime/environment

Your runtime/environment is the actual language that runs your code. For languages that compile to machine code there isn’t really an environment after compiling. For languages that run in a REPL or use Bytecode a runtime is what actually executes the code you type in.

REPL

REPL (Read, Eval, Print, Loop) is a special way to execute code. It is mostly used for testing, but it is possible to run full programs using it. REPL works by running your code line-by-line as you type them. For example each >>> would be a statement, and underneath is the printed result:

>>> x = 4
4
>>> x + 10
14
>>> x += 4
8

So as you can see the language Reads your code, Evaluates it, Prints the relevant result, Loops to wait for the next input. This method is also available for some compiled languages, though typically through third party libraries (i.e. gore for go).

Transpiling & Code Generation

A transpiler is a program that takes in code of one type and converts it to some other type of code. Sometimes the word is also used for transpiling markup languages. Essentially we want to take some text and convert it to text that is useful for us. A transpiller specifically tends to do this using the same methods that Compilers (TODO) use.

Code generation is instead a method of creating code based on some input. For example ezcv is a program that takes in information about you and generates HTML/CSS/Javascript for it. Essentially because source code is just text, we just need some code to produce text for us. For example here is a code generator that takes in your name and would generate a python file to print it:

name = input("Type your name")

write_file(content="print({name})", filename="print_name.py")

This takes in your name from some sort of input, then writes a file called print_name.py with the source code print(name).

Bytecode

Bytecode is a low-level, platform-independent representation of a program’s source code that has been translated from a high-level programming language. Instead of being directly executable by a computer’s hardware, bytecode serves as an intermediate step. You generate bytecode from source code and then the language runtime will actually run the code. It is typically generated by a compiler or an interpreter and consists of compact, binary instructions that are designed to be efficiently interpreted by a virtual machine specific to the programming language.

Bytecode in theory allows for greater portability of software, as it can be executed on any system equipped with the appropriate virtual machine, providing a level of abstraction between the application and the underlying hardware architecture. For example let’s say we have the code:

print("hello")

This code is easy to read and friendly, but if we were to put this code in python and get it’s resulting bytecode (using dis), it looks like this:

1         0 RESUME                   0
 
2         2 LOAD_GLOBAL              1 (NULL + print)
		 14 LOAD_FAST                0 (text)
		 16 PRECALL                  1
		 20 CALL                     1
		 30 POP_TOP
		 32 LOAD_CONST               0 (None)
		 34 RETURN_VALUE

This bytecode could be taken and run anywhere that supports python (though usually you just run python from it’s source code, and don’t even see this step). This code would then be transpilled into the machine code for your system. This can be handy for interoperability, and for optimizations that are cross-platform.

Node-based

There is one other paradigm of languages that is newer that exists. Node-based languages are languages that use nodes to visually connect your data processing. Under the hood these are fancy transpillers, whatever you create visually will generate some code, and then it will be processed however that language works. These nodes will each typically represent 1 function, and then will have ways of passing information between them. For example imagine a program where a function gets someone’s name and birthdate, then sends that into another function which shows ā€œhappy birthdayā€ if it’s their birthday. The pseudocode might be:

info = get_user_info() // Returns some info

if info.birthday == Today:
	say_happy_birthday()

In a node-based language it might look something like this:

For example:

Comments

Comments are what they sound like, they don’t do anything and they’re there to let you add comments for yourself and other developers to read. This can be handy (especially when starting) to provide information that is not easily ascertainable by the code. A comment can be on it’s own line, or ā€œinlineā€. inline comments will go after some code. Comments can also be single-line, or multiline. In the example below the comment character will be //, which means anything after // will be a comment. For example:

// This is a signle line comment

some_code // This is an inline comment

However there are various different comment characters that are used for example:

# This is jused in python, bash, YAML etc.
// This is used in C, Rust, Javascript etc.
-- This is used in SQL, Haskell etc.
<!-- This is used in HTML, XML etc. -->
; This is a comment in assembly, etc.
! This is a comment in FORTRAN, etc.
% This is a single line comment in Erlang, LaTeX, etc.

And multiline comments can be different:

"""This is a multiline comment in
	- python
"""
/* This is a multine comment in
	- C
	- Rust
	- Javascript
	- CSS
	- etc.
*/
{-- This is a multiline comment in
	- Haskell
--}

For my pseudocode I will use // for comments and /* */ for multiline comments.

Variables

When working with code you will inevitably want to store some information. To store information we use variables. Variables are basically labels we can use to refer to information more easily. Different languages have different rules about how to create variables, and how to use them, but every language has variables in some form.

Assignment and initialization

When you want to use a variable you need to create it. The simplest form of this in many programming languages is to put the label (variable name) on the left, and then an = and then the value. For example:

name = kieran

You can then typically reference this later in the file using the label. For example here might be some math:

x = 4
y = 3

z = x + y // z is 7

Mutability

Mutability is the concept that you can change variables. Some types of data you store are able to be mutated so that their content can be changed, others cannot. If a variable cannot be changed it is called an immutable variable. For example here is a mutable variable:

x = 4

x = 5

In some languages (like rust) values are immutable by default and you have to specify mutable values.

mut x = 5 // x can be mutated

y = 5 // y is immutable

Constants and immutable values

Constants exist in some languages, constants cannot be updated regardless of the type used. These are good for things that don’t change (like the value of PI, or the gravitational constant). Most languages your variables are mutable. In these languages you can sometimes specify variables as immutable with constants, or other language constructs like readonly:

readonly x = 5

const PI = 3.14159

Scoping

Variables don’t exist forever. If they did then long running programs would be very inefficient. What programming languages do instead is they scope variables, so they get deleted when they’re no longer needed. The scoping rules, and how they apply differ by language.

This also helps to avoid some common issues that might come up with variables. For example lets say you have some code that uses the variable name then later you have some code that also uses name. In this case whichever one comes last would override the other. However if they are in different scopes, then they can be used independent of one another. Often for example you can have a program where name is used in one file, and name is used in another file, but since the variables are scoped to each file they don’t conflict. For example:

file1.name // Kieran

file2.name // Jamie

In this case code in file1 will get Kieran when they use name and file2 would get Jamie when they use name. Scoping is also heavily tied to Conditionals , and Functions.

Data Types

Not all data is formatted the same. Data types are the basic building blocks that let you define what data looks like. It gives information about what you’re trying to store and effects performance, and what information you can put in a variable

Dynamic vs Strict Typing

Dynamic languages will allow you to create variables without stating a data type explicitly, instead they are inferred, for example:

x = 4
y = 3

z = x + y // z is 7

In this case the type of the data is inferred meaning when x is assigned to 4 it’s inferred to be an Integer. In other languages you have to explicitly state the data type. If you have to state the type it’s referred to as static typed, whereas ones without needing to specify the type are called dynamic typed (or duck typed sometimes). For static languages, this is an example of how you define a variable:

// type label = value
int x = 4 // Rust, C and other languages use this format

// label:type = value
x:int = 4 // Typescript and others use this format

Some languages can let you specify when you want to infer vs be strict. For example in go := means assign a variable and infer it’s type:

// Explicit typing
int x = 4

// Inferred tpye
x:= 4

Some languages will also allow you to declare a variable without a value, which can be initialized with a value later. For example:

int x

x = 4

Primitive vs Derived types

Primitive types are data types that are included by default in most languages. They are the essential data types used to build programs. Every type we cover in this section will be a primitive type. A derived type is a type that is programmer created and not part of the language. You can create these using classes/structs/enums.

Integer

Integers are normal whole numbers (no decimals). So for example here are some integers:

x = 5
y = 32
z = -256
q = 0

In many languages you will find integers being referred to as int.

Sizing

Integers are often split up by sizes. This can help massively with optimization, but can make things more complicated. In languages that specify them usually there will be an i with a number. This number will typically indicate the bits:

SymbolDescriptionMin and Max
i88 bit integer (1 byte)-128 to 127
i1616 bit integer-32,768 to 32,767
i3232 bit integer-2,147,483,648 to 2,147,483,647
In some languages they instead have short, long, long long and other shorthands for integers. You would need to lookup the specifics in each language to find these, but typically they will correspond to a number that has a certain number of bits.
Signed vs Unsigned

An unsigned integer is an integer that can only be positive. A signed integer is an integer that can be positive or negative. In many programming languages you will see an unsigned integer as starting with U:

SymbolDescriptionMin and Max
u88 bit integer (1 byte)0 to 255
u1616 bit integer0 to 65,535
u3232 bit integer0 to 4,294,967,295
As you can see compared to the signed integers above, unsigned integers can hold larger numbers for the same number of bits.

Float/Floating Point

Floats (floating point numbers) are decimal numbers. This includes positiveĀ andĀ negative numbers. One important thing to keep in mind while working with floats is that every language has a limited precision (whole site dedicated to this). This means it will only be accurate to a certain number of digits. There are also common rounding errors, like the famous 0.1+0.2 == 0.30000000000000004.

Collections

Collections are a data type that is used to hold multiple other data types. For example lets say you wanted to keep track of all of the names of items in a player inventory. You could put them into a collection to keep track of all of them in one variable, instead of a separate variable for each item! There are tons of different types of collections, some of the names are not always exactly the same across languages, so keep that in mind when looking at this info!

Lists

Lists are a dynamic collection. They basically let you add as much (besides memory constraints) data as you want. In strongly typed languages (ones where you have to specify types), they can only have 1 data type, in most other languages they can take whatever data you want. Here is an example of what it might look like in aĀ non-strongly typed language:

ages = [18,21,18,19,20]

This gives you a list where

array

You can then access the element using it’sĀ index. The index is essentially the number that indicates where in the list a value is (starting from 0). You can access this usingĀ ages[index]. So if you wanted to access theĀ secondĀ element you could useĀ ages[1]Ā (which in this case would be 21):

array access

Traditionally lists will have methods to add, remove, and pop. Add and remove are self explanatory, but pop is probably a new idea. Pop will run and it will delete an item from the front of a list and then return that value.

Arrays

Arrays are one of the most basic collection types. These are typically quite restrictive, but very fast. You will have to specify the length of an array as well as the types it will contain.

So for example if you want to store the ages of 5 people as integers you might do something like this:

ages[5]<Int> = [18,21,18,19,20]

This gives you an array where:

array

You can then access the element using it’sĀ index. The index is essentially the number that indicates where in the list a value is (starting from 0). You can access this usingĀ ages[index]. So if you wanted to access theĀ secondĀ element you could useĀ ages[1]Ā (which in this case would be 21):

array access

This data type can be different in different languages, Arrays in JavaScript are actually Lists for example.

Sets

Sets are collections that requireĀ uniqueĀ items. This is implemented different ways in different languages, but for example:

words = set("hello", "oranges", "hello", "great")
print(words) // ["hello", "oranges", "great"]

Even though ā€œhelloā€ was given twice it only appears once. This makes sets great for checking if something exists. Imagine you are searching through a book, and want to check if the book has the word ā€œdisparateā€ in it. Now lets say there are 900 times the word ā€œtheā€ appears. To search all the words you have to search through all 900 repeats of ā€œtheā€, but with a set there’s only 1 occurrence of ā€œtheā€.

Tuple’s

Tuples are similar to lists, except once the values have been added they can’t be changed (it’s immutable). So you can’t add items to a tuple, it’s stuck how it is. This can be handy for data you don’t want to let be modified. For example someone’s birthday:

birthday = ('oct', 29, 1998) 
birthday[2] += 1 # ERROR

You don’t want to accidentally have someone add something to the birthday because the data doesn’t change! This is often used in databases since the data being returned should be considered read-only, and copied into something mutable if people want to make changes.

Associative Arrays/Maps/JSON/Dictionaries

These are the first collection that does not use indexes for it’s elements. All of these are different names for what are called key-value stores. Instead of using indexes you can set your own ā€˜key’, which maps to a value. This lets you represent abstract data with it’s own labels easily. For example information about a user:

user = {"name": "Kieran", "age":24, "developer":true} 

user["name"] # "Kieran"

Under the hood this uses Hashing to be more efficient. Additionally a blog post about creating these data structures from scratch can be found here.

Text types

There are several ways to represent text in most programming languages based on what you need.

Char

A char is a single character. In many languages this type is actually an integer under the hood. There will be a list where each character has a number corresponding to it and you can convert back and forth between them. For example in python you can see this text-number conversion with theĀ ord()Ā andĀ chr()Ā functions:

ord("a") # 97 chr(97) # 'a'

Other languages like C you can just convert characters to integers and back natively:

char a = 'a';
 
int numericalA = (int)a; // Returns ASCII value of 'a'

In some languages Char’s and String’s are differentiated with ' and ", but in others this is not the case.

String

Strings are what we think of as normal text. They allow for the storage of text, in some languages this can be text of any length, in others it’s a fixed-length amount of text. In some languages strings consist ofĀ BasicsĀ ofĀ Char’s, in other’s they’re their own custom type. For example you could consider ā€œhelloā€ to be either of the below:

['H','e','l','l','o']

"Hello"

Whichever you choose in many languages they’re still treated as an array-like data type. This allows you do loop over characters to do processing.

Whitespace Characters

In strings there are often times where you need to include some sort of whitespace. For example this might be inserting a newline character in order to simulate pressing the enter key in most text editors (\n), or a character to indicate the same effect as pressing tab (\t). These are called whitespace characters. They tend to be pretty universal.

For example:

 greeting = "Hello there!\nMy name is Kieran. Here are my favourite hobbies\n\t- Skiing\n\t- Coding"

This would result in:

Hello there!
My name is Kieran. Here are my favourite hobbies
	- Skiing    
	- Coding
Formatting

With strings in most languages there are various ways of doing formatting. Formatting allows you to inject data into strings. This is incredibly powerful, but can also be very dangerous.

For example let’s say you want to have a template email where the variables for recipient (person receiving email) and sender. In python you can put anĀ fĀ in front of a string to turn it into a ā€œformat stringā€, from there you put the variables inside squiggly braces ({}), and they will be replaced by the values:

sender = "Kieran" 
recipient = "you" 
 
email = f"""Hello {recipient},
 
We appreciate you reaching out, we are not open on the weekend and will re-open on monday at 9am to address your email. 
 
Thanks,
{sender}"""

The same can be done in javascript with strings that use a backtick (`), then stating which should be replaced by variables using squigly braces that have aĀ $Ā in front:

sender = "Kieran" 
recipient = "you" 
 
email = `Hello ${recipient}, 
 
We appreciate you reaching out, we are not open on the weekend and will re-open on monday at 9am to address your email. 
 
Thanks,
${sender}`
Encoding

Text under the hood is represented as numbers for each character, there are then different sets of numbers that allow for different sets of characters. These are called the encodings. Different systems use different encodings in order to allow different characters.

For example ASCII is a very simple encoding that allows 127 different characters. In ASCII ā€˜a’ would be 97. Unicode is a set of different encodings that allow for a lot more characters. UTF-8 allows 1,112,064 characters, in our example case ā€˜a’ would still be 97, but this is not the case in every encoding. Also because UTF-8 supports more characters you have to be careful with conversions. Japanese characters work in UTF-8 for example, butĀ notĀ ASCII.

We have a page dedicated to encodings here.

Booleans

Booleans are values that indicate if something is true or false. These can be used in conjunction with Conditionals to tell a program what to do.

A trivial example would be the current season:

is_summer = False
is_winter = False
is_fall = False
is_spring = True

Based on this the program might use a conditional to show a certain theme based on the current season. This can also be used for things like user settings:

dark_theme = true

In some languages (like C & python) booleans are actually just integers. For example here are the various representations of true and false in different languages:

// True
true
Yes
1
TRUE
True

// False
false
No
0
FALSE
False
Boolean Logic

Logical operators can be used to make a series of statements and only let them be true based on which operator is used. Traditionally this uses Booleans, which can also take the form of an Integer in languages like C and python. Here are the Boolean logic operators:

NameWhat it meansCodeSymbols
ANDIf both values are true, the result is true, otherwise False
true && true // True

true && false // False

false && true // False

false && false // False
&&, and, AND
ORIf one value is true, the result is true, otherwise falsetrue || true // True

true || false // True

false || true // True

false || false // False
||, or, OR
NOTInvert the operation (true is false and false is true)!true // False

!false // True
!, NOT, not,
XORIf the values are opposite then true, else false, this is a bitwise operation meaning it’s based on 0’s and 1’s in binary
True ^ True // False

True ^ False // True

False ^ False // False
^, XOR, xor

This sort of logic is fundamental for binary operations, Logic Gates (TODO) and much more.

Comparison Operators

Comparison operators return a boolean value after comparing two values to see if a statement is True or False

NameDescriptionPythonJS
GreaterChecks if something is greater than something else1 < 3 # True1 < 3
lessChecks if something is less than something else3 > 1 # True3 > 1 // true
Greater than or equal toChecks if something is greater than or equal tp something else1 <= 3 # True1 <= 3
Less than or equal toChecks if something is Less than or equal tp something else3 => 1 # True3 => 1
Truthyness

In many languages you can do checks against values of other data types to see how ā€œtruthyā€ they are. This is usually done to indicate if a value is ā€œemptyā€ or not. For example:

"" // Would be false because it's an empty string
0  // Would be false because it's 0
[] // Would be false because it's empty
Referential

A referential check is done to see if a variable is exactly the same object as another variable. So not just that the value is the same, but that the two variables are actually talking aboutĀ the exact sameĀ spot in memory. In this case we will use is as the keyword for a referential check:

a = [1,2,3]
b = a
c = [1,2,3] 

a == b // True
b == c // True
a == c // True 

a is b // True
b is c // False
Value and Type

In some languages when you are checking a value the value itself will be derived from different types. For example :

1 == True // True
0 == False // True

In this case True gets converted to an integer (1) in this case, which we then check for equality and the equality is now true. Sometimes with some languages this goes further like:

"1" == 1 // True

In some languages we have an option to equality check while forcing a specific type to be checked. We do this by adding an extraĀ =Ā to our checks (called a strict comparison):


"1" === 1 // False

Null, None & undefined types

Many programming languages have some sort of ā€œNullā€ value. These values can be called different things, but they essentially are there to state nothing. This may seem entirely useless at first, after all who would want to reference nothing in their programs? Well, it’s actually very useful for a few reasons. Typically most people use Null as an initialization state. For example you want to create a variable you intend to use later, but have no value to put in it yet. This can be handy because it means that other programs that might use that variable can just check every so often if the value is still Null as a way to wait for it to become initialized.

It’s also useful to do this for space savings. Unlike other placeholder values most Null’s take up basically no space (in some languages literally no space). This means you can save all that space in memory until you actually need it.

Pointers

A pointer is a way to specify a variable that ā€œpointsā€ to another value. This is important for languages that aren’t memory managed (like C). In languages that allow pointers you can specify an address that a pointer references. Whatever is available at that address can be manipulated as if it was the variable. For example:

a = 5

b = *a

b = b - 3

print(a) // 2

This allows you to share state as we can see above where we set b = *a, which is saying that b is a pointer to a and so any changes to b will affect a. This is also used under the hood in all other languages, but many languages (like python) don’t allow you to directly modify these pointers.

Conditionals

In programming we don’t always want to execute the same code. Sometimes we want to execute code based on something. We might want to check if someone has a premium account before allowing them to access a song, or check if they’re in a certain country etc. Conditionals are the way we do these checks, which allow us to conditionally run code based on some sort of check.

Under the hood these checks operate based off Booleans. All of the operations done will evaluate to a True or False value which can be checked against.

If/Else/ Elif or Else if

The main statement used for conditionals is the if statement. This statement is made up of two parts, the condition and the body. The body will only execute if the condition is True. For example theĀ print()Ā will always execute:

if True{
	print("True!")
}

In this caseĀ print("True!")Ā is the condition body it is wrapped in {} to indicate what should run if it’s True. For example if we nest some statements:

if premium{
	if isAdult{
		print("A premium Adult")
	} else {
		print("Just is premium")
	}
}

In this case if premium AND isAdult then we get A premium Adult printed. You can see that each set of {} corresponds to a different condition, and will only run if that condition is true. This is called a scope. In some languages scopes are instead defined by indentation, like python:

if premium:
	if isAdult:
		print("A premium Adult")
	else:
		print("Just is premium")

In this case each level of indentation is a separate scope. From here you can createĀ control flows, which are statements that allow for multipleĀ branchesĀ of code where one branch will activate based on a condition. For example code in python that changes based on the current season:

isSummer = false
isWinter = false
isFall = false
isSpring = true
 
if (is_summer){
    print("It's warm")
} else if (is_spring){
    print("It's raining")
} else if (is_fall){
    print("It's getting colder")
}else{ 
    //Assumes isWinter is true
    print("It's snowing!")
 
} 

Some languages also combine the keywork else if into the abbreviated elif.

Functions

Functions are a way to reuse code efficiently. It allows you to define a set of steps of code that should be run when the function is ā€œcalledā€, along with a name.

Using existing functions

Using (or ā€œcallingā€) existing functions works the same inĀ mostĀ languages. You find whatever the name of the function is, and you typeĀ function_name(), some functions take in extra data (calledĀ parameters), so you can ā€œpassā€ the function this data when you call it.

For example here is how you print some text to the screen in using aĀ print()Ā function:

print("Hello World")

In this case we are using a String parameter to tell the function what to print. However there are many times that our functions take in no values, in these cases the functions effects are called side-effects. For example, let’s say we have a function to restart a computer called restart():

restart()

We have no parameters to pass in because we just want it to effect something else that exists.

Anatomy of functions

To create a function there are several parts you need, all of the parts work to define what the function does, and how it does it. These parts are:

  1. The definition
  2. The body

Within each part there are several sub-parts to consider as well.

Function Definition

This is where you define the function name (and optionallyĀ Parameters). To define a function you will need to use the definition keyword in whatever language you are writing, and you will need to provide a name.

For example let’s sayĀ funcĀ is the definition keyword. So if we were to define a function that will tell you what the weather is today calledĀ todays_weatherĀ we could do it like this:

func todays_weather(){
  // This is where the function body will go
}    
Naming conventions

Languages will have different naming conventions. YouĀ don’t have to follow these, but it’s recommended. In python, rust and some others functions are usually ā€œsnake caseā€, this means the names are all lowercase, and you separate words with ā€œ_ā€. For example first name might become first_name.

Javascript, Java and others typically uses camelCase, instead of separating different words you just capitalize the first letter. So for first name it would become firstName. This changes nothing about the code that is run with a function, it’s just a convention people follow in languages to standardize how code looks.

Parameters

Parameters are data you can pass to a function in order to be able to re-use code more effectively. For example you might specify aĀ nameĀ parameter that is used to pass the user’s name to a function. Imagine we have a function calledĀ greeting()Ā that takes this name parameter, it might look like this in python:

def greeting(name):    
	# Function body here

and like this in javascript

function greeting(name){    
	// function body here
}
Multiple parameters

You can specify multiple parameters for functions, in most languages you can do this with a comma seperated list of names for the parameters. For example a functionĀ game_over()Ā that takes in a winner and loser parameter. First in python:

def game_over(winner, loser):    
	# Function body here

Now in javascript aĀ gameOver()Ā function with the same parameters:

function gameOver(winner, loser){    
	// Function body here
}
Default and optional values for parameters

You can also specify parameters that have default values. This can be used to make common situations your functions will be run under easier, but also can be used to make some parameters optional if the value is still the default when run. Here is a functionĀ feedback_form_submission()Ā that takes in data from when someone fills out a form in an app, it takes in the email of the user, and optionally a comment variable:

def feedback_form_submission(name, comment=""):    
	# function body here 
	
# Can now call the function with a comment
feedback_form_submission("John Doe", "What an awful event") 
 
# Or call it without a comment
feedback_form_submission("Kieran")

In python these are also called keyword arguments (kwargs for short). In javascript it would look like this

function feedback_form_submission(name, comment=""){    
	// function body here
} 
// Can now call the function with a comment
feedback_form_submission("John Doe", "What an awful event") 
 
// Or call it without a comment
feedback_form_submission("Kieran")
Typed vs Untyped

There are different types of languages, strongly and weakly typed. Strongly typed languages require you to tell the language what the types of each parameter are (integer, string, list etc.). Javascript and python are weakly typed languages, so this isn’tĀ required, but python does offer type hinting, which can be useful in ambiguous situations. If you have never heard ofĀ type hints, they are used to define what data type each of the variables/attributes should be. For example a string variable called name would look like this:

name:str

And if the variable can more than one type you have the first type on one side of a | and then the other option for the type. SoĀ str | NoneĀ would mean the variable could be a string, or aĀ NoneĀ like this:

name: str|None

We could then apply this to our parameters like this:

def feedback_form_submission(name:str, comment:str=""):    
	# function body here

Function Body

This is where you define the code that should be run when someone calls a function. This is defined by some sort ofĀ scope identifier. These scope identifiers change per language, but there are two common ones.

Indentation

The indentation level of the code is used to identify the scope in several languages. For example in python let’s define a function calledĀ greet_person()Ā which takes in a name parameter which is a string and uses it to greet them:

def greet_person(name:str):    
	# Function body starts here    
	print("Hello there")    
	print(name)    # And ends here
Squiglies

Squiflies (not the actual name) are often used as scope identifiers in languages. For example in javascript you define where a function starts and stops with everything inside squigglies ({}), so a function starts atĀ {Ā and ends atĀ }. Here is an example of a function that takes in a name, prints a greeting, then the name:

function greetPerson(name){    
	console.log("Good morning")    
	console.log(name)
}

This means when someone callsĀ greetPerson("kieran")Ā only the twoĀ console.log()Ā statements will run!

Returning

For some functions you will want to return a resulting value. The easiest example of this is returning a number from an addition function:

def add(x, y):    
	return x + y

or in js

function add(x, y){    
	return x + y
}

Type hinting returns

You can type hint your returns the same as you can with your parameters in python. You simply add a little arrowĀ ->Ā before you start the function:

def add(x:int, y:int)->int:    return x + y

This tells people what to expect when they retrieve the value of a function and store it in a variable

Recursion

Recursion is the technique of running a function within a function definition. This can be used to solve problems. For example the Fibonacci sequence can be generated using:

func fibonacci(n){
	if n == 0{
		return 0
	} if n == 1{
		return 1
	}
	return fibonacci(n-1) + fibonacci(n-2)
}

So let’s step through what happens if we were to provide n=3:

fibonacci(3):
  1. Return fibonacci(3-1) + fibonacci(3-2)
  2. Do the left first fibonacci(3-1):
	  1. fibonacci(2)
		  1. return fibonacci(2-1) + fibonacci(2-2)
		  2. Do the left first fibonacci(2-1)
			  1. returns 1
		  3. Do the right
			  1. Returns 0
		  4. 1 + 0 = 1
  3. Do the right
	  1. fibonacci(3-2)
		  1. returns 1
  4. return 1 + 1

fibonacci(3) == 2

To create a recursive function we need:

  1. Base case(s); When the function stops making recursive calls to itself. If we don’t have this it will recurse infinitely
  2. The recursive case(s); When the function should make the recursive calls

Here is the fibonacci function annotated with comments to indicate the base and recursive cases:

func fibonacci(n){
	// 1. Base case(s)
	if n == 0{   // Base case 1
		return 0
	} if n == 1{ // Base case 2
		return 1
	}

	// 2. Recursive case
	return fibonacci(n-1) + fibonacci(n-2)
}

Effect on scopes

As mentioned earlier functions have an impact on Scoping. For example there’s a separate scope inside a function:

x = 5

function doStuff(){
	x = 3
	// x is 3
}
// x is 5

Some languages will allow you to modify values in outer scopes, and in those cases x would be 3. But in most languages x would be 5 at the second comment. Look into the language specifics of your language to understand this.

Loops

Loops are a concept in programming that allows you to run some code for a defined number of times. This means if you have an operation you want to run 1000 times, or maybe run some code for every user in a database, or show a menu until someone makes a choice in a game, loops are what you want.

Parts of a loop

Loops have two main parts, the loop definition, and the loop body. The loop definition defines how long the loop should run for, and/or what data is available inside the loop. The loop body defines what runs inside the loop. There are two popular ways this is done in languages, indentation or squiggly braces:

*Not real code

loop definition:    
	loop body 
 
loop definition{    
	loop body
}

In the first (used by languages like python) everything that is indented will run for eachĀ Iteration of the loop, in the second everything inside the {} will run.

Iteration

Iterators is the name given to types of data that are designed to be looped over. For example if you have some text then in most languages that will be an iterator where you will start at the first letter and be able to loop through each letter one at a time.

You can also usually create your own iterators so that for example if you have some code generating a slideshow you could create an iterator that loops through each slide. The only thing that matters is that you can define a start, an end, and some way to get from one item to another (sometimes items in iterators are called elements).

Iterators

Iterators is the name given to types of data that are designed to be looped over. More details can be found here.

loop Types

There are several different types of loops that exist and are used in different situations. Most problems you run into can be approached with more than one option, so pick which one you think works best for you.

For

For loops run for a length of time defined by what you are trying to loop over. There is a section below that explains when to use each!

C-style

C-Style for loops are what most languages call for loops. They will allow you to define a variable that starts at some value, define an end condition and then loop until the variable equals that condition. Below is an idea of how this might work:

*Not real code

index = 0

for index until index is 10:
    print("Hello")
    index += 1

In the above example index starts at 0, on each iteration it will print hello, and then the index has 1 added to it. The loop runs until the index variable is 10 which is when the loop ends.

This can be done in python like so:

for index in range(10):
    # Python automatically starts at 0 
    # & adds 1 to index per itteration
    print("hello")

or Javascript like so:

for (let index = 0; index < 10; index++) {
    console.log("hello");
}
Foreach

For each loops are a bit different than regular for loops. In a regular for loop you will use integers (numbers) to control how the loop works. Whereas a foreach loop will loop over each item/element in an iterator.

For example lets say you have a shopping list, and want to print each item in the shopping list, you can do something like this:

*Not real code

shopping_list = ["eggs", "ham", "spam"]
foreach item in shopping_list:
    print(item)

This loop would print ā€œeggsā€, then ā€œhamā€, then ā€œspamā€. By default python is one of the only languages that uses foreach as it’s for loop. So here is the above example in python:

shopping_list = ["eggs", "ham", "spam"]
for item in shopping_list:
    print(item)

When you use the range() function in python it actually just generates a list to loop over with a foreach loop. So these two would be the same:

for index in range(10):
    print(index)
 
for index in [0,1,2,3,4,5,6,7,8,9]:
    print(index)

foreach is implemented differently in different languages. Javascript for example runs the loop directly on the data you want to loop over:

shopping_list = ["eggs", "ham", "spam"]
 
shopping_list.forEach(item => {
    // This would be your "loop body"
    console.log(item)
});
When to use each

Both of these two for loops have advantages and disadvantages. But here are some rules of thumb

C-style: If you want to make modifications to items, just want to use numbers or foreach isn’t available

foreach: If you want to only read data. Some data types will let you make modifications in foreach loops, but not all of them and not in every language. If you have a list of numbers for example and you add 1 to it, then that change won’t save in a lot of languages. Here’s a python example:

numbers = [0,1,2,3,4,5,6,7,8]
 
for number in numbers:
    number += 1
 
print(numbers) # still [0,1,2,3,4,5,6,7,8]

For this to work you would need a c-style loop:

numbers = [0,1,2,3,4,5,6,7,8]
 
length_numbers = len(numbers)
 
for index in range(length_numbers):
    numbers[index]  += 1
 
print(numbers) # now [1, 2, 3, 4, 5, 6, 7, 8, 9]
while

while loops are used to run until a certain condition is met. They basically run until whatever condition specified is true. So for example this might be a while loop that would run 10 times:

*Not real code

number = 0

while number < 10:
    number += 1

In this case the loop would run 10 times, then on the 10th run number would be 10 and number<10 would be false, which would end the loop. This can be useful for tons of things, but the most common is game loops and menus. In games you can have something like:

*Not real code

game_over = false

while not game_over:
    play_game()

Which would run until the game_over variable is set to true (perhaps when a player dies). This can be done with menus as well to wait for someone to select something, or anything that can be controlled with a boolean!

Here are the above examples in python:

number = 0
 
while number < 10:
    number += 1
 
game_over = False
 
while not game_over:
    play_game()

and in javascript:

number = 0
 
while (number < 10){
    number += 1
}
 
game_over = false
 
while (!game_over){
    play_game()
}

Infinite loops

You need to make sure your while loop can end. Most programming languages will not stop you from making a loop that never ends!

loops and collections

These sorts of loops can be very handy when used with Collections. Since collections take multiple steps if you want to run code on everything in them they are a perfect candidate for loops!

For loops

Let’s say for example someone updated their difficulty in a game so you want to increase enemy HP, you could do something like this:

*Not real code

index = 0

enemies = [enemy_1, enemy_2, enemny_3]

for index until index is length(enemies):
    increase_hp(enemies[index])

When accessing values in a list/array (enemies) you can access each item by it’s index. So in this case enemies[0] would give you enemy_1. Since we start at 0 (all arrays/lists do) and then go until the index is the length of the list, we go through each element and run increase_hp() on it. So these two are the same:

*Not real code

increase_hp(enemies[0])
increase_hp(enemy_1)

Here is the same example in python:

enemies = [enemy_1, enemy_2, enemy_3]
 
length_of_enemies = len(enemies)
 
for index in range(length_of_enemies):
    increase_hp(enemies[index])

and in Javascript:

enemies = [enemy_1, enemy_2, enemy_3];
 
lengthOfEnemies = enemies.length;
 
for (let index = 0; index < lengthOfEnemies; index++) {
    increase_hp(enemies[index]);
}

While loops

Let’s say for example someone updated their difficulty in a game so you want to increase enemy HP, you could do something like this:

index = 0

enemies = [enemy_1, enemy_2, enemny_3]

while index < length(enemies):
    increase_hp(enemies[index])
    index += 1

When accessing values in a list/array (enemies) you can access each item by it’s index. So in this case enemies[0] would give you enemy_1. Since we start at 0 (all arrays/lists do) and then go until the index is the length of the list, we go through each element and run increase_hp() on it. So these two are the same:

increase_hp(enemies[0])
increase_hp(enemy_1)

Here is the same example in python:

enemies = [enemy_1, enemy_2, enemy_3]
 
length_of_enemies = len(enemies)
 
index = 0
 
while (index < length_of_enemies):
    increase_hp(enemies[index])
    index += 1

and in Javascript:

enemies = [enemy_1, enemy_2, enemy_3];
 
lengthOfEnemies = enemies.length;
 
index = 0
 
while (index < lengthOfEnemies) {
    increase_hp(enemies[index]);
    index += 1;
}

Other aspects of loops

Sometimes you want more manual control over a loop. For example let’s say you want to end a loop early, or skip an item if some condition is true. There are built in options to most languages to do this.

break

Break can be used to end a loop early. This can be useful if you are looping over something, and want to allow the loop to stop running if the word ā€œstopā€ is encountered:

foreach word in words:
    if word == "stop":
        break

This would break out of the loop when stop is encountered or when it reaches the end of the list if stop isn’t there.

Here is an example in python:

for word in words:
    if word == "stop":
        break

and in javascript

words.forEach(word => {
    if (word == "stop"){
        break
    }
});

continue

continue can be used to ā€œskipā€ an iteration. For example lets say you want to add 1 to a number if it is even. You could do something like this to skip odd numbers:

numbers = [1,2,3,4,5,6]
length_of_numbers = numbers.length

index = 0

for index until index is length_of_numbers:
    if isOdd(numbers[index]):
        continue
    else:
        numbers[index] += 1

Here is an example of this in python:

numbers = [1,2,3,4,5,6]
length_of_numbers = len(numbers)
 
for index in range(length_of_numbers):
    if not (numbers[index]%2==0): # Is odd number
        continue
    else:
        numbers[index] +=1

and in javascript:

numbers = [1,2,3,4,5,6]
length_of_numbers = numbers.length
 
for (let index = 0; index < length_of_numbers; index++) {
    if (!(numbers[index]%2)==0){
        continue
    } else{
        numbers[index] +=1
    }
}

Additional Resources