Day 6 - Introduction to tables
TODO: lengthen class exercise
Skills: 2
Pre-reading: 4.1.1 & 4.1.2
Intro (15 min)
Goal Learn about tabular data, creating tables literally, importing data, extracting rows and cell values.
- Many everyday pieces of data -- like a workout journal, recipe index, or library catalog — are naturally represented as tables, a type of data where there are many rows where each row has the same set of attributes, called columns.
- Tables are values, just like numbers, strings, images, and booleans, and small ones can be directly typed into Pyret as:
workouts = table: date :: String, activity :: String, duration :: Number
row: "2025-04-01", "Running", 30
row: "2025-04-02", "Yoga", 45
row: "2025-04-03", "Cycling", 60
end - Note that after the
table:
comes a list of columns, with optional type annotations. This is then followed by a sequence of rows, that each must have exactly the columns mentioned at the beginning. - Since tables are values, they can be the input and output of functions, and can be used in examples. An important detail: when comparing tables for equality (like in test cases) the order of rows matters!
- We can use
check: ... end
to write a set of tests not associated with a function, and use that to see:check:
table: date :: String, activity :: String, duration :: Number
row: "2025-04-01", "Running", 30
row: "2025-04-02", "Yoga", 45
row: "2025-04-03", "Cycling", 60
end
is-not
table: date :: String, activity :: String, duration :: Number
row: "2025-04-03", "Cycling", 60
row: "2025-04-01", "Running", 30
row: "2025-04-02", "Yoga", 45
end
end - To deal with external files, we need to first
include
a Pyret piece of functionality that is not enabled by default to handle tables represented as "comma separated values" (CSV) files. - Then we can use
load-table:
, rather thantable:
, and rather than listing the rows, specifying that they come from a csv file (in this case, from a URL, but in HW and lab, often it will be a file in the same project, usingcsv-table-file
).include csv
recipes = load-table:
title :: String,
servings :: Number,
prep-time :: Number
source: csv-table-url("https://pdi.run/f25-2000-recipes.csv", default-options)
end - In addition to printing the whole table (or a prefix, if the table is long),
you can extract a row from it by writing
table-identifier.row-n(N)
for someN
. The first row is numbered0
, the last is one minus the number in the table.second-workout = workouts.row-n(1)
# -> Row: date = "2025-04-02", activity = "Yoga", duration = 45 - From a row, you can extract a column values using
row-identifier["column-name"]
, e.g.,second-workout["activity"] # -> "Yoga"
# or all at once:
workouts.row-n(1)["duration"] # -> 45
Class Exercise (40 mins)
- Find a CSV on https://data.boston.gov/, copy the URL, and create a table from it.
- First, make up some columns, but the error should tell you how many there should be (NOTE: This isn't currently the case, but issue tracking it is https://github.com/brownplt/pyret-lang/issues/1779).
- Use the interactions window,
.row-n
, and the column extraction to explore the data a little bit. - Check the total number of rows with
table-identifier.length()
. What happens if you try to dotable-identifier.row-n(M)
forM
that is greater than the total number of rows? - Similarly, try extracting a column that doesn't exist.
Wrap-up (5 mins)
- Tables are an extremely common and powerful form of data. Today we just learned how to look at them; in the upcoming days we will see how to program with them!