Programming Language Crash Course (Bootstrap Part 1)

This article is part of a larger series on How To Program Anything: Core Rulebook (Parent Series)

Preface

This article comes on the heels of two other posts I made much earlier about programming languages and computer memory.  The reason I haven’t written an “Introduction to Programming” tutorial yet (like linguistics, philosophy, and electricity) is two fold.  One, it’s the subject I’m the most expert in and that’s led to two, there’s a lot of information and background that goes into programming a device.  There’s mathematical background, there’s abstract concepts background, there’s how the dang computational devices work and what environment you’re programming in background.  I mean, the tutorials I gave on binary are just a the tip of the iceberg when it comes to how one might program a computer.  I’ve thought for long periods of where the heck do I start a series on how to program?  Do I start with the history of counting?  Because to me the programming is simply an extension of math put to use in an applied manner and thus the abstractions of counting and numbers are paramount to its success.  Do I start with the philosophical underpinnings of the process of abstraction?  Because being able to abstract from concretes up, and then being able to concretize from abstracts down is also paramount to successful programming.  Do I start with string rewriting systems and grammars of such languages, such as Extended Backus-Naur Form, exploring various automata and formal languages?  That’s a good place to start, but it’s thick in theory.

I’ve decided what I need to do is provide what we call a “bootstrap” post about programming.  I am interested in exploring a particular language in a series, in this case the C programming language, and I need to start from some point I can refer back to without elucidating the history of all abstract thought.  I’m building upon a couple of series I did many years ago that started with what a computer was, how a computer worked in general, how to count in binary, and most important to this article how a computer’s memory works, and what are programming languages.  These posts are important to this post because we will touch upon each one briefly, so you might as well look into them.  They’re pretty short and from my old blog, so it shouldn’t be too hard.

The purpose of this article then is to introduce some basic “fundamentals” or at least characteristics that most programming languages in use today have or employ.  At the same time it introduces some basic concepts that are required to understand most programming that is generally applied.  This article doesn’t cover the different programming “paradigms,” nor their similarities and differences, that is left for another post.  This article also doesn’t cover specialized programming environments/modes such as logic programming in languages such as Prolog.  Instead, this article focuses on getting you up to speed with general and pervasive programming concepts that are out there in the wild today.

NOTE: What I’m going to cover in this article is known as “imperative programming.”  This is a specific model of programming, or a programming paradigm.  There are many numerous other models, but imperative programming is probably the most popular and the most applicable these days.  Most general purpose programming languages include methods of utilizing the imperative paradigm.

What Is Programming?

In our current modern times we are surrounded by miraculous machines that can “think.”  That is, they can process information in such a way that they can take different actions depending on the data given to them.  We aren’t to the point, yet, that a computer can simulate the thinking process of a human brain exactly, but we’re getting closer every day.  The key to getting these computational devices, being home alarm systems, computer networks, robots, cell phones, desktop installations, to do what we want them to do is through programming.  Programming is the process of taking an abstract task or function, breaking it down into individual steps (a process), and then telling (instructing) one of these thinking devices to do those exact specific steps.  We do this with “formal” languages that are highly specific and precise and illustrate every single tiny step the computational device must take.  Computers can’t, as of yet, fill in any blanks for us so we have to be very specific in telling them what to do.

These formal languages are artificial, are man made, and follow specific rules.  These are called programming languages.  How we tell a computer to do something depends on the programming language we choose.  The previous post (above) on programming languages illustrates this a bit more in depth.  For now, a programming language is a way of telling a computer what to do on some level.

In an interesting way, and how I tend to anthropomorphize the process, programming is a bit like magic.  Magic is the application of will to reality, “bending” reality or influencing reality through the process of pure will if you forgive my tangent.  Programming is the application of your will to the computer, forcing it to do what you want.  When you can make your robot or program start to do what you want in the wild, it’s a terribly exciting prospect… and almost magical.

Choice Of Languages

There are hundreds of programming languages to choose from to accomplish any given task.  How you choose a programming language at any given time depends on a lot of factors, including what libraries are available for it and what can you do with it.  As you become more familiar with programming you start asking more abstract questions, such as, how easy is it to do what I want to do in a given language.  No one programming language, even if it is a general programming language is suited for every task, though that doesn’t stop anyone from making a herculean effort to make it do what they want.

There are many qualities a programming language can have or be measured by.  Is it Turing Complete?  Can it process or solve this problem, or that problem?  How many lines of code does it take to do something, and so on.  As you gain experience in various languages you’ll start to be able to appreciate questions like these and take them into consideration when choosing the particular language you want to employ in solving your problem.

Some of the more popular programming languages these days include Java, Python, JavaScript, Go, R, PHP, C, and C++.  There are myriads of other programming languages for various purposes as well such as C#, Scratch, Haskell, PERL, Prolog, Verilog, BASIC, and so on.  The list is truly endless.  The key here though is that many of these languages share similar constructs that make them up.  I will cover some of these similarities here in this article.

Program Flow

It’s easy to forget sometimes that programming is generally, when it comes down to the true nuts and bolts of a single processor (or core), linear.  Now, threads, sockets, multi-core, object-oriented, and concurrent programming will tell you otherwise, but in general when you get down to one processor(-core) it can only do one instruction at a time.  Sure, the operating system may juggle processes, and multiple processors may be executing multiple instructions at once, but in general it’s one instruction at a time.

This holds true for any kind of programming you’re going to be doing.  The simplest program goes from start to finish, executing one instruction at a time.  Even if you are programming in an object-oriented paradigm (we’ll get to that) you are always programming with the idea that wherever you are in the program, that’s the single thread of execution the computer is going to be doing at that particular time.  Rarely do you need to worry that one statement or expression is going to come after another.  Though you may build non-linear systems, and you will, when you program the steps a computer takes you are doing things one step at a time in any given context.

Shared Constructs Of Many Programming Languages

In today’s programming world there has been a lot of work in “standardizing” a lot of how we interact with the computer.  Now, there is no one standardized language everyone just uses, but that’s a good thing.  You can’t even “standardize” machine language because every processor and the environment that processor is running in is different.  However, many modern programming languages, beyond straight assembly, have some features they share (though they may implement them in their own way).  These include variables and data typesoperatorsexpressions and statements, flow control constructs, functions and subroutines and depending on the language’s sophistication object-orientation (object-oriented programming will be in Bootstrap Part 2).  I outline further what these are below:

Variables And Data Types

When programming we often need to “store” a number or piece of data “somewhere” for a while before we come back to it to further process it.  This could be comparing it to another piece of data, incrementing it, and so on.  The computer “stores” data, be it numbers or characters, in its memory.  There are many kinds of memory found all along the computational device from processor registers, to random access memory (RAM) for short term storage, to hard drives for long term storage.  The key here is that any one place in memory is locatable by using an address.  By “giving” the computer this address, which is usually a numerical code, we can retrieve that piece of data.

Now, back up one step from there.  We have a sea of memory, and each spot in that memory is represented by a number.  That’s great, but while we’re programming along if we had to remember the numerical address of every little piece of data we ever stored anywhere, it’d become just about unbearable.  That’s where variables come in with today’s programming languages.  A variable is an identifier that “encapsulates” the memory address behind an easy to remember label.  When we want to use that data, or assign new information to that data at that address we just use the variable.  Think like this:  myVariable = 10 and  myVariable > 20 .

In many programming languages the story of the variable doesn’t end quite there, it’s only the beginning.  In languages such as C, or Java, a variable must be typed, that is, the programmer has to define what kind of data is going to be stored at that variable’s memory address.  This is known as a data type.  The two simplest data types are the number, being an integer, floating-point decimal, or complex number, and a string, being a list of characters strung together  "like this" .  For example the C language has the type  char for eight bit numbers,  int for sixteen bit numbers, etc.

An important data type that is slightly more complex is the array.  An array is simply a list of data points.  In fact, the string “like this” is really an array of chars like so:  'l', 'i', 'k', 'e', ' ', 't', 'h', 'i', 's', 0 .  If this list was assigned to variable “arr” you could then access it’s individual parts through an index (usually starting from 0):  arr[0] (would be 'l'); arr[2] (would be 'k'); .  This is called indexing an array.  The idea is that the given data is a series that is indexable, like memory, with a number.

Sometimes arrays can be accessed with strings or other identifiers in some languages, usually “higher” languages, such as  arr["key"] .  These types of arrays are often known as associative arrays, or dictionaries.  They work just like numerically indexed arrays, and simply return whatever value was associated with the given key.

More complex data types can be constructed from those two kinds of data types into what we’ll call structures.  A structure will combine multiple pieces of data and data types into one record that itself can act as a data type.  For example, one record may contain a person’s age, name, and birthdate.  This structure may be called “person”, and variables that contain that combination of data types are of the data type “person”.  This becomes important late in object-oriented programming.

Languages that force all of their variables to be a specific data type at one point or another, and in particular to never change types, are called statically typed languages.  There are languages out there, particularly scripting languages such as PHP and Python, that let you assign any data type to any variable at any time.  This sounds like it would add to the confusion, but actually, there are some serious benefits out of it such as duck-typing (more on duck-typing in the object-oriented section.)  Languages that play fast and loose with data types in relation to variables are called dynamically typed languages.

Some programs also have a special functionality called constants (like PHP).  Constants are basically variable that will never change value.  You assign, or define, them once, and then use them in the rest of the program.  Usually constants are indicated in the program by using all UPPERCASE LETTERS.  They are useful for setting up any type of configurations that are used multiply throughout the program.

So what do we do with all these variables?  How do we tell the computer to act on all this data?  The answer is in operators.

Operators

Programming languages are made up of operators that do various things.  For example you have the assignment operator (usually “=”) that assigns the result of an expression to a variable.  You also have the addition operator (usually “+”) which adds the result of two expressions together to obtain another result.  Don’t worry if the usage of expression here is a bit confusing, we’re going to cover expressions shortly.

Some operators are unary, meaning they operate on one operand such as “++”:  myVariable++ .  This tells the programming language to increment the value held by myVariable by one.  Other operators are binary, meaning they operate on two operands.  The usually arithmetical operators are of this ilk, such as addition, subtraction, division, and multiplication:  2 * 2; 3 / 1; 4 + 5; 9 - 3; .  The operands in this example are on the left and right side of the operator (though not all programming languages place them there, such as Lisp or PostScript).  There is the unusual trinary operator present in some languages, which usually tests a condition, but best left until later.

The general idea is that when given an operator, the programming language computes a value, and depending on the operator, does something with that value.

Expressions And Statements

In some languages the difference between an expression and a statement is a little blurred.  I generally define anything that is immediately calculable as an expression, that is it can be replaced with a value as it stands.  A statement is something that does something, usually through the interpretation of an operator.  Both expressions and statements can use operators, and both expressions and statements can have side-effects.  An operator is a piece of code, usually a symbol, that tells the computer to do something or calculate something a certain way.

The easiest way to imagine or understand operators is to think first of math.  If we see the following:  2 + 3 + 5 we think to ourselves, “Oh, that’s equal to 10, and that’s because we are adding 2 to 5, and then adding that result to another 5.”  That my friend is an expression using the addition operator.  Why is it an expression and not a statement?  Well, the expression as given in just about any programming language will compute to (be replaced with) the value of 10, but then just as quickly as it was computed, it’s forgotten because we didn’t do anything with it.

Where as the following is a statement:  myVariable = 10 .  Why is this a statement?  It uses the assignment operator to make myVariable (a variable, see above) equal and store the value 10.  This actually does something so to speak, if I were type  myVariable in the programming language from now on it’ll be equivalent to 10.

Expressions and statements are tricky things.  For instance, variable resolution, which is what we performed by simply typing  myVariable above is an expression.  It computed the value of myVariable, and replaced it.  The line  myVariable = 2 + 5 + (3 * 6) is a combination of expressions and a statement.  Expressions can be made up of smaller expressions, as long as they are calculable, where in this case 2+5+(3*6) can be split into much smaller expressions like so:

Where “exp” stands for expression, “stmt” stands for statement, and the dashes “-” represent operators.  The key here is that when given, an expression is computed and replaced, whereas a statement is executed (does something) and may or may not give us a value.

Flow Control

You’re going along and you’re programming your little heart out, but you’re running into some difficulty.  You can make the robot for instance walk ten steps forward and ten steps right.  However, you’d really like to get it to be able to walk ten steps forward, and then depending on the input of a motion sensor, walk ten steps left or right.  Now we need something called a flow control construct.

If Clause

The exact type of flow control statement we’re looking into here is called an “if-clause.”  There are several types of flow control statements including the “for loop”, a “while”, and such.  However, all of these statements/clauses rest on a particular type of expression (see above) that uses comparison operators (see above).  What do I mean by this?  Here are the general comparison operators most programming languages offer as the basic foundation:  <, >, >=, <=, == .  Respectively these mean “less than”, “greater than”, “greater than or equal to”, “less than or equal to”, and “equal to (or equivalence)”.  You use them like this:  variable1 > variable2; 6 <= variable3; myVariable == 6; .   This is a bit of a special expression in that it computes to a true or false value.  If the condition indicated is true, if variable1 is actually greater than variable2, the first expression is computed as “true”.  Many programming languages offer more sophistication with these truth-expressions (comparison expressions) such as a “not” operator, usually an exclamation point, the ability to enclose them in parentheses, and the ability to include more than one condition in a logical connection using “and” and “or” operators (usually && and ||).  For example in a more sophisticated language I might write:  (a < 3) && !((b == 4) || (b == 1)) .  This would read: “variable b is NOT 4 OR 1 AND variable a is less than 3.”  Don’t worry, the computer would compute all that out and give us a true or false result.

These comparison expressions are simply expressions that return a true or false value, but they are still expressions; the computer computes them, replaces their value, and moves on.  How do we use say, a < 3?  One of the simplest ways we can use the result of the comparison is in an if clause.  An if clause is simply a way of telling the computer to execute one set of statements if something is true, and, optionally, another set of statements if something is false instead.  It is structured generally like this (some programming languages don’t use brackets):

This basically reads: “If a is less than 3 execute statement1 and statement2, or else (if a is greater than or equal to 3) execute statement3 and statement4”.

This is called a flow control construct because it interrupts the linear step-by-step interpretation of the program by the computer, presents us with a test, and then proceeds to different statements depending on that test.  It affects the program flow.  After the if clause statement is executed, flow continues down the program like normal.  Note that the else clause is optional most of the time, but it can be used in case you want to something if something is false without writing a new if clause.

Looping Constructs

What happens when you want to something a number of times but you don’t want to copy and paste the statements over and over into the program?  You can use a looping construct.  There are several looping constructs a given language may have, but usually they have as a foundation the following two: the while loop, and the for loop.  There is also the foreach loop, and the do-while loop.

A looping construct uses a variable and a condition expression to determine how many times it will execute its enclosing statements.  Usually the variable is incremented, or otherwise updated, each time through the loop, and as soon as the condition in the given expression is met the loop stops.  It is possible to not update the variable correctly, or write an incorrect condition statement and cause what is known as an infinite loop.  These, except in very specific circumstances, are to be avoided.

The syntax or construction of a given while loop looks like this (some languages don’t use brackets):

As you can see it’s very much like an if-clause just with the added benefit that the loop will go back to the beginning of the brackets and start all over again as long as the condition in the expression evaluates to true.  In this case if a starts out equaling 0, statement1 and statement2 will be executed 3 times.  One for a = 0, one for a = 1, and one for a = 2.

Again, the reason this is considered a flow control construct is because it takes the normal linear flow of the program (next instruction, next instruction, next instruction…) and makes it “go back” and repeat certain instructions over and over until a condition is met.

for loop‘s syntax or construction is a bit more complicated, and I’ll take from the C language version of it to show the usual syntax, but many languages will differ:

Here we see a for loop consists of a body of statements (statement1-3), and in its conditional clause two statements and one conditional expression.  First we initialize the variable to be used, a (to 0).  Then we determine the condition that will determine whether the loop will run again (a < 5).  Lastly we tell the computer what to do at the end of every loop (after statement3 is executed, which is increment a by one).

In this case statement1, statement2, and statement3 will be executed, in that order five times (once for a = 0, once for a = 1, again for a = 2, a = 3, and a = 4).

foreach loop‘s syntax or construction is definitely language dependent.  In this case I’m going to use the PHP version of the foreach loop to illustrate its functionality.  A foreach loop differs from a for loop in that it iterates (or steps through one at a time) over an array (see above).  That is it assigns a single element of an array in order to a temporary variable that the statements inside the loop can use.  Here is an example to illustrate this:

In this case, statement1 and statement2 will be executed six times, and in each loop $val will equal the next item in the array “arr”: val = 0, val = 5, val = 8, 2, 4, 3.  Many higher level languages such as scripting languages have this kind of flow control construct so it’s a good idea to familiarize yourself with it now.  Not all languages have this construct, and those that do often have quite varying syntax of it (such as using “in” instead of “as”).

The last flow control expression/statement that we’ll cover is the function or subroutine.

Functions and Subroutines

So we have a program, and it goes from beginning to end, although along the way depending on the data it might execute certain statements and not others, as well some parts repeat themselves a certain number of times, but all in all we get from start to finish.  All is well and good right?  Well, let’s go back to our little robot.

Let’s say we want every time our robot is supposed to display a happy response he raises his arms, his eyes turn green, and he says, “Yay!”  That’d be pretty cute wouldn’t it?  However, we’re presented with a bit of a problem.  He might give us his three step happy response at a lot of different times and in response to many different kinds of input.  As of right now, with our programming knowledge, we have to insert those three specific steps everywhere in the program that he might make that response.  That’s not a good idea.

For one, what if you decide to change his eyes to orange?  Well, you could always make the color of his eyes a constant (see above) and just use that and change the constant to orange.  Okay, what if you decide later to only raise one arm instead of both?  Then you’ll have to go through the entire program and find every instance where he raises both his arms to say, “Yay” and replace it with a statement only raising one arm.  That’s tedious and error-prone.  So what are we to do?

The answer is a subroutine.  Not all languages have basic subroutines and instead implement everything like this as a function.  We’ll get to functions in a moment, as they have some functionality (no pun intended) that subroutines do not.  A subroutine is a collection of statements that the computer can “call” into at any given time, and then “come back from” to the main program flow.  That is, the program stops and records where it is in the program, jumps to the statements contained in the subroutine, executes them, and then returns back to where it was before.

This is nifty!  Now we can write the happy response of our robot as a subroutine, and then we can “jump” or call that subroutine from anywhere in the code and come back like we had just written that code right there.  That’s handy because now if we wrote our program appropriately, we just change the subroutine to raise one hand and its “reflected” everywhere else in the program.  It might look something like this (in BASIC):

You can see here the “gosub” operator jumps the program to “line” 10000, and then the “return” operator jumps the program flow back to where it came from.  Very nice!  However, there are some shortcomings to subroutines.  What if you wanted to pass some information to the subroutine so that it might operate a little differently?  That is, give it some input?  Or what if you wanted to return a value from the subroutine, because the subroutine calculated something?  In this BASIC example (pun intended) you’d have to use global variables (for more information on the global scope read below), and those can get messy.  A better answer is a function.

function is basically a subroutine but it comes with some added bells and whistles.  The first extra functionality it has is that it can take what are called arguments.  These are pieces of data that can be “passed” to the function when it is called upon.  They are defined by variables in the function definition that are only used in that function (see scope below).  Another piece of the puzzle is that functions can return values.  Rather than simply jump back to where you were in the program upon return, the computer can actually substitute a value computed in the function as the value of the function when it’s called.  Here is an example:

Here we define a function called sum that simply adds to numbers together.  Here sum is the name of the function, so when we use that identifier elsewhere in the program the computer knows we’re “calling” a function.  You can see inside the function definition we identify “arg1” and “arg2”.  These are the arguments of the function, being they hold the data that is “passed” to the function when it is called from elsewhere in the program.  Within the functions block of statements we see it define a variable “localvar” (more on this in a moment), which stores the result of the arg1+arg2 expression.  Lastly, we return localvar, which returns whatever data is stored in localvar.  That replaces the original function call with the return value, and that value is used in the rest of the calling statement.

I realize that’s a lot of magic going on all at once so I’ll break it down.

Let’s say we have defined the function “sum” as we have done before.  Let’s step through when we execute the first sumvar1 statement:

I hope this diagram can illustrate the process I just iterated.  In short, you pass values to functions when you call them.  These values are assigned as the arguments of the function, the function then hopefully acts on these arguments and returns a value.

Note, because function calls are replaceable with return values they are not actually statements, though some programming languages may differ, but instead they are expressions.  They are immediately computable.  This gets confusing because sometimes functions have side effects and do things too, not just compute things.  But in general in most languages, because they can resolve to a return value they are expressions.

Neat trick though, since they are expressions, they can be used in other flow control constructs such as the if clause and while loop.  This is because the function can return a true or false value, and that’s all the if clause or while loop are looking for when evaluating its expression.  So you could have something like these:

In general you can use a function call or invocation anywhere that you can use an expression.

Variable Scope

You may have noticed that when we made our localvar variable in our sum function I labeled it “local”.  This is because of something also present in most popular programming languages.  That is the concept of scope.

Scope is a somewhat abstract concept, and every programming language unfortunately has its own definitions of scope.  Scope is basically the idea of where you can reference what in the language.  What I mean is, if I make a variable here, can I reference that variable over here?  If I make a function here, can I reference that function over in this other part of the program?  The answer to that is scope.  The idea is that there are in general two different scopes.  There is the global scope where anything defined in it can be referenced anywhere in the program, and there’s more finer scopes that are narrower and narrower from there.  Some programming languages have module scopefile scope and so on.  I refer to these all as local scopes.  A local scope is a place in your program where if you define anything, such as a function or variable, other parts of the program aren’t going to be able to “see” or reference it.  I will give an example:

This throws an error if we are using block scoping.  There are many different models of scope, and scope takes on a whole new dimension when we get to classes and objects (next post).  This throws an error because we defined mylocalvarv in the myFunc function.  Each function defines its own local scope, and in this case mylocalvar goes into that particular function’s scope.  Anything outside of that function, the main code, another function, etc. cannot access that functions scope.  In fact mylocalvar is forgotten by the computer as soon as the function returns.  So when I try to assign mylocalvar to myglobalvar, I can’t because mylocalvar doesn’t exist.  That’s the power of scope.

Conclusion

With variables, data types, flow control, functions, expressions, statements, subroutines, and such under your belt, you are prepared to understand more fully just about any programming that comes your way from any of the popular general purpose languages out there.  That’s really the core of what makes up programming today (granted you’re not using a more specialized language such as Prolog or LISP).  You can get pretty far with this understanding in C, PHP, Python, and more.  Every programming language has variations on these constructs and so you’ll have to learn each one if you want to program in that language, but these are the core.

In the next post I hope to explore object-oriented programming and the slew of terms and nuances it provides to us programmers.  You’ll learn things like classes, objects, prototypes, inheritance, polymorphism, oh my!  See you next time!

If you appreciate my tutorials and wisdom please consider supporting me on Patreon.

However, if a monthly commitment is a little too needy for you, you might consider buying me a cup of coffee.

This article is part of a larger series on How To Program Anything: Core Rulebook (Parent Series)

photo credit: catsocmedia Staying hydrated via photopin (license)

Liked it? Take a second to support kadar on Patreon!

kadar

I'm just a wunk, trying to enjoy life. I am a cofounder of http//originalpursuitssoc.com/ and I like computers, code, creativity, and friends.

You may also like...

Leave a Reply

%d bloggers like this: