Skip to content

Latest commit

 

History

History
119 lines (81 loc) · 7.39 KB

00-background.md

File metadata and controls

119 lines (81 loc) · 7.39 KB

From Voltage to Language

From a technical perspective, the journey from electrical voltage to a programming language is not trivial. But to understand the background of how "programming" came to be, it roughly goes through 3 stages.

Stage 1 - Digitization

A chain of abstractions forms the capability of programming. Digitization lays the foundation for them -- a process that quantizes analog (continuous) signals into digital (discrete) signals.

digitization

Abstraction is not the only scientific/engineering concept applied in the realm of programming. Another one would be the various trade-offs made to enable programming or applications made through programming.

Digital photography/videography is an example of such trade-offs:

Scalability Vividness Operability Storage Feedback
Film Infinite Close to nature Needs some expertise Limited After being developed
Digital Limited by hardware Limited by hardware Got a smartphone? Indefinite* Usually instantaneous

Stage 2 - Encoding

Binaries allow us to manipulate and command computer hardware to do our bidding, but not with ease.

encoding

In this scenario, encoding provides a path between the two parties so that machines and humans can understand each other better.

The same concept has been applied successfully in the fantasy realm too:

alohomora

Arguably the most prominent form of encoding exists in the form of Instruction Set Architectures (ISA). These architectures map combinations of binaries into hardware instructions.

One representation of ISAs is in the form of assembly languages. An example from the MIPS (Microprocessor without Interlocked Pipelined Stages) 32-bit architecture looks like such:

MIPS32 addi

The above assembly instruction (add $r1 $r2 350) takes the value stored in a register ($r1), operates (addi or "add-immediate") to the immediate value (350), then store the result into another register ($r2).

These instructions are about the first layer of near-natural programming languages that humans can program but generally don't want to. They are too verbose and lengthy to conduct even the most trivial commands. They are also easy for humans to make mistakes because humans are not best at being consistent. Therefore these instructions are usually generated by compilers that enable humans to write in friendlier and more robust programming languages.

Stage 3 - Programming languages

These languages map a subset of logical human natural languages, sometimes through one or many layers of other programming languages, eventually into hardware instructions of one or many suitable ISAs.

According to Stack Overflow Developer Survey 2020 (from 65,000 participants), these are the actively used/asked-about (25) languages by popularity: languages

Each of these programming languages has its distinct features and strengths that make them suitable over others for a range of tasks. Many of them also have overlapping strengths (or weaknesses). So the choice of programming languages for the job often comes down to:

  1. Trade-offs between useful pros and cons that can be compromised
  2. Ecosystem of community, support, and shared codebases (libraries/packages)
  3. Personal or collective preferences

Like natural (human) languages, they come in various shapes and forms. In the realm of computer science, language paradigms classify some of the key concepts. These concepts are only useful when you can apply them. As natural languages are a toolbox to convey ideas, programming languages are a toolbox to solve problems and accomplish objectives. Knowing all aspects of a programming language doesn't automatically write itself and makes you the next Mark Zuckerberg. Being able to define problems to solve and objectives to achieve are more valuable than the tools themselves.

In this series, we will only ease-in some of the abstracted concepts from various aspects that matter.

Natures of Programming

A program is a set of instructions defined through a programming language that we can often utilize flowcharts to visualize:

euclid

In mathematics and computer science, the technical term for the above example is called an algorithm. Other representations of algorithms include mathematical expressions and pseudocode.

Objective Centric

It's always helpful to define goals which the program intends to accomplish.

It's also helpful to break a large problem into smaller chunks. This process resembles digitization itself as each step becomes more manageable.

Logical

Programming is highly logical because it's formed on top of "logic gates" that toggle the binary bits (0s and 1s) to construct meaningful combinations that translate to hardware instructions. Programmers have to follow specific rules (syntax and semantics) of a given programming language and the target platforms the program intends to run on. Like LEGO® blocks, there is only a finite shape of them to be utilized, and they all follow a "system" to be effectively bound together.

Creative

Programming is also highly creative because it can be expressed in many ways for the same objectives, much like human languages.

#include <time.h> //  Robert Nystrom
#include <stdio.h> // @munificentbob
#include <stdlib.h> //     for Ginny
#define  r return    //    2008-2019
#define  l(a, b, c, d) for (i y=a;y\
<b; y++) for (int x = c; x < d; x++)
typedef int i;const i H=40;const i W
=80;i m[40][80];i g(i x){r rand()%x;
}void cave(i s){i w=g(10)+5;i h=g(6)
+3;i t=g(W-w-2)+1;i u=g(H-h-2)+1;l(u
-1,u+h+2,t-1            ,t+w+2)if(m[
y][x]=='.'                  )r;i d=0
;i e,f        ;if(!s){l(      u-1,u+
h+2,t-    1,t+w+2){i s=x<t     ||x>t
+w;i    t=y<u||           y>    u+h;
if(s    ^t&&              m[      y]
[x    ]=='#'    ){d++;    if(g    (d
)     ==0)    e=x,f=y;    }}if    (d
==    0)r;    }l(u-1,u    +h+2    ,t
-1    ,t+w    +2){i s=    x< t    ||
x>    t+w;    i t= y<u    ||y>    u+
h;    m[y]      [x]= s    &&t?   '!'
:s^t    ?'#'                    :'.'
;}if    (d>0)m                  [f][
e]=g(2    )?'\'':'+';for(i j=0;j<(s?
1:g(6)        +1);j++)m[g(h)+u][g(w)
+t]=s?'@'                 :g(4) ==0?
'$':65+g(62)              ;}i main(i
argc, const char* argv[]) {srand((i)
time(NULL));l(0, H, 0,W)m[y][x]=' ';
for(i j=0;j<1000;j++)cave(j==0);l(0,
H,0,W) {i c=m[y][x]; putchar(c=='!'?
'#':c);if(x==W-1)printf("\n");}r 0;}

(A random dungeon generator that fits on a business card)

To achieve certain objectives, programmers often need to work around constraints imposed by the programming language, target platforms, and lower-level abstractions that form up the programming language itself. Again, like LEGO® blocks, even with finite shapes, people with fantastic ideas can achieve things like:

lego pharaoh