Multi-Paradigm Programming and Scripting
Timeline of the most popular programming languages since 1965 to 2019: https://www.youtube.com/watch?v=Og847HVwRSI
File:Some_important_programming_concepts.pdf
Why Multi-Paradigm Programming and Scripting? | |||
---|---|---|---|
| |||
Content of this course | |||
Programming Constructs:
|
Programming Paradigms & Languages:
|
Scripting:
|
Applications of Shell Scripting:
|
Contents
- 1 High level - Low Level Languages
- 2 Compiled vs Interpreted languages
- 3 Subprogram - Subroutine - Procedure - Function - Method - etc
- 4 Generic subprograms
- 5 Variables
- 6 Data type
- 7 Recursion
- 8 Binding
- 9 Statically and Dynamically typed languages
- 10 Reflection
- 11 Languages evaluation criteria
- 12 Some programming paradigms
High level - Low Level Languages
Compiled vs Interpreted languages
https://medium.com/@DHGorman/a-crash-course-in-interpreted-vs-compiled-languages-5531978930b6
https://guide.freecodecamp.org/computer-science/compiled-versus-interpreted-languages/
Speaking simplistically, compiled languages are those which are written in one language and, before being run, translated or "compiled" into another language, called the target language (typically in machine language that the processor can execute). Once the translation is complete, the executable code is either run or set aside to run later. Some common compiled languages include C
, C++
, Delphi
and Rust
.
The compiler
translates the high-level source program into an equivalent target program (typically in machine language).
The alternative to using a compiler
(for a compiled language) is using an interpreter
(for interpreted languages). Interpreted languages are compiled at runtime. What this allows for is a lot more flexibility, especially when it comes to a program adaptively modifying its structure. This flexibility does have a cost; interpreted languages are considered significantly slower.
Interpreters
will run through a program line by line and execute each command.
Advantages and Disadvantages
Compiled Languages:
- Advantages:
- Programs compiled into native code are faster than those translated at run time, due to the overhead of the translation process.
- Disadvantages:
- The compilation code usually will only be able to run in the platform where the program was compiled. This is solved in Java by the implementation of the Java Virtual Machine.
Interpreted Languages:
- Advantages:
- An Interpreted language gives implementations some additional flexibility over compiled implementations. Because interpreters execute the source program code themselves, the code itself is platform independent. Other features include dynamic typing, and smaller executable program size.
- Better diagnostics (error messages).
- Disadvantages:
- The most notable disadvantage is the execution speed, which is less compared to compiled languages.
- 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.
Phases of Compilation
Compiler operates in various phases each phase transforms the source program from one representation to another. Every phase takes inputs from its previous stage and feeds its output to the next phase of the compiler. https://www.guru99.com/compiler-design-phases-of-compiler.html
- Lexical analysis:
- Syntax analysis:
- Semantic analysis:
- Intermediate code generator:
- Code optimizer:
- Code generator:
Subprogram - Subroutine - Procedure - Function - Method - etc
In computer programming, a Subprograms
is a sequence of program instructions that performs a specific task, packaged as a unit. This unit can then be used in programs wherever that particular task should be performed.
In different programming languages, a subroutine may be called a procedure, a function, a routine, a method, or a subprogram. https://en.wikipedia.org/wiki/Subroutine
Luego de revisar varias referencias. No creo que haya diferencias claras entre estos términos. Hay diferencias dependiendo del lenguaje de programación. Sólo he encontrado una diferencia que parece ser mencionada en varias fuentes:
- Functions return values and procedures do not. Sin embargo, no todas las fuentes concuerdan con esto. See this source: https://softwareengineering.stackexchange.com/questions/20909/method-vs-function-vs-procedure
You might say a function returns a value. Well, the following C function doesn't return a value:
void f() { return; }
...but I doubt you'd find anyone who would call it a procedure.
Sure, in Pascal, procedures don't return values and functions return values, but that's merely a reflection of how Pascal was designed. In Fortran, a function returns a value, and a subroutine returns multiple values. Yet none of this really allows us to come up with a "universal" definition for these terms.
In fact, the term "procedural programming" refers to a whole class of languages, including C, Fortran and Pascal, only one of which actually uses the term "procedure" to mean anything.
So none of this is really consistent.
The only exception is probably method
, which seems to be used almost entirely with OO Languages, referring to a function that is associated with an object. Although, even this is not always consistent. C++, for example, usually uses the term "member function" rather than method, (even though the term "method" has crept into the C++ vernacular among programmers.)
The point is, none of this is really consistent. It simply reflects the terminology employed by whatever languages are en vogue at the time.
A real distinction is when we talk about a function in Functional programming. If you like to keep a function clean (just look at functional languages) you need to make sure a function does not have a side effect. However, in all the procedural or OOP languages we refer to functions that don't really meet the exact mathematical definition of a function that is used in Functional programming. https://stackoverflow.com/questions/721090/what-is-the-difference-between-a-function-and-a-procedure/721107
Subprogram header is the fist part of the definition including the name, the kind of subprogram, and the formal parameters.
The parameter profile (aka signature) of a subprogram is the number
, order
and types
of its parameters.
The protocol is a subprogram parameter profile and, if it is a function, its return type.
There are tow categories of subprograms: (This is from Muhammad slides. I have already explained what I found in my research about the difference between Procedures and Functions).
- Procedures: Are collection of statements that define parameterized computations.
- Functions: Structurally resemble procedures but are semantically modeled on mathematical functions.
Design issues for Subprograms:
- Are local variables static or dynamic?
- What types of values can be returned from functions?
- How many values can be returned from functions?
- Can subprograms be overloaded?
- Can subprogram be generic?
- Is the language allowed nested subprograms?
Some important concepts around Subprograms are:
- Parameter-passing:
- Pass-by-Value (In Mode)
- Pass-by-Result (Out Mode)
- Pass-by-Reference (Inout Mode)
- Local referencing environments
- Generic subprograms
- Overloaded subprograms
Generic subprograms
A generic subprogram is one that takes parameters of different types
on different activation.
Following example illustrates how we can print an array of different type using a single Generic method: https://www.tutorialspoint.com/java/java_generics.htm
public class GenericMethodTest {
// generic method printArray
public static < E > void printArray( E[] inputArray ) {
// Display array elements
for(E element : inputArray) {
System.out.printf("%s ", element);
}
System.out.println();
}
public static void main(String args[]) {
// Create arrays of Integer, Double and Character
Integer[] intArray = { 1, 2, 3, 4, 5 };
Double[] doubleArray = { 1.1, 2.2, 3.3, 4.4 };
Character[] charArray = { 'H', 'E', 'L', 'L', 'O' };
System.out.println("Array integerArray contains:");
printArray(intArray); // pass an Integer array
System.out.println("\nArray doubleArray contains:");
printArray(doubleArray); // pass a Double array
System.out.println("\nArray characterArray contains:");
printArray(charArray); // pass a Character array
}
}
Variables
A name is a string of characters used to identify some entity in a program. Variable names
are the most common names in the programs.
- Are names case sensitive?
- Length?
- etc...
Names with special characters:
PHP
: All variable names must begin with dollar signsPerl
: All variable names begin with special characters, which specify the variable's typeRuby
: Variable names that begin with@
are instance variables; those that begin with@@
are class variables
Case sensitivity names:
- Names in the
C-based
languages are case sensitive. Not in others languages.
Variables
A variable is an abstraction of a memory cell.
Variables can be characterized as a sextuplet (six parts) of attributes:
- Name
- Address
- Value
- Type
- Lifetime
- Scope
Address: The memory address with which it is associated.
- A variable may have different addresses at different times during execution.
- A variable may have different addresses at different places in a program.
- If two variable names can be used to access the same memory location, they are called aliases.
- Aliases are created via pointers, reference variables,
C
andC++
unions - Two pointer variables are aliases when they point to the same memory location. The same is true for reference variables.
- Aliases are harmful to readability (program readers must remember all of them).
Type: Determines the range of values of variables and the set of operations that are defined for values of that type; in the case of floating point, type also determines the precision
For example, the int type in Java specifies a value range of -2147483648 to 2147483647
Value: The value of a variable is the contents of the memory cell or cells associated with the variable:
- The l-value of a variable is its address
- The r-value of a variable is its value
Data type
A data type, in programming, is a classification that specifies which type of value a variable has and what type of mathematical, relational or logical operations can be applied to it without causing an error. A string, for example, is a data type that is used to classify text and an integer is a data type used to classify whole numbers.
Descriptor:
It's the collection of the attributes of a variable.
Ex.:
Example | ||||
---|---|---|---|---|
Primitive Data Types
|
Integer | byte
|
||
short
|
||||
int
|
||||
long
|
||||
Floating Point | float
|
|||
double
|
||||
Complex | Each value consists of two floats, the real part and the imaginary part | |||
Boolean | ||||
Character |
|
|||
|
|
|||
Arrays | An array is a homogeneous aggregate of data elements in which an individual element is identified by its position in the aggregate, relative to the first element.
|
Slicing in Python: Python
vector = [2, 4, 6, 8, 10, 12, 14, 16]
mat = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
vector (3:6) is a three-element array
mat[0][0:2] is the first and second element of the first row of mat
| ||
Associative Arrays | An associative array is an unordered collection of data elements that are indexed by an equal number of values called keys:
Ex: Python: C++: Perl: |
Associative Arrays in Perl# Names begin with %; literals are delimited by parentheses
%hi_temps = ("Mon" => 77, "Tue" => 79, "Wed" => 65, ...);
# Subscripting is done using braces and keys
$hi_temps{"Wed"} = 83;
# Elements can be removed with delete
delete $hi_temps{"Tue"};
| ||
Record | A record is a possibly heterogeneous aggregate of data elements in which the individual elements are identified by names | |||
Enumeration | All possible values, which are named constants, are provided in the definition.
No enumeration variable can be assigned a value outside its defined range |
C# example:enum days {mon, tue, wed, thu, fri, sat, sun};
|
Pointer
Pointers store address of variables or a memory location.
A pointer is a variable that stores the address of another variable. Unlike other variables that hold values of a certain type, pointer holds the address of a variable. For example, an integer variable holds (or you can say stores) an integer value, however an integer pointer holds the address of a integer variable. https://beginnersbook.com/2014/01/c-pointers/
- A pointer type variable has a range of values that consists of memory addresses and a special value, nil.
- Provide the power of indirect addressing
- Provide a way to manage dynamic memory
- A pointer can be used to access a location in the area where storage is dynamically created (usually called a heap)
Pointers in C and CPP
To use pointers in C, we must understand below two operators: & and *
| |||
Ampersand ( |
The unary operator For example |
// The output of this program can be different in different runs.
// Note that The program prints address of a variable and a variable
// can be assigned different address in different runs.
#include <stdio.h>
int main()
{
int x = 10;
// Prints address of x
printf("%p", &x);
return 0;
}
|
|
Unary (Asterisk) ( |
To declare a pointer variable:
|
// C program to demonstrate declaration of
// pointer variables.
#include <stdio.h>
int main()
{
int x = 10;
// 1) Since there is * in declaration, ptr becomes a pointer
// varaible (a variable that stores address of another variable)
// 2) Since there is int before *, ptr is pointer to an integer
// type variable
int *ptr;
// & operator before x is used to get address of x.
// The address of x is assigned to ptr.
ptr = &x;
return 0;
}
| |
To access the value stored in the address.
|
// C program to demonstrate use of * for pointers in C
#include <stdio.h>
int main()
{
// A normal integer variable
int x = 10;
// A pointer variable that holds address of var.
int *ptr = &x;
// This line prints the value at the address stored in ptr.
// The Value stored is the value of variable "x"
printf("Value of x = %d\n", *ptr);
// The output of this line may be different in different
// runs even on the same machine.
printf("Address of x = %p\n", ptr);
// We can also use ptr as lvalue (Left hand side of assignment)
*ptr = 20; // Value at address is now 20
// This prints 20
printf("After doing *ptr = 20, *ptr is %d\n", *ptr);
return 0;
}
|
j = *ptr
|
Recursion
https://www.python-course.eu/recursive_functions.php
https://www.geeksforgeeks.org/recursion/
The process in which a function calls itself directly or indirectly is called recursion and the corresponding function is called as recursive function. Using recursive algorithm, certain problems can be solved quite easily. Examples of such problems are Towers of Hanoi (TOH), Inorder/Preorder/Postorder Tree Traversals, DFS of Graph, etc.
A VERY VERY NICE example of recursion is the factorial function: https://www.geeksforgeeks.org/program-for-factorial-of-a-number/
Example:
4! = 4 * 3!
3! = 3 * 2!
2! = 2 * 1
Replacing the calculated values gives us the following expression
4! = 4 * 3 * 2 * 1
Iterative solution (Java):
class Main{
static int factorial(int n){
int res = 1;
for (int i=2 ; i<=n ; i++)
res *= i;
return res;
}
public static void main(String[] args){
System.out.println(factorial(6));
}
}
Recursive solution (Java):
class Main{
static int factorial(int n){
if (n == 0)
return 1;
return n*factorial(n-1);
}
public static void main(String[] args){
System.out.println(factorial(5));
}
}
One line Solution (Using Ternary operator) (Java):
class Main{
int factorial(int n){
return (n == 1 || n == 0) ? 1 : n * factorial(n - 1);
}
public static void main(String args[]){
Main obj = new Main();
System.out.println(obj.factorial(6));
}
}
Binding
A binding is an association between an entity and an attribute, such as between a variable and its type or value, or between an operation and a symbol.
Binding time is the time at which a binding takes place. Bindings can take place at:
- Language design time
- Language implementation time
- Compile time
- Load time
- Link time
- Run time
For example:
- The asterisk symbol (*) is usually bound to the multiplication operation at language design time. At compile time, a variable in a Java program is bound to a particular data type.
- Language design time: Bind operator symbols to operations
- Language implementation time: Bind floating point type to a representation
- Compile time: Bind a variable to a type in
C
orJava
- Load time: Bind a
C
orC++
static variable
to a memory cell - Runtime: Bind a
nonstatic local variable
to a memory cell
Static vs Dynamic Binding
https://techdifferences.com/difference-between-static-and-dynamic-binding.html
A binding is static if it first occurs before run time and remains unchanged throughout program execution.
A binding is dynamic if it first occurs during execution or can change during execution of the program.
Static vs Dynamic Binding in Java
https://www.geeksforgeeks.org/static-vs-dynamic-binding-in-java/
Static Binding:
The binding which can be resolved at compile time by compiler is known as static or early binding. Binding of all the static, private and final methods is done at compile-time .
Why binding of static, final and private methods is always a static binding?Static binding is better performance wise (no extra overhead is required). Compiler knows that all such methods cannot be overridden and will always be accessed by object of local class. Hence compiler doesn’t have any difficulty to determine object of class (local class for sure). That’s the reason binding for such methods is static. Let’s see by an example:
public class NewClass { public static class superclass { static void print() { System.out.println("print in superclass."); } } public static class subclass extends superclass { static void print() { System.out.println("print in subclass."); } } public static void main(String[] args) { superclass A = new superclass(); superclass B = new subclass(); A.print(); B.print(); } }Output:
print in superclass. print in superclass.As you can see, in both cases print method of
superclass
is called. Lets see how this happens:
- We have created one object of
subclass
and one object ofsuperclass
with the reference of thesuperclass
.- Since the
superclass
isstatic
, compiler knows that it will not be overridden insubclasses
and hence compiler knows during compile time which print method to call and hence no ambiguity.As an exercise, reader can change the reference of object B to subclass and then check the output.
Dynamic Binding:
In Dynamic binding compiler doesn’t decide the method to be called. Overriding is a perfect example of dynamic binding. In overriding both parent and child classes have same method . Let’s see by an example:
public class NewClass { public static class superclass { void print() { System.out.println("print in superclass."); } } public static class subclass extends superclass { @Override void print() { System.out.println("print in subclass."); } } public static void main(String[] args) { superclass A = new superclass(); superclass B = new subclass(); A.print(); B.print(); } }Output:
print in superclass. print in subclass.
Here the output differs. But why? Let’s break down the code and understand it thoroughly:
- Methods are not static in this code.
- During compilation, the compiler has no idea as to which
runtime
and therefore the corresponding version of print will be called based on type on object.
Important points
- Private, final and static members (methods and variables) use static binding while for virtual methods (In Java methods are virtual by default) binding is done during run time based upon run time object.
- Static binding uses Type information for binding while Dynamic binding uses Objects to resolve binding.
- Overloaded methods are resolved (deciding which method to be called when there are multiple methods with same name) using static binding while overridden methods using dynamic binding, i.e, at run time.
Statically and Dynamically typed languages
Statically typed languages:
A language is statically typed if the type of a variable is known at compile time. For some languages this means that you as the programmer must specify what type each variable is (e.g.: Java
, C
, C++
); other languages offer some form of type inference, the capability of the type system to deduce the type of a variable (e.g.: OCaml
, Haskell
, Scala
, Kotlin
)
The main advantage here is that all kinds of checking can be done by the compiler, and therefore a lot of trivial bugs are caught at a very early stage.
Examples: C
, C++
, Java
, Rust
, Go
, Scala
Dynamically typed languages:
A language is dynamically typed if the type is associated with run-time values, and not named variables/fields/etc. This means that you as a programmer can write a little quicker because you do not have to specify types every time (unless using a statically-typed language with type inference).
Examples: Perl
, Ruby
, Python
, PHP
, JavaScript
Most scripting languages have this feature as there is no compiler to do static type-checking anyway, but you may find yourself searching for a bug that is due to the interpreter misinterpreting the type of a variable. Luckily, scripts tend to be small so bugs have not so many places to hide.
Most dynamically typed languages do allow you to provide type information, but do not require it. One language that is currently being developed, Rascal, takes a hybrid approach allowing dynamic typing within functions but enforcing static typing for the function signature.
Reflection
http://tutorials.jenkov.com/java-reflection/index.html#java-reflection-example
https://docs.oracle.com/javase/tutorial/reflect/index.html
A programming language that supports reflection allows its programs to have runtime access to their types and structure and to be able to dynamically modify their behavior.
- The types and structure of a program are called
metadata
- The process of a program examining its metadata is called
introspection
- Interceding in the execution of a program is called
intercession
Java Reflection makes it possible to inspect classes, interfaces, fields and methods at runtime, without knowing the names of the classes, methods etc. at compile time. It is also possible to instantiate new objects, invoke methods and get/set field values using reflection. http://tutorials.jenkov.com/java-reflection/index.html#java-reflection-example
Uses of reflection for software tools:
- Class browsers need to enumerate the classes of a program
- Visual IDEs use type information to assist the developer in building type correct code
- Debuggers need to examine private fields and methods of classes
- Test systems need to know all of the methods of a class
Downsides of Reflection:
- Performance costs
- Exposes private fields and methods
- Voids the advantages of early type checking
- Some reflection code may not run under a security manager, making code non-portable
Reflection in Java
- Limited support from
java.lang.Class
- Java runtime instantiates an instance of
Class
for each object in the program
- The
getClass
method ofClass
returns theClass
object of an object
float[] totals = new float[100];
Class fltlist = totals.getClass();
Class stg = "hello".getClass();
- If there is no object, use class field:
Class stg = String.class;
- Class has four useful methods:
getMethod
searches for a specific public method of a classgetMethods
returns an array of all public methods of a classgetDeclaredMethod
searches for a specific method of a classgetDeclaredMethods
returns an array of all methods of a class- The
Method
class defines the invoke method, which is used to execute the method found bygetMethod
Here is a quick Java Reflection example to show you what using reflection looks like:
Method[] methods = MyObject.class.getMethods();
for(Method method : methods){
System.out.println("method = " + method.getName());
}
This example obtains the Class object from the class called MyObject. Using the class object the example gets a list of the methods in that class, iterates the methods and print out their names. http://tutorials.jenkov.com/java-reflection/index.html#java-reflection-example
Languages evaluation criteria
https://www.cs.scranton.edu/~mccloske/courses/cmps344/sebesta_chap1.html
Readability | Writability | Reliability | Cost | Other criteria |
---|---|---|---|---|
This refers to the ease with which programs (in the language under consideration) can be understood. This is especially important for software maintenance.
|
This is a measure of how easily a language can be used to develop programs for a chosen problem domain.
|
This is the property of performing to specifications under all conditions.
|
The following contribute to the cost of using a particular language:
|
|
Some programming paradigms
Imperative vs Declarative programming paradigm
https://codeburst.io/declarative-vs-imperative-programming-a8a7c93d9ad2
- Imperative programming style:
- Focused on describe HOW the computer should accomplish the task.
- A more formal definition: Imperative programming is a programming paradigm that uses statements that change a program's state.
- Your code focuses on creating statements that change program states by creating algorithms that tell the computer HOW TO DO THINGS. It closely relates to how hardware works. Typically your code will make use of conditinal statements, loops and class inheritence.
- Procedural and object-oriented programming belong under imperative paradigm:
C
,C++
,C#
,PHP
,Java
and of courseAssembly
.
- Procedural and object-oriented programming belong under imperative paradigm:
- Example of imperative code in JavaScript:
class Number { constructor (number = 0) { this.number = number; } add (x) { this.number = this.number + x; } } const myNumber = new Number (5); myNumber.add (3); console.log (myNumber.number); // 8
- Declarative programming style:
- Focused on describe WHAT the computer should accomplish.
- A more formal definition: Declarative programming is a programming paradigm that expresses the logic of a computation without describing its control flow:
- Declarative code focuses on building logic of software without actually describing its flow. You are saying WHAT TO DO WITHOUT ADDING HOW. For example with HTML you use
to tell browser to display an image and you don’t care how it does that.
- Declarative code focuses on building logic of software without actually describing its flow. You are saying WHAT TO DO WITHOUT ADDING HOW. For example with HTML you use
- Logic, functional and domain-specific languages belong under declarative paradigms and they are not always Turing-complete (they are not always universal programming languages). Examples:
HTML
,XML
,CSS
,SQL
,Prolog
,Haskell
,F#
andLisp
.
- Logic, functional and domain-specific languages belong under declarative paradigms and they are not always Turing-complete (they are not always universal programming languages). Examples:
- Example of declarative code in JavaScript:
const sum = a => b => a + b; console.log (sum (5) (3)); // 8
Procedural programming paradigm
Procedural vs Functional vs Object-Oriented Programming
Can we do Object-Oriented Programming with ANSI-C? Yes! this book explains how to do it: https://www.cs.rit.edu/~ats/books/ooc.pdf
https://www.codecademy.com/articles/cpp-object-oriented-programming
https://owlcation.com/stem/Use-Of-Object-Oriented-Programming
https://searchapparchitecture.techtarget.com/definition/object-oriented-programming-OOP
https://www.geeksforgeeks.org/object-oriented-programming-oops-concept-in-java/
http://ee402.eeng.dcu.ie/introduction/chapter-1---introduction-to-object-oriented-programming
Object-Oriented Paradigm
Functional Programming
Scripting
https://www.geeksforgeeks.org/whats-the-difference-between-scripting-and-programming-languages/
Basically, all scripting languages are programming languages. The theoretical difference between the two is that scripting languages do not require the compilation step and are rather interpreted.
https://www.pcmag.com/encyclopedia/term/scripting-language
http://pages.di.unipi.it/corradini/Didattica/AP-19/DOCS/Scott-ch13.pdf