35 Conditionals

A conditional chooses between two result-producing expressions using a Boolean condition.

For example, this expression labels each course as advanced or introductory:


u.course.(
    code,
    (if advanced then "advanced" else "introductory") as level
)

The condition is advanced. If it is true for the current course, the result is "advanced". Otherwise the result is "introductory".

Conditions can use path tails

The condition is an ordinary Boolean-valued expression, so it can use navigation, filters and folds:


u.course.(
    code,
    (if assessment.exam.Σexists then "exam" else "coursework")
      as assessmentStyle
)

This labels a course as "exam" when it has at least one exam assessment, and as "coursework" otherwise.

Branches can use path tails too

The then-branch and else-branch are also path expressions. The following expression uses a fold in the then-branch:


u.course.(
    code,
    (if advanced
     then assessment.project.estimatedHours.Σsum
     else 0)
      as advancedProjectHours
)

For advanced courses, the result is the total estimated project hours. For other courses, the result is 0.

Both branches produce one result

The producing branches must have a common result type. This works because both branches produce strings:


u.course.(
    code,
    (if session.time.day.Σcount > 2
     then "spread out"
     else "compact")
      as timetableShape
)

A conditional exposes one result. The result name can be supplied with as on the whole conditional expression.

Conditionals are not alternatives

Conditionals and alternatives are both expression-level branching constructs, but they answer different questions. Use if then else when there is an explicit Boolean condition. Use | when several branches may produce the same kind of result.


u.course.assessment.(
    (if exam.Σexists
     then exam.maxMark
     else (assignment.maxMark | project.maxMark))
      as maxMark
)

This is legal, but it is not the clearest expression of the idea. The variant case is better written with alternatives:


u.course.assessment.(
    (exam.maxMark | assignment.maxMark | project.maxMark)
      as maxMark
)

The first version asks a Boolean question and then chooses a branch. The second version simply says which paths can produce the maximum mark.

Composability

Conditionals compose with the earlier path tails. The condition can filter, count or navigate. The branches can calculate, fold, use alternatives, or return constants.


u.course.(
    code,
    (if advanced ∧ assessment.project.Σexists
     then assessment.project.estimatedHours.Σsum
     else 0)
      as projectHoursForAdvancedCourses
)

The expression reaches each course, checks a Boolean condition about that course, and then chooses the value to output. Each part is still a path expression.