There are 7 main Programming paradigms:
- imperative : defines what the program would do (in statements, it dictates computer’s executions). Examples: procedural.
- declarative : declares what the program would achieve, rather than how to do it (SQL, regular expression, logic programming, functional programming). It is more about performing calculation and getting result (like Mathematica), not changing state.
- functional : avoids changing state & mutable data (no assignments, only function calling). (Common Lisp, Scheme, Clojure, Racket, Erlang, OCaml, Haskell), it is a declarative, not imperative programming. Functional programming is state-less, compared to imperative which has state.
- first-class functions: functions are treated as first-class citizens, they can be passed as parameters to function or returned as function result.
- anonymous functions (unnamed function) which do not have a name/identifier
- closures: data structure containing a function reference which also has a reference to a table of local variables (Blocks in iOS is a type of Closure)
- procedural : based on procedures.
- The main difference to functional is that procedures can and do change the shared state, while functional doesn’t.
- The main difference to object-oriented is that it is based on having separate data structures and procedures operating on data, while in OO they combine to be objects operating on their “own data structures”.
- object-oriented : objects, polymorphism & inheritance. A way to visualise, making the code an representation of the real world.
- logic : based on logic, it describes a problem using facts & rules.
- Algorithm = Logic + Control:
- A top-level goal, and-or tree as a search space for solutions. Using logic, one top level goal can be split to many sub-goals, which can be solved.
- Many search strategy can be used to solve this, like parallel search, intelligent backtracking, best-first search …
- symbolic (LISP) the program can modify its formulas and program components – like in Artificial Intelligence where the base of programs is used to create more programs, which are then put in competition to survive (Genetic programming).
One of the main characters of a programming language is the type system. When we say strong typed, or weak typed, it indicates the permissive strength of the type system. When a system is strong-typed, it allows less expressions to be valid, than a weak-typed one.
For example, Perl is weaker-typed than Haskell, as in Perl “foo”+2 is 2 when in Haskell the operation is invalid. A stronger is understandably ‘intuitively’ better than a weaker one.
Static & Dynamic: static-typing means that the type is known to compiler at compile-time, before any code execution. Static typing reduces the chance of error.
If we have 2 similar languages with same syntax and everything, but one is static-typing S and one is dynamic-typing D (it’s possible to do this with just a boolean flag in compiler), a program in S would be valid in D. A program in D can encounter more runtime errors.
— Basically anything STATIC is compile-time, and DYNAMIC is runtime.
- Immutability: most functional programmers avoid mutability at all cost.
- It simplifies code a lot when a property is readonly. There are many problems that come with a resource that can change. It’s update, especially in multithreading environment, can be complex. (a read-only file resource avoids all issues of concurrency that can ruin even a Pathfinder).
- Asynchronicity: using delegates to handle async callbacks will make app hard to read, causing delegation forest.
- Completion blocks are more convenient, as completion blocks are declared as the same place with creation code, and have access to the same variables.
- The only issue is with nested completion blocks, which can be a bit long. This can be solved by method chaining, but again it causes many methods and makes the flow not intuitive.
- The author proposed OperationQueue using CDEAsynchronousTaskQueue.