Skip to main content

Recitation 2 -- Functions & Conditionals

Outcomes: 2.1, 3.1

Objectives

  • Practice defining functions and constants in Pyret.
  • Incrementally build a distance function using FCC approximation formula.
  • Use real-world coordinate data (from Google Maps) to test the function.
  • Discover and correct a unit conversion error when the computed value does not match the expected value.

I. Introduction (5 minutes)

  • Overview: Explain that today students will write a function to compute the distance between two points given by latitude and longitude using an approximate formula provided by the Federal Communications Commission (FCC).

II. Setting Up the Problem (10 minutes)

A. Choosing Two Points

  • Activity: Have each student or group select two landmarks (using Google Maps) that are approximately 1 mile apart according to "measure distance" function (right/ctrl click to use it). They should record the latitude and longitude for each point.
  • Defining Constants: Students define their chosen points. For example:
    POINT-A-LAT = 42.3505
    POINT-A-LON = -71.1054

    POINT-B-LAT = 42.3430
    POINT-B-LON = -71.1020
    (Students should use the coordinates they find.)

B. Writing a Helper Function: deg-to-rad

  • Explanation: The FCC approximation formulas use trigonometric functions, and Pyret's require angles to be in radians, whereas latitude & longitude are in degrees.
  • Activity: Have students write a function to convert from degrees to radians:
    fun deg-to-rad(deg):
    PI = ~3.141592653589793
    (2 * PI * deg) / 360
    end
  • Check Understanding: Ask, “How does this function convert an angle from degrees to radians?”

III. Developing FCC Constants (10 minutes)

A. Choosing a Reference Latitude

  • Activity: Let students define a reference latitude using the average of their points:
    REF-LAT = (POINT-A-LAT + POINT-B-LAT) / 2

B. Computing the Conversion Factors

  • Write out these formulae on the board, in normal math, without the deg-to-rad conversion. Students should translate it into code, e.g.:
  • For Latitude (KPDLAT):
    KPDLAT = (111.13209 - (0.56605 * num-cos(deg-to-rad(2 * REF-LAT))))
    + (0.00120 * num-cos(deg-to-rad(4 * REF-LAT)))
  • For Longitude (KPDLON):
    KPDLON = (111.41513 - num-cos(deg-to-rad(REF-LAT))
    - (0.09455 * num-cos(deg-to-rad(3 * REF-LAT))))
    + (0.00012 * num-cos(deg-to-rad(5 * REF-LAT)))
  • Discussion: Walk through the formulas, asking:
    • “What is the role of these constants?”
    • “How do they help convert differences in degrees into distances?”

IV. Building the Distance Function Incrementally (20 minutes)

A. Writing the Function Header and Documentation

  • Activity: Ask students to define a function called dist that computes the distance between two points, given the following signature & docstring:
    fun dist(lat1 :: Number, lat2 :: Number, lon1 :: Number, lon2 :: Number):
    doc: "Calculates the distance between two coordinates using FCC approximation"

B. Step 1: Compute Scaled Differences

  • Activity: Have students compute the differences scaled by the FCC constants:
      NS = KPDLAT * (lat1 - lat2)
    EW = KPDLON * (lon1 - lon2)
  • Prompt: “What do these variables (NS and EW) represent?”

C. Step 2: Compute the Euclidean Distance

  • Activity: Next, compute the raw distance using the Pythagorean theorem:
      num-sqrt(num-sqr(NS) + num-sqr(EW))
    end

D. Step 3: Writing a Test Case

  • Scenario: Explain that the two points were chosen to be about 1 mile apart.

  • Activity: Ask students to add a test case using a where clause. For example:

    fun dist(lat1, lat2, lon1, lon2):
    doc: "Calculates the distance between two coordinates using FCC approximation"
    NS = KPDLAT * (lat1 - lat2)
    EW = KPDLON * (lon1 - lon2)
    num-sqrt(num-sqr(NS) + num-sqr(EW))
    where:
    dist(POINT-A-LAT, POINT-B-LAT, POINT-A-LON, POINT-B-LON) is%(within(0.1)) 1
    end
  • Explain that numeric calculations using decimal numbers will often have small inaccuracies, so tests will work better if they test that the output is not equal, but rather, within a certain bound of the expected value. Pyret's is can be followed by %() and then a testing predicate can be placed within the parentheses: the most common one is within(N) where N is some number. This checks that the output is 1 +- 0.1, i.e., that it is greater than 0.9 and less than 1.1.

  • Observation: When students run the test, many will notice that the computed value does not match the expected value of 1.

E. Discovering the Unit Mismatch

  • Prompt Discussion: Ask:
    • “If our FCC formulas produce a result based on our constants, why might the computed value be different from 1?”
    • "If tests fail, either the code is wrong or the tests are wrong. Which is the case here?"
    • “Could it be that our function is returning a value in a different unit than expected?”
  • Guided Reasoning: Lead students to consider that the FCC formulas yield a value (approximately 1.609) that is not 1—because the output produced a number that was not in miles!

F. Step 4: Correcting the Function to Return the Expected Value

  • Activity: Explain that to match the test case (which expects 1), the function must convert the computed value. Ask:
    • “What conversion might we need if the computed value is, say, 1.609 when we expect 1?”
  • Solution: Lead students to recall that 1 mile is approximately 1.60934 KM. Have them update the function by dividing the raw distance by 1.60934:
    fun dist(lat1, lat2, lon1, lon2):
    doc: "Calculates the distance between two coordinates using FCC approximations"
    NS = KPDLAT * (lat1 - lat2)
    EW = KPDLON * (lon1 - lon2)
    num-sqrt(num-sqr(NS) + num-sqr(EW)) / 1.60934
    where:
    dist(POINT-A-LAT, POINT-B-LAT, POINT-A-LON, POINT-B-LON) is%(within(0.1)) 1
    end
  • Test Again: Instruct students to run the updated function. They should now see a value that passes the test.

V. Recap and Wrap-Up (5 minutes)

  • Key Points Discussion:
    • Incremental Development: How breaking the problem into parts (helper function, constants, raw computation) helped manage complexity.
    • Testing and Debugging: How a test case using real-world data (the two points chosen to be 1 mile apart) revealed the unit mismatch.
  • Reflection Questions:
    • “How did our test case help you find the error?”
  • Units Matter