Taught by Professor Toby Donaldson
History of Programming Languages
Programming languages are developed organically based on the developer's needs.
The three most influential languages were Fortran, LISP, and COBOL
Fortran (1957), stands for Formula Translator, was the first language to incorporate variables, before this it was machine languages. John Backus developed this with engineering and science users in mind. Fortran is still actively used today.
LISP (1958), stands for list processing, developed by John McCarthy is a language with a simple core, developed with math users in mind.
COBOL (1950's), asscoiated with Grace Hoppe, for business users, stands for Common Business Oriented Language.
we briefly mentioned the below languages
Algol (1960's), was another pioneer language, but was not heavily adopted.
SmallTalk (1970's), asscoiated with Alan Kay and XEROX parc, help popularized object oriented programming in North America. inspired by Simula and LISP
Prolog (1970's), developed with logic in mind, for AI and parsing English, syntax is based on first order logic.
Ways to Organize Languages:
Declarative vs Procedural
Declarative languages like markup, SQL, prolog.
Procedural languages like Von Neuman (C Ada Fortran) , Object Oriented (java, smalltalk), or Script (python ruby perl)
Compiled vs Interpretted
Compiled programs (C, Fortran) are very efficient, compilers can find errors before program is run, and it can do static analysis (checking something against the soruce code)
Interpretted programs (like Python, LISP) are good for fast development, allow codes to be created on the fly, but it is slower than compiled codes
Golang
Developed at Google, a way to replace C++ for writing server, the developers thought C++ took too long to compile.
Go compiles fast, comparable to interpret languages.
Concurrency Support has “Go routines” that are lightweight processes to handle concurrency tasks.
No Exceptions Go relies on explicit error codes return from functions. Whereas error handling in C++, java, leads to convoluted code that treats too many situations as error. Go forces you to explicitly deal with error. (No error you would return nil)
Lightweight typing Go lets you leave off the type, but is still statically typed
Novel use of interface Go does not have classes,but still object oriented by introducing interface
Closure allows passing functions (lambda functions)
Go has really modern set of libraries like fmt thats relevant to web dev.
Go run lets you compile and run in one step
if variables or functions are Uppercase, then its public, (other languages have a explicit public
for these things)
Go has a built in formatter (Go fmt) that conforms your code when you save
the :=
initializes and gives values to a variable , the type is inferred
name := ""
the above is similar to var name string
, name = ""
var name string
fmt.Scanf("&s", &name)
// needs an address of name because Scanf writes in value at the name address
Go uses for
for both for
and while
like in other languages
the for loop pattern is
for i := 0l i < 10; i++ {
//do stuff
}
//range loop
s := "some string"
for i,c := range s{
//do stuff
fmt.Printf("s[%v] = '%v'\n", i, c) // the %v gets the unicode value, %c gets the char
}
the Go compiler says its an error if a variable is declared but not used, the aim is to make things practical by taking out superfluous variables
because of this, the _
keyword is a blank variable in Go, it allows the compiler to run if you dont care about the declared variable.
array is immutable in Go, problem is the length is part of the type.
slice is a dynamic array , builds ontop of an array
var sl []int = []int{1,2,3}
gives starting values to the sl slice
alternatively sl := []int{1,2,3}
we can use the builtin keywords append
and make
to generate slices
map is declared like var notes map[type of key] type of value
the string is the type of the key, and int value
Go returns a value 0 if a key is not there in the map. different from how other languages does it.
panic
is for error checking, and panic immediately ends the program
Go didn't add destructors
, instead, the defer
keyword allows statements to run after function ends, effectively Go programmers adds deferobject.close()
Go does not have inheritence, instead, it has a concept of embed. so if structA has structB inside, and structC. StructA is of a separate type than structB and structC.
need to understand how Go methods and functions interact with method sets
in Go, some key words are bound at language design time, and can't be unbound, like For loop
Compile Time Binding (Static Binding) vs Runtime Binding (Dynamic Binding)
different languages decide on the binding differently, runtime binding gives more flexibility, while compile time binding lets you find mistakes much faster.
Go, C++, Java, Haskell -> are all compiled time binding languages,
Javascript, Python, Ruby, Scheme/Lisp -> are all binding done at runtime.
the bindings are not all distinct like this, all languages implement a mix of both
Memory Allocation
Static -> compile time - eg. global variable , the original Fortran only had static memory variables. but problem is, when we start using functions, we want functions to have their own local variables. so static allocated programs had a hard time accomodating for local variables. which leads to...
Stack (or call stack) -> is created in run time, each stack contains stack frame that stores the local variables at the current function.and automatically pop when the function exits.
Heap ( dynamic)
Summary Of Go easy language for getting a job, write a web server etc.
Scheme
Though Scheme has loop
feature, the course only studies recursion.
Distinctions among symbols, variables, functions and lists:
- x
: variable x
- 'x
: symbol x
- (x parameter1 parameter 2)
: function x with 2 parameters
- '(my dog has fleas)
: a list of 4 elements which are symbols
Example:
(min 3 1)
evalutes to 1
'(min 3 1)
evalutes to (min 3 1)
List Processing
In scheme, we can think of lists like stacks with main operations: car
as peek() that returns the first element, and cdr
as pop() that returns the rest of the list.
Example:
(car '(+ 1 2 3) )
evaluates to '+' sign
Note that '+' sign returned from the above example is not considered the addition operator but just a symbol. Thus, using the returned '+' to feed a calculation pipe line will cause errors:
(+ 1 2)
evaluates 3
((car '(+ 1 2 3)) 1 2)
causes errors
Scheme uses the lazy evaluation technique in evaluating logic operations and
and or
. Scheme stops evaluating and
at the first found false
argument; and stops evaluating or
at the first found true
argument. A similar fearture can be seen in C.
Scheme uses cond
or if
to branch the flow.
(define len ;; this is taught in class
(lambda (lst)
(cond
((null? lst) 0) ;; base case
(else
(+ 1 (len (cdr lst) ) ) )
)
)
)