0% found this document useful (0 votes)
9 views21 pages

APLC Notes

The document provides an overview of various programming paradigms, focusing on functional programming concepts such as purity, higher-order functions, currying, and immutability. It discusses the advantages and disadvantages of different paradigms, including declarative and imperative programming, and highlights the importance of recursion in functional programming. Additionally, it covers key topics like lambda functions, nullability, and the differences between mutable and immutable objects.

Uploaded by

mahi way
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
9 views21 pages

APLC Notes

The document provides an overview of various programming paradigms, focusing on functional programming concepts such as purity, higher-order functions, currying, and immutability. It discusses the advantages and disadvantages of different paradigms, including declarative and imperative programming, and highlights the importance of recursion in functional programming. Additionally, it covers key topics like lambda functions, nullability, and the differences between mutable and immutable objects.

Uploaded by

mahi way
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 21

APLC Notes

Contents
Programming Paradigms.............................................................................2
Purity and HOF............................................................................................5
Currying and Partial Applications................................................................7
Lambda.....................................................................................................10
Immutability and Nullability......................................................................11
Recursion:..................................................................................................14
Logic Programming and Prolog:.................................................................15
Evaluation Strategy:..................................................................................17

All the underlined topics need more focus


Programming Paradigms

What is a Paradigm/Functional programming paradigm ?


 A framework that expresses a set of assumptions, concepts, values, and practices that
constitutes a way of solving and thinking thinking through problems
 Acts as a methodologies to solve problems
 Focus is on adopting Programming concepts and techniques and Not on programming
languages .
 Model of Computation:- A formal system that defines how computations work.
 It involves concepts like data types, operations pprogramming techniques and design
principles. Programmers implement these using computational models.

Programming paradigm
 An approach to programming based on a mathematical theory
 Each concept is best suited for certain kind of problem
 OOP best for problems with high no. of data abstractions.
 Logic programming best for navigating complex code
 Each paradigm consists of different structures, features, and opinions
 Solving a programming problem requires the correct solution = concepts
 Javascript is a multi paradigm model.

 Declarative Programming Paradigm


o Description: Expresses the logic of computation without specifying control
flow.
o Focus: Emphasizes what tasks need to be done rather than how they are
done.
o Advantages:
 High Abstraction: Developers work at a higher level of abstraction.
 Independence Maintenance: Changes in implementation details
don’t affect the overall logic.
 Efficient Solution Outline: Concise representation of problem-
solving steps.
o Disadvantages:
 Conceptual Complexity: Can be challenging to understand for
beginners.
o Example: When you jump in a taxi, you declare your destination to the
driver.
 Imperative programming paradigm
o Description: Implements algorithms in explicit steps, focusing on changing
program states.
o Advantages:
 Logical: Follows a clear sequence of instructions.
 Simple Implementation: Easy to write and understand.
 Contains Loops and Variables: Allows iterative processes.
o Disadvantages:
 Ineffective for Complex Problems: Not suitable for solving intricate
problems.
 Less Efficient and Productive: Requires more code for the same
functionality.
 No Parallel Processing: Difficult to parallelize.
o Example
 Var name = “APU”
 Var greeting = “Hello”
 Println(greeting + name)
 Giving explicit information to your friend on how to arrive to your
house
 Logic programming
o Description: Focuses on knowledge representation and problem-solving
based on formal logic.
o Requires a knowledgebase to service queries for results.
o Execution: Like proving mathematical statements; expressing facts and rules
about problems.
 Focus is on what should be done without specifying exact steps
 Unlike Imperative Programming
o Benefits:
 High Abstraction: Developers work at a higher level of abstraction.
 Independence Maintenance: Changes in implementation details
don’t affect overall logic.
 Efficient Solution Outline: Concise representation of problem-
solving steps.
o Example: Prolog
 % Facts: Define parent-child relationships
 parent(art, bob).
 parent(art, bea).
 parent(bob, cal).
 parent(bob, cam).
 parent(bea, cat).
 parent(bea, coe).
 % Rules: Define grandparent relationship
 grandparent(X, Y) :- parent(X, Z), parent(Z, Y).
 Database / Data driven programming
o Description: Program statements are defined by data rather than hard-
coding steps.
o Example: Database entry programs, updating databases using SQL prompts.
o SQL prompts
 SELECT department_id, COUNT(*) AS number_of_employees FROM
employees
 Functional programming
o By Alonzo Church: Introduced lambda calculus.
o It is a software development approach that uses pure functions to create
software useful for parallelism and maintainability. In other words, programs are
built by applying and combining functions.
o Purpose: Efficiently deals with lists and data structures.
o Pure Functions: Create software for parallelism and maintainability.
o Example Languages: Haskell, JavaScript, Java.
o Manipulating as a Whole: Focuses on whole data structures, not individual
elements.
 Rather than by taking each element and manipulating it separately
as procedural programming would
o A single expression
 Executed by evaluating the expression
o Benefits: Parallel processing, maintainability.
o Focused on the ‘what’ not the ‘how’
o Example
 Why functional programming?
o More readability
o More maintainability as pure functions donot change state.
o Dependent on input
o Easy to understand.
o Easier to handle Concurrency and parallel execution due to lack of side
effects as pure functions are immutable.
o High Predictability thus makes debugging easier due to pure functions take
arguments once and produce same output.
 Functions take values once and produce unchangeable output
o High Reusability :Higher order functions enable you to write reusable pieces
of code

Purity and HOF


What is referential transparency
o A property that allows an expression to be replaced by a value without
changing the results of whatever is being done
o A fundamental concept in functional programming that refers to the
property of a function to yield the same result with the same arguments
o Instead of x = plusone(y), we do x = y++
o Referential Transparent Function (given an input and function it can be
replaced with the value instead of calling function).
o Referential Opaque Function ( cannot guarantee same result, even with
same arguments)
o

What is purity?
o A crucial concept in functional programming style that provides the ability
for the functions to avoid side effects and remain deterministic. It enables the
possibility of parallel processing of functions without worrying of the possibilities
of side effects.
o When working with a pure function
 Obtain the same results every time you call the function
 Reverse the order of calls to different functions
 Process the function calls in parallel without any consequence
 Evaluate the function calls in any order, assuming that the entire
language does not allow side effects
 Remove the function if no other functions rely on its output

What is Side Effects?

 It is the change in state or interaction with external elements during execution.


 Occurs when operation modifies state variable(s) outside its local environment.
 Observable effect beyond returning a value to the caller.
 Examples include user interaction, web service calls, and changes to external
systems during calculation or processing.
 Further Examples: Changing global variables, Mutating objects received as
arguments., Performing any I/O, such as showing an alert message or logging some
text, Writing to the file, Writing to the network

In reference to above impure function


- First side effect: Dependency on 'y' means 'fip()' will return an error if 'y' is
unavailable or undefined.

- Second side effect: 'fip()' modifies external code by mutating the state of 'y'.

- Third side effect: Inclusion of external code in 'fip()' makes it non-deterministic, as


its output cannot be determined solely by examining it.

Lambda
o A function that can be created without belonging to any class.
o Also called arrow function in javascript
o Can be passed around as an object or execute on demand
Example

Higher order functions


o A function that takes a function as an argument or returns a function .
o First order functions do not take function as an argument or return a
function. Under HOF also includes reduce, map and filter functions.
Example:
 Map function map()
o Mapping is a fundamental functional programming technique for operating
on all the elements in an array and producing another array of the same length
with transformed content
o Example
 Const double = x => x * 2;


 Reduce function
o Reducing an array in a single value
o Iteration returns an accumulated value based on the previous result
o Value is kept until the end of the array is reached
o Result is always a single value
o Example : To get sum of lengths of the words in animals array as number

Currying and Partial Applications

 Function as value, function as argument, function returns function


 Variables are not allowed to change their values; constant variables
 Object is a software component that encapsulates state and
behavior together into a single entity in memory
o Not primitive data types
o Ways of creating an object
 Object literals
 Serializing objects
 Classes are dynamic, so don’t make it unnecessarily rigid
o Class Inheritance causes these few problems
 Tight coupling
 Inflexible hierarchies
 Use cases keep changing, so current
solution may be wrong in the future
 But tight coupling makes the refactoring
difficult
 Gorilla/banana problem
 No selective inheritance
 “You wanted a banana but what you got was
a gorilla holding the banana and the entire
jungle.” Joe Armstrong in “Coders at Work”
 Duplication by necessity
 Code reuse by copy and paste

 First class object


o Functions nested within other functions
o Functions that are passed as an argument into another
function
o Functions declared as variables

Figure 1: Function as Function


Figure 2: Function as a variable

Figure 3: Function as a argument

 Currying
o The process of taking a function that accepts n
arguments and turning it into n functions that each accepts
a single argument .

 Arity
o It represents The numbers of arguments a function
takes.
o Unary = 1 parameter
o Binary = 2 parameters
o Ternary = 3 parameters
o n-nary = takes n number of arguments
o Nullary = 0 parameters
Currying transforms a n-nary function into n unary
function.
 Partial application
o The process of fixing several arguments to a function,
producing another function of smaller arity .

 Full application
o Applying all arguments of a function
o Applying fewer arguments than the total is a partial
application

Lambda
 Lambda Calculus
o A framework To study the interaction of functional abstraction and function
application from an abstract, purely mathematical perspective
o Functional abstraction begins by breaking a particular problem into a series
of steps
o Function application is the act of applying the function to an argument and
obtaining value as output
o Lambda calculus uses only functions
o Lambda calculus has no state or side effects
o Order of evaluation is irrelevant
o Functions are unary, receiving one argument
 A Lambda expression is a short function that uses arrow-function
o It has No name is assigned to it
Functions vs Methods
 A function is a piece of code that can be called by its name
 Can pass arguments and return values optimally
 A method is a piece of code that is called and associated with an object
Lambda parameters
 Expressions are effectively just functions
 Can take parameters
o Zero
o One
o Multiple
Example :

Advantages of lambda functions


 Pure functions
 Easy to read
 Easy to cache
 Concise function / syntax
Example:

Callback functions
 Computer programs may not always run sequentially.
o But code can run asynchronously.
 Callbacks make sure that a function is not going to run before a task is completed.
o Keep the code safe from problems and errors.
o It aids in developing asynchronous code.
Example

Immutability and Nullability


Immutability in Functional Programming
 A concept in functional programming that involves not
changing the state or contents of a piece of data once it is
created
o Allows for easier and Simpler application development
process
o No defensive copying
o Enabling advanced memoization
o Good change detection techniques with simple logic
o In JavaScript
 Primitive values are immutable but can be
reassigned
 Objects and arrays are mutable by default

 Closures
o A data structure that binds a function to its environment
when it’s declared
 A static or lexical scope surrounding the function
definition
o Allows you to create functions that can remember and
modify variables from their outer scope
o Useful for handling private data and encapsulation
o Allow you to associate data with a function that operates
on that data

 Memoization
o An optimization technique used primarily to speed up
computer programs
o By storing the results of expensive function calls to pure
functions
o Returning cached result when the same inputs occur
again
o Also known as tabling

 Nullability
o Ability of variables to have an absence of value
Example:
o Variable not initialized
o Function failed to construct objects or any computation
o Component is not required or disposed
o Often nullability is represented using null, nil, none etc
o Handle nullability
 Null-check : Use annotations like
@NonNull,@Nullable, or isNull in lodash,js, Optional in
Java
 Example :
Immutability Concepts
 Immutable Classes
o Design your custom classes to be immutable by:
 Making fields final (so they cannot be modified
after initialization).
 Not providing setter methods.
 Returning new instances instead of modifying
existing ones.
 Immutable Collections
o Use immutable versions of collections (e.g., List.of,
Set.of, Map.of) provided by Java.
o These collections cannot be modified after creation.
o Example: List<String> names = List.of("Alice", "Bob",
"Charlie");
 String Immutability
o Strings in Java are immutable by design.
o Any operation on a string creates a new string instance.
o Avoid using += or concat for string concatenation;
prefer StringBuilder.
 Defensive Copying
o When returning a mutable object from a method, return
a defensive copy to prevent modification.
o Example
 public List<Integer> getNumbers() {
return List.copyOf(numbers); // Defensive copy
}
 Thread Safety with Immutability
o Immutable objects are inherently thread safe.
o Use them for shared data structures to avoid
synchronization issues.

Difference btw immutable and mutable objects:


NullPointerException in OOP:
NullPointerException is an exception that occurs in object-oriented programming languages
when you try to access or manipulate an object that is null (i.e., it does not reference an
actual object). This typically happens when you attempt to call a method or access a
property on a null object reference. In languages like Java, it's a common runtime error that
can crash the program if not handled properly.

Recursion:
A technique for solving problems by breaking them down into

smaller, self-similar instances of the same problem.
 Must have a base case (stop condition) and a recursive case
(where it calls itself with a smaller input).
 Is essential in pure functional programming languages that
lack looping constructs.
Recursion vs. Iteration:
 Recursion
o Involves a function calling itself
o It can be more concise and readable but may consume
more memory due to the function call stack.
 Iteration
o Uses loops.
o More memory-efficient, but recursive solutions can be
more elegant for certain problems.
 Any recursive problem can be solved iteratively, but not all
problems have a natural recursive solution.
Head Recursion and Tail Recursion:
 Head recursion occurs when the recursive call is not the last
operation in the function.
o Check for recursive condition first
o Base case is evaluated last
 Tail recursion happens when the recursive call is the last
operation performed by the function.
o Base case is evaluated first
o If base case is not fulfilled, then proceed to recursion
call
 Tail recursion can be optimized by some
compilers/interpreters to use a constant amount of stack space,
making it more memory efficient.
Functional Programming and Recursion:
 Recursion is a fundamental technique in functional
programming, where side effects are avoided.
 Functional programming focuses on operations rather than
data structures, promoting code that is easier to reason about.
 Recursion helps achieve this by breaking down problems into
smaller, self-similar instances, removing local side effects.
Benefits of Recursion:
 Can lead to more concise and readable code for certain types
of problems.
o Readability and Maintainability
 Promotes a functional programming style by avoiding side
effects and mutable states.
o Predictability
 Encourages breaking down complex problems into simpler,
self-similar sub-problems.
o Abstraction & Encapsulation
Additional Context:
 Recursion has a wide range of applications
o Traversing data structures (e.g., trees, linked lists)
o Solving mathematical problems (e.g., factorial, Fibonacci
series)
o Implementing algorithms (e.g., merge sort, quicksort).
 While recursion can be elegant and powerful, it's essential to
ensure that the base case is correctly defined to avoid infinite
recursion, which can lead to stack overflow errors.
 Functional programming languages often favor recursion over
iteration due to their focus on immutable data and avoiding side
effects.
In summary, recursion is a fundamental technique in functional
programming that promotes breaking down complex problems into
simpler, self-similar instances, leading to more concise and readable
code while avoiding local side effects. However, it's important to
consider its memory implications and ensure the correct base case
is defined to prevent infinite recursion.

Logic Programming and Prolog:


 Logic programming is a functional programming paradigm
that views programs as logical theories rather than step-by-step
algorithms.
 Prolog (Programming in Logic) is a language designed for logic
programming, developed in 1972.
 Prolog programs consist of facts and rules that model a
problem domain by expressing relationships between entities.
Facts and Rules:
 Facts are declarative statements about the problem domain,
represented as predicates.
 Rules define new predicates using logical implications based
on existing facts and rules (Horn clauses).

Backtracking:
 Prolog uses backtracking to find all possible solutions to a
query by exploring alternative variable bindings.
o Like solving a puzzle by testing different pieces until
they fit together perfectly
 If a set of variable bindings fails to satisfy a goal, Prolog
backtracks and tries a different set of bindings.
Data Structures and Pattern Matching:
 Prolog supports compound terms (structures) as arguments to
predicates, allowing for complex data representations.
 Pattern matching is used to match queries against facts and
rules, with variables, constants, and structures following specific
matching rules.
Logical Negation and Closed-World Assumption:
 Prolog uses negation as failure, where a proposition is
considered false if it cannot be proven from the given facts and
rules.
 This is based on the closed-world assumption, where Prolog's
knowledge is limited to the provided facts and rules.

Applications of Prolog:
 Prolog is well-suited for tasks like databases, expert systems,
theorem proving, and natural language processing.
 Its declarative nature and backtracking capabilities make it
useful for solving problems that involve logical reasoning and
symbolic manipulation.
Additional Context:
 Prolog differs from imperative programming languages in its
approach to variables, machine model assumptions, and
execution model.
 While Prolog has its strengths, it may not be suitable for all
types of problems, especially those requiring extensive numerical
computations or high-performance requirements.
 Prolog has various implementations with different syntax and
semantics, such as SWI Prolog, which has an active user
community.

Lists in Prolog:
 Lists are a fundamental data structure in Prolog, represented
using square brackets and commas to separate elements.
 Lists can contain constants, variables, structures, and even
sublists.
 The empty list is represented as [].
Head and Tail of Lists:
 Prolog provides a mechanism to separate the first element
(head) from the rest of the list (tail) using the | operator.
 This allows for pattern matching and recursive operations on
lists.
Pattern Matching with Lists:
 Pattern matching is a powerful feature in Prolog for working
with lists.
 Variables can match any element, and the anonymous
variable _ matches any single element.
 Structures can match other structures with the same functor
and matching arguments.
Recursive Rules for Lists:
 Many list operations in Prolog are defined using recursive
rules.
 The base case typically handles the empty list, while the
recursive case operates on the head and tail of the list.
 Examples include the last predicate to find the last element of
a list, and the member predicate to check if an element is a
member of a list.
List Predicates:
 Prolog provides built-in predicates for common list operations,
such as member, append, and reverse.
o Member

Evaluation Strategy:
 An evaluation strategy defines the rules for evaluating
expressions in a programming language.
 Concept: parameter-passing strategy which defines what kind
of value is passed to a function for each parameter, sometimes
called binding strategy, and then evaluated.
 For example, executing a function call f(a,b) first evaluates
and stores the arguments a and b. The result is at the reference
or memory locations ref_a and ref_b and the body of the function
is evaluated using the passed references – call-by-reference
evaluation
 It specifies the order in which expressions are evaluated and
how arguments are passed to functions.
Evaluation Order:
 Evaluation order determines the sequence in which sub-
expressions are evaluated within an expression.
 Different languages may have different evaluation orders
(e.g., left-to-right, right-to-left, or unspecified).
 Example :
o JS ,Java and C # programs have left to right evaluation
order
o OCaml has right to left evaluation order
o C++ have unspecified order
Strict vs. Non-Strict Evaluation:
 Strict evaluation (eager /greedy evaluation) means that
function arguments are fully evaluated before the function is
applied.
o Uses call-by-value and call-by-reference
 Non-strict evaluation (lazy evaluation) means that arguments
are not evaluated until their values are needed within the
function.
 Haskell is a well-known non-strict language, while most
mainstream languages like JavaScript, Java, and C++ use strict
evaluation.

Call By Reference:
 Also known as call-by-address or pass-by-reference, pass-by-reference evaluation
strategy allows the caller to pass an expression that is evaluated to a reference
instead of a value. This means that the argument contains a reference pointing to
the memory location of the passed value.
 No Copies: It avoids copying values, instead passing references, which modifies
variables directly.
 Implicit References: Parameters are bound to implicit references, modifying
variables used as arguments.
 Difficulty in Tracing Effects: This strategy makes it harder to trace function call
effects, leading to subtle bugs.

Call By Value

 Definition: In call-by-value (or pass-by-value), the evaluated value of the argument


expression is bound to the corresponding variable in the function. This often involves
copying the value into a new memory region.
 Assignment Limitation: If the function or procedure can assign values to its
parameters, only its local variable is assigned. Anything passed into a function call
remains unchanged in the caller's scope when the function returns.
 Limitation: Call-by-value can lead to performance degradation and memory leakage
due to the need to copy values into new memory regions.
Call by Name:

 Evaluates function arguments by directly substituting them into the function


body without prior evaluation.
 Arguments are only evaluated when they are used within the function body.
 Saves time by not evaluating arguments that are not used in the function.
 If the arguments are not used within the function, call-by-name can avoid
unnecessary evaluation compared to call-by-value.

Call by Need (Lazy Evaluation):

 Similar to call-by-name but uses memoization to avoid unnecessary re-evaluation


of arguments.
 Memoization stores the results of expensive function calls and returns the
cached result when the same inputs occur again.
 Only evaluates the argument's expression once, even if it's used multiple times
within the function's body.
 Produces the same result as call-by-name if the arguments are pure (have no side
effects).
 Haskell is a well-known language that uses call-by-need evaluation.

You might also like