Programming Techniques - robbiehume/CS-Notes GitHub Wiki

Links


Misc.

Anonymous (lambda) functions

  • Anonymous Functions (General):
    • Key Feature: Functions without a name, used in many languages for short-term use (e.g., JavaScript, Python, Java, etc.)
      • Often used as arguments to higher-order functions
  • Arrow functions (JavaScript):
    • Syntax: (params) => { expression }
    • Key feature: inherits this from the surrounding scope in which it was defined
      • This differs from traditional functions, where the value of this depends on how the function is called instead of how it's defined
    • Example: const add = (a, b) => a + b;
  • Lambda functions (Python):
    • Syntax: lambda <arg(s)>: expression
    • Key feature: single-expression anonymous functions
    • Example: add = lambda a, b: a + b
  • Lambda expressions (Java, etc.):
    • Syntax: (params) -> expression or (params) -> { statements }
    • Key feature: introduced in Java 8, often used in functional interfaces
    • Example: (a, b) -> a + b

First-class functions vs Higher-order functions (link)

  • Comparison
  • Languages that have first class functions: Javascript, Python, PHP, Ruby, etc.
  • Non-functional programming languages such as C++, C and Java have limited support or no support for first class functions
  • First-class functions are functions that are treated like an object (or are assignable to a variable)
    • When you say that a language has first-class functions, that means that the language treats functions as values – that you can assign a function to a variable, pass it around, etc.
  • Higher-order functions are functions that take at least one first-class function as a parameter, or return at least one first-class function
    • Types of higher-order functions: map(), filter(), reduce()
  • Example with first class and higher order functions:
    def add(x, y): 
        return x + y 
    def subtract(x, y): 
        return x - y 
        
    # A higher order function to use the above functions 
    def compute(operation, x, y): 
        return operation(x, y) 
    
    # Now you can call the 'compute' function with any operation you want 
    result = compute(add, 2, 3) 
    print(result) # prints: 5 
    result = compute(subtract, 7, 3) 
    print(result) # prints: 4 

filter(), map(), and reduce()

  • .filter() / .map() / .reduce() article
  • filter():
    • Purpose: to create a new collection by including only the elements that satisfy a specific condition.
    • How it works: you provide a function (predicate) that returns true or false for each element in the collection. Only the elements that return true will be included in the new collection
  • map():
    • Purpose: to create a new collection by transforming each element in the original collection.
    • How it works: you provide a function that applies some operation to each element, and the result of this function is used in the new collection
  • reduce():
    • Purpose: to reduce a collection of elements into a single value by applying a function.
    • How it works: you provide a function that accumulates a result by processing each element in the collection. The function takes two arguments: an accumulator and the current element, and returns the updated accumulator

JavaScript

  • const numbers = [1, 2, 3, 4];
    const evenNumbers = numbers.filter(num => num % 2 === 0);  // [2, 4]
    const doubled = numbers.map(num => num * 2);  // [2, 4, 6, 8]
    const sum = numbers.reduce((acc, num) => acc + num, 0);  // 10

Java

  • List<Integer> numbers = Arrays.asList(1, 2, 3, 4);
    List<Integer> evenNumbers = numbers.stream()
                                       .filter(num -> num % 2 == 0)    // keep only even numbers
                                       .collect(Collectors.toList());  // [2, 4]
    List<Integer> evenNumbers = numbers.stream()
                                       .map(num -> num * 2)            // double each number
                                       .collect(Collectors.toList());  // [2, 4, 6, 8]
    int sum = numbers.stream()
                     .reduce(0, (accumulator, current) -> accumulator + current);  // 10
  • Like JavaScript, Java also supports chaining:
    • int result = numbers.stream()
                          .filter(num -> num % 2 == 0)  // filter even numbers: [2, 4]
                          .map(num -> num * 2)          // double the values:   [4, 8]
                          .reduce(0, Integer::sum);     // sum them up:     4 + 8 = 12
      

Python

  • List comprehensions / generator expressions are often faster than filter() / map() / reduce() combinations
    • Example: [x * 2 for x in numbers if x % 2 == 0] is faster than list(map(lambda x: x * 2, filter(lambda x: x % 2 == 0, numbers)))

Closures (link)

  • A closure is an inner function that remembers and has access to variables in the local scope in which it was created, even after the outer function has finished executing
  • The use of closures is associated with languages where functions are first-class objects, in which functions can be returned as results from higher-order functions, or passed as arguments to other function calls

Decorators and Wrappers

  • A decorator is just a function that takes another function as an argument, adds some kind of functionality, and then returns another function
    • All of this without altering the source code of the original function that was passed in
    • In essence, decorators are a kind of higher-order function
  • A wrapper is something that wraps a function, usually adding some extra behavior to it
  • A decorator is a type of wrapper; an adaptor is another type of wrapper

Currying (partial functions)

  • Currying refers to creating new functions from existing functions by applying partial arguments
    • Thus, this concept is sometimes also termed partial functions
  • In simple terms, Currying is used to transform a multiple-argument function into a single-argument function by evaluating incremental nesting of function arguments
  • The purpose of function currying is to easily get specialized functions from more general functions

Generators

  • Generators allow us to look at one value at a time and to not store the entire sequence of numbers when it's not necessary to

Coroutines / Subroutines

⚠️ **GitHub.com Fallback** ⚠️