Lesson 1 and 2 Programming Languages
Lesson 1 and 2 Programming Languages
Programming Languages
dim x as integer
2x=3
3 dim y as integer
Would output:4 y = 8 5
Third generation languages can be platform independent, meaning that code written for 5 x = x + y one
system will work on another. To convert a 3rd generation program into object code requires a Compiler or
an Interpreter.
To summarise:
Hardware independence, can be easily ported to other systems and processors
Time saving programmer friendly, one line of 3rd gen is the equivalent of many lines of 1st and
2nd gen
However
Code produced might not make the best use of processor specific features unlike 1st and 2nd gen
There are several types of Third-generation languages that you will cover in more
detail at A2. They include:
• Object Orientated
• Event driven
Fourth-generation languages are designed to reduce programming effort and the time it takes to develop
software, resulting in a reduction in the cost of software development. They are not always successful in
this task, sometimes resulting in inelegant and hard to maintain code. Languages have been designed with
a specific purpose in mind and this might include languages to query databases (SQL), languages to make
reports (Oracle Reports) and languages to construct user interface (XUL). An example of 4th generation
programming type is the declarative language.
--an example of a Structured Query Language (SQL) to select
criminal details from a database
Declarative languages - describe what computation should be performed and not
SELECT name, height, DoB FROM criminals WHERE numScars = 7; how
to perform it. Not imperative!
An example of a declarative language is CSS which you might learn more about when completing any web
design unit.
/*code to change the headings on a page to green and the paragraphs to red and italic*/ h1 { color : #00FF00; }
p { color : #FF0000; font-style : italic }
A programming paradigm is a style, or “way,” of programming. Some languages make it easy to write in
some paradigms but not others.
Paradigms are not meant to be mutually exclusive; a single program can feature
Imperative Programming by defining objects that send messages to each other. Objects have their
own internal (encapsulated) state and public interfaces. Object orientation can be:
Declarative Class-based: Objects get state and behavior based on membership in a class.
Procedural Programming by defining objects that send messages to each other. Objects have their
own internal (encapsulated) state and public interfaces. Object orientation can be:
Functional Class-based: Objects get state and behavior based on membership in a class.
Object-Oriented Programming by defining objects that send messages to each other. Objects have their
own internal (encapsulated) state and public interfaces. Object orientation can be:
Event-Driven Programming with emitters and listeners of asynchronous actions.
Flow-Driven Programming processes communicating with each other over predefined channels.
Logic (Rule-based): Programming by specifying a set of facts and rules. An engine infers the
answers to questions.
Constraint Programming by specifying a set of constraints. An engine finds the values that meet the
constraints.
Aspect-Oriented Programming cross-cutting concerns applied transparently.
Array Programming with powerful array operators that usually make loops unnecessary.
Control flow in imperative programming is explicit: commands show how the computation takes place, step
by step. Each step affects the global state of the computation.
result = []
i = 0 start:
numPeople = length(people)
if i >= numPeople goto finished
p = people[i]
nameLength = length(p.name) if
nameLength <= 5 goto nextOne
upperName = toUpper(p.name)
addToList(result, upperName)
nextOne:
i=i+1
goto start
finished:
return sort(result)
Structured Programming
Structured programming is a kind of imperative programming where control flow is defined by nested
loops, conditionals, and subroutines, rather than via gotos. Variables are generally local to blocks (have
lexical scope).
result = [];
for i = 0; i < length(people); i++ {
p = people[i];
if length(p.name)) > 5 {
addToList(result, toUpper(p.name));
}
}
Early languages emphasizing structured programming: Algol 60, PL/I, Algol 68, Pascal, C, Ada 83, Modula,
Modula-2. Structured programming as a discipline is sometimes though to have been started by a famous
letter by Edsger Dijkstra entitled Go to Statement Considered Harmful.
OOP is based on the sending of messages to objects. Objects respond to messages by performing
operations, generally called methods. Messages can have arguments. A society of objects, each with their
own local memory and own set of operations has a different feel than the monolithic processor and single
shared memory feel of non object oriented languages.
One of the more visible aspects of the more pure-ish OO languages is that conditionals and loops become
messages themselves, whose arguments are often blocks of executable code. In a Smalltalk-like syntax:
result := List new.
people each: [:p |
p name length greaterThan: 5 ifTrue: [result add (p name upper)]
]
result sort.
^result
Many popular languages that call themselves OO languages (e.g., Java, C++), really just take some elements
of OOP and mix them in to imperative-looking code. In the following, we can see that length and toUpper
are methods rather than top-level functions, but the for and if are back to being control structures:
result = [] for p in
people {
if p.name.length > 5 {
result.add(p.name.toUpper); }
}
The first object oriented language was return result.sort; Simula-67; Smalltalk followed
soon after as the
first “pure” object-oriented language. Many languages designed from the 1980s to the present have labeled
themselves object-oriented, notably C++, CLOS (object system of Common Lisp), Eiffel, Modula-3, Ada 95,
Java, C#, Ruby.
Declarative Programming
Control flow in declarative programming is implicit: the programmer states only what the result should look
like, not how to obtain it.
select upper(name)
from people where length(name) > 5
order by name
No loops, no assignments, etc. Whatever engine that interprets this code is just supposed go get the desired
information, and can use whatever approach it wants. (The logic and constraint paradigms are generally
declarative as well.)
Functional Programming
In functional programming , control flow is expressed by combining function calls, rather than by assigning
values to variables:
sort(
fix(λf. λp. if(equals(p,
emptylist),
emptylist,
if(greater(length(name(head(p))), 5),
append(to_upper(name(head(p))), f(tail(p))),
f(tail(people)))))(people))
Yikes! We’ll describe that later. For now, be thankful there’s usually syntactic sugar:
let
fun uppercasedLongNames [] = []
| uppercasedLongNames (p :: ps) = if length(name p) > 5 then (to_upper(name
p))::(uppercasedLongNames ps) else (uppercasedLongNames ps)
in
sort(uppercasedLongNames(people))
Huh? That still isn’t very pretty. Why do people like this stuff? Well the real power of this paradigm comes
from passing functions to functions (and returning functions from functions).
sort(
filter(λs. length s > 5,
map(λp. to_upper(name p), people)))
We can do better by using the cool |> operator. Here x |> f just means f(x). The operator
has very low precedence so you can read things left-to-right:
people |> map (λp. to_upper (name p)) |> filter (λs. length s > 5) |> sort
Let’s keep going! Notice that you wouldn’t write map(λx. square(x)), right? You would write map(square).
We can do something similar above, but we have to use function composition, you know, (f o g)x is f(g(x)),
so:
people |> map (to_upper o name) |> filter (λs. length s > 5) |> sort
Research the following programming styles and state how they are similar and how
they are different from each other: (a) Stack-based, (b) Concatenative, (c) Point free,
(d) Tacit.
The difference between an interpreted and a compiled language lies in the result of the process of
interpreting or compiling. An interpreter produces a result from a program, while a compiler produces a
program written in assembly language. The assembler of architecture then turns the resulting program into
binary code. Assembly language varies for each individual computer, depending upon its architecture.
Consequently, compiled programs can only run on computers that have the same architecture as the
computer on which they were compiled.
Because different kinds of computers do not speak each others' machine languages, a compiled
program will only work on the platform it was designed for. For example, a program written for HP-UX
normally will not work on a Mac OS computer or a computer running Solaris. Despite this drawback,
compiled programs are faster than those that must be run through an interpreter. Also, it is often possible
to recompile the program so that it will run on different platforms. Examples of languages that are normally
used to produce compiled programs include C, Fortran, and COBOL.
In an interpreted program, on the other hand, the source code typically is the program. Programs
of this type (often known as scripts) require an interpreter, which parses the commands in the program
and then executes them. Some interpreters, such as the Unix shells (sh, csh, ksh, etc.), read and then
immediately execute each command, while others, such as Perl, analyze the entire script before sending
the corresponding machine language instructions. The advantage of a script is that it is very portable. Any
computer that has the appropriate interpreter installed may run the program more or less unchanged. This
is a disadvantage as well, because the program will not run at all if the interpreter is not available. In
general, interpreted programs are slower than compiled programs, but are easier to debug and revise.
Other examples of interpreted languages include JavaScript and Python.
Compiled Languages
Compiled languages are converted directly into machine code that the processor can execute. As a result,
they tend to be faster and more efficient to execute than interpreted languages. They also give the
developer more control over hardware aspects, like memory management and CPU usage.
Compiled languages need a “build” step - they need to be manually compiled first. You need to “rebuild”
the program every time you need to make a change. In our hummus example, the entire translation is
written before it gets to you. If the original author decided he wanted to use a different kind of olive oil,
the entire recipe would need to be translated again and then sent to you.
Examples of pure compiled languages are C, C++, Erlang, Haskell, Rust, and Go.
Interpreted Languages
Interpreters will run through a program line by line and execute each command. Now, if the author decided
he wanted to use a different kind of olive oil, he could scratch the old one out and add the new one. Your
translator friend can then convey that change to you as it happens.
Interpreted languages were once known to be significantly slower than compiled languages. But, with the
development of just-in-time compilation, that gap is shrinking.
Examples of common interpreted languages are PHP, Ruby, Python, and JavaScript.
A Small Caveat
Most programming languages can have both compiled and interpreted implementations. The language
itself is not necessarily compiled or interpreted. However, for simplicity’s sake, they’re typically referred to
as such.
Strictly speaking, the terms interpreted language and compiled language are not well defined because, in
theory, any programming language can be either interpreted or compiled. In modern programming
language implementation it is increasingly popular for a platform to provide both options. e.g. Python can
be executed either as a compiled program, or as an interpreted language in interactive mode.
Most command line tools, CLIs, and shells can theoretically be classified as interpreted languages.
• Additional time needed to complete the entire compilation step before testing, and
• Platform dependence of the generated binary code.
Generally, compiled programs run faster than interpreted programs because they are first converted native
machine code. Also, compilers read and analyze the code only once, and report the errors collectively that
the code might have, but the interpreter will read and analyze the code statements each time it meets
them and halts at that very instance if there is some error. In practice, the distinction between the two is
getting blurred owing to improved computation capabilities of the modern hardware and advanced coding
practices.
Another point to be noted is that while classifying a language as scripting language or programming
language, the environment on which it would execute must be taken into consideration. The reason why
this is important is that we can design an interpreter for C language and use it as a scripting language, and
at the same time, we can design a compiler for JavaScript and use it as a non-scripting(compiled language).
A live example of this is V8, the JavaScript engine of Google Chrome, which compiles the JavaScript code
into machine code, rather than interpreting it.
Some scripting languages traditionally used without an explicit compilation step are
JavaScript,PHP,Python,VBScript.
Some programming languages traditionally used with an explicit compilation step are C, C++.