Lab 8 Lambda and JSON
Purpose: The purpose of this lab is to practice the use of lambda and mutually recursive data.
Textbook References: Chapter 17: Nameless Functions, Chapter 19: The Poetry of S-Expressions, Chapter 22: The Commerce of XML
Repeater After Me
We want to define another representation for natural numbers, we’ve decided that things like 0, 1, and 2 are a pain, and we’d rather just think of everything in terms of functions. Your mission is to help define and implement natural numbers as functions. We’ll start by defining a few functions which apply their argument multiple times.
; A Repeater is a [X -> X] -> [X -> X] ; That, given a function f, outputs a function that will repeatedly apply f ; some number of times.
To get you started here is the definition of our Repeater named two.
; two : Repeater ; Applies a given function twice (check-expect ((two add1) 0) 2) (check-expect ((two sqr) 2) 16) (define two (lambda (f) (lambda (x) (f (f x)))))
Exercise 1 Design the Repeater three, which, similarly to the definition of two, that applies it’s argument three times.
Exercise 2 Design the Repeaters one and zero. Is there something strange about the definition of zero?
The functions zero, one, two, and three look curiously similar to natural numbers, in that all they do is repeat their input some number greater than or equal to 0 times.
Exercise 3 Design a function rep->nat which takes a Repeater and returns the number of times it repeats its argument. For example (rep->nat two) should return 2. Hint: If you have a Repeater, all you can do is give it some inputs and see what it gives you back. So your task here is simply to devise some inputs that will tell you how many times it repeated.
Our representation of Repeater now looks a lot like natural numbers. The fact that we can convert back to actual natural numbers will make testing and thinking about these things easier.
Exercise 4 Design the function rep-add1 that increments a Repeater by 1. For example, (rep-add1 two) should produce three. Note that this function produces a Repeater, NOT a natural number.
Exercise 5 Design the function rep+ that takes two Repeaters and returns the Repeater that represents their sum. For example, (rep+ one two) should return three. Note that this function produces a Repeater, NOT a natural number.
Exercise 6 Design the function rep* that takes two Repeaters and returns the Repeater that represents their product. Note that this function produces a Repeater, NOT a natural number.
Exercise 7 Design the function rep-expt that takes two Repeaters and returns the Repeater that represents their exponentiation. In other words, (rep-expt n m) produces the Repeater representation of nm.
JSON Is Your Friend
This portion of the lab relies on the ability for us to parse JSON, and get JSON from the internet. Parsing JSON is not trivial, so we’re providing a teachpack that does this for you. Please save this file (right click > Save as ...) in the same folder as your lab and put (require "lab8-teachpack.rkt") at the top of your file.
; A JSON is one of: ; - String ; - Number ; - Boolean ; - 'null ; - JSONArray ; - JSONObject ; A JSONArray is a [List-of JSON]) ; A JSONObject is a (make-object [List-of JSONPair]) (define-struct object [content]) ; DO NOT COPY THE ABOVE STRUCTURE DEFINITION INTO YOUR CODE. IT IS ALREADY ; PROVIDED BY THE TEACHPACK. ; A JSONPair is a (list Symbol JSON)
Exercise 8 Provide some examples of a JSON, a JSONArray, a JSONObject, and a JSONPair. You can give some simple examples, but also provide some more nested examples to show how the data definitions are intertwined.
Exercise 9 Write a template for JSON. The JSON data representation consists of four data definitions. How many templates do you need? The data definitions for JSONObjects and JSONArrays both refer to JSON and the latter refer to the former. This must produce mutual recursive templates. To help you we have provided the following functions: json-pair?, json-object?, and json-array?.
You can get real world weather data turned into JSON using one of the APIs we have made available!
(get-url TODAY-FORECAST-URL)
(get-url DAILY-FORECAST-URL)
Exercise 10 Define weather-data as the result of calling string->json on one of the get-url calls above. This should provide you with real actual JSON to work with which matches our data definition.
Exercise 11 Design a function find-value that takes a JSON and a Symbol and returns the first JSON pair-value where the pair-name is equal to the given symbol. You should produce 'notfound if the pair does not exist. Be sure to test your function thoroughly!
Exercise 12 Design a function max-temp which, given a JSON, returns the maximum temperature from the data as a Number (look at the data you got back from the weather service to see what label they use for the maximum temperature).
Exercise 13 Design a function current-weather which given a JSON returns a [Listof String] of all the descriptions of the current weather.
Exercise 14 Design the function flatten-json that will return a [List-of (list String JSON)], but the second of any element of the list will not be a JSONArray or a JSONObject. The function will work as follows:
If a JSON j is a String, Number, Boolean, or ’null, (flatten-json j) will return (list (list X j)), where X is one of "STRING", "NUMBER", "BOOLEAN", or "NULL", depending on what j is.
If it is a JSONObject, then the names of its pairs will be string-appended onto the names of the flattening of the associated value.
If it is a JSONArray, then the indices of its values will be string-appended onto the names of the flattening of the associated value.
When string appending, append "-" between the two string values as to separate one field name from another.
The following check should pass:
(check-expect (flatten-json (list 'null '() (make-object (list (list 'greeting (make-object (list (list 'formal "hello") (list 'informal "howdy") (list 'garbage (list true 1))))))))) (list (list "0-NULL" 'null) (list "2-greeting-formal-STRING" "hello") (list "2-greeting-informal-STRING" "howdy") (list "2-greeting-garbage-0-BOOLEAN" true) (list "2-greeting-garbage-1-NUMBER" 1)))