25 Tuple Construction

Tuple construction picks several things and combines them to give the set of attributes output by the frame. The following expression selects course and department from the university as outputs:


u.(course, department)

Here course and department are both evaluated from the same university u.

Its denotation as a frame is:


course=C:Course, department=D:Department
where
    u.course(C)
  ∧ u.department(D)

The same idea works after navigation. The following expression selects code and title from each course as outputs:


u.course.(code, title)

The path tails inside the parentheses are evaluated from the same current value. In this case, both code and title are evaluated from the same course.

The empty tuple () projects away all attributes. The following expression reaches each course and then returns the empty tuple for each one:


u.course.()

This is the zero-attribute projection. It is useful when only the existence of a matching value matters, rather than any attributes of that value.

Nested tuple expressions

Tuple expressions can be nested:


u.course.((code, title), department.name)

Nesting does not create nested structure in the output frame. The output attributes are flattened:


code=C:String, title=T:String, name=N:String
where
  ∃K:Course ∃D:Department
    u.course(K)
  ∧ K.code(C)
  ∧ K.title(T)
  ∧ K.department(D)
  ∧ D.name(N)

Empty tuple expressions also disappear when flattened. For example, a.(b,(),(()).()) is equivalent to a.b.

Analogies with unwrapping, projection and Cartesian products

These examples have several relational-model analogies:

  • u.(course, department) is relational-product-like because course and department are independent tails evaluated from the same university.
  • u.course.(code, title) is relational-projection-like because it selects code and title as outputs.
  • u.course.(code, title) is also unwrapping-like because it selects parts of each current course.

Later chapters use the same parentheses with renaming, calculations, folds and nested path expressions.

Path tails inside tuple construction

In general, tuple construction contains path tails. This is powerful because tuple construction composes with navigation, filters, folds and the other forms of path expression.

For example, this expression selects the student's name and the course code from each enrolment as outputs:


u.enrolment.(student.name, course.code)

Both path tails are evaluated from the same enrolment. That is why the student name and course code remain associated with each other.

The path tails can use filters too:


u.course.(code, [advanced].title)

Here code and [advanced].title are both evaluated from the same course. The second path tail begins with a filter before selecting the course title.

A theta-join-like expression

Tuple construction and filters can be combined in a way that resembles a theta join:


u.(enrolment, session).[enrolment.course = session.course]

The tuple construction forms enrolment-session combinations from the university. The filter keeps the combinations where the enrolment and the session refer to the same course.