Enum lab questions?

Free Vaccines Tomorrow

  • Over 350 students and faculty are signed up
  • You can still sign up (Walkins welcome)
  • 10am to 1pm in Reardon lobby

It is a great vaccine. It is a safe vaccine, and it is something that works.

– Donald Trump (source, also CDC)

Control Abstraction

Chapter 9

Abstraction

  • Allows us to hide complexity behind simpler interfaces

Data Abstraction

  • Create complex data structures with simple interfaces to pass around (e.g. records, structs, dictionaries, etc)

Control Abstraction

  • Create organized sections of executable code that execute in well-understood ways and can be reused

Subroutine

  • Performs operations for the caller while the caller waits
  • Arguments, or actual parameters, are passed to subroutines and mapped to formal parameters from the subroutine definition
  • Subroutines that can return values can be called functions

Call Stack

  • Memory space for functions to use to store local variables, return addresses, and other data
  • Function calls push a new frame to the stack
  • Returns pop their frame when they are finished with it

Call stack review resources

Parameter Passing

Pass by Value

  • Actual parameter values are made available to the subroutine
  • Modification of values will not impact the caller
  • This may involved making a copy in memory

Pass by Reference

  • Actual parameters are references to data from the caller
  • Modification of values will impact caller
  • Should not involve copying data

C

  • Pass by value
#include <stdio.h>

void increment(int i) {
  // This will not change the callers value
  i = i + 1;
}

int main(void) {
  int i = 0;
  increment(i);
  printf("%d\n", i);
}
  • If we want to be able to modify values, we need to pass values by reference
  • We can’t do this is C, but we can use pointers passed by value to emulate it
#include <stdio.h>

void increment(int* i) {
  // This will change the callers value
  *i = *i + 1;
}

int main(void) {
  int i = 0;
  increment(&i);
  printf("%d\n", i);
}

If we allow C++, we can use a proper pass by reference mode.

#include <stdio.h>

void increment(int &i) {
  // This will change the callers value
  i = i + 1;
}

int main(void) {
  int i = 0;
  increment(i);
  printf("%d\n", i);
}

Python

  • Pass by object reference
  • Numbers and strings are passed by value
  • Composite types such as objects are passed as a reference
def increment(i):
  // Only modifies local value
  i = i + 1

i = 0
increment(i)
print(i)

Callers will be able to see modifications to mutable objects

def append(mylist, value):
  mylist.append(value)

mylist = []
append(mylist, 1)
print(mylist)

Callers will still hold a reference to the exact same object

def empty(mylist):
  # The caller won't be impacted by this reassignment
  mylist = []

mylist = [1,2]
empty(mylist)
print(mylist)

Immutable objects (such as tuples or strings) can’t be modified for the caller

Optional Parameters

  • Some languages allow us to mark parameters as optional
  • We may be able to provide a default value
  • In some languages all parameters are optional

Python allows us to annotate optional parameters by providing default values

def remove_character(mystring, character=" "):
  return mystring.replace(character, '')

print(remove_character("Hello, World!"))

All parameters are optional in Javascript

function print(a) {
  console.log(a)
}

print('Hello, World!')
print() // This is not an error in JS

Named Parameters

  • We’ve been exploring positional parameters
  • Some languages allow them to be used by name
  • This can be very helpful, especially combined with optional parameters
def make_vehicle(type='car', color='red', max_speed=55):
  return (type, color, max_speed)

print(make_car(color='blue'))

Variable Numbers of Arguments

  • It can sometimes be helpful to accept a different number of arguments
  • One example of this is printf in C
int printf ( const char * format, ... );

Function Returns

  • End the function
  • Return some value
  • In languages without separate statements, the return is simply the value of the function body
  • Some languages allow for implicit returns
fn get_num() -> u8 {
  42
}

fn main() {
  println!("{}", get_num());
}

Events

  • Event happens outside of program at unpredictable times
  • Running programs wants to respond

Blocking

  • We simply wait for an event to complete
import urllib.request
import json

junk_foods = [
  'Pizza',
  'Popcorn',
  'Hamburger',
  'Pepsi',
  'Potato_chip',
  'Cake',
]

url = 'https://en.wikipedia.org/w/api.php?action=parse&format=json&page='

for food in junk_foods:
  contents = urllib.request.urlopen(f'{url}{food}').read()
  print(f"{food}: {json.loads(contents)['parse']['properties'][0]['*']}")
const https = require('https')

junk_foods = ['Pizza', 'Popcorn', 'Hamburger', 'Pepsi', 'Potato_chip', 'Cake']

url = 'https://en.wikipedia.org/w/api.php?action=parse&format=json&page='

junk_foods.forEach(food => {
  https.get(
    {
      host: 'en.wikipedia.org',
      path: '/w/api.php?action=parse&format=json&page=' + food,
    },
    function (res) {
      let body = ''
      res.on('data', function (d) {
        body += d
      })
      res.on('end', function () {
        console.log(`${food}: ${JSON.parse(body).parse.properties[0]['*']}`)
      })
    },
  )
})