Writing Queries

Consider the following example of classes, students, and enrollments, and that we want to compute the number of students who have enrolled in at least one CS class.

// There are three classes rel classes = {0, 1, 2} // Each student is enrolled in a course (Math or CS) rel enroll = { ("tom", "CS"), ("jenny", "Math"), // Class 0 ("alice", "CS"), ("bob", "CS"), // Class 1 ("jerry", "Math"), ("john", "Math"), // Class 2 } // Count how many student enrolls in CS course rel num_enroll_cs(n) = n := count(s: enroll(s, "CS"))

Normally, executing a program would result in scli outputting every single relation.

classes: {(0), (1), (2)} num_enroll_cs: {(3)} enroll: {("alice", "CS"), ("bob", "CS"), ("jenny", "Math"), ...}

However, we might only be interested in the relation named num_enroll_cs. In this case, we write a query using the query keyword:

query num_enroll_cs

In this case, only the relation num_enroll_cs will be output:

num_enroll_cs: {(3)}

Atomic Query

One can also write atomic query if we just want to get a part of the relation. For instance, consider the fibonacci example:

type fib(x: i32, y: i32) rel fib = {(0, 1), (1, 1)} rel fib(x, y1 + y2) = fib(x - 1, y1) and fib(x - 2, y2) and x <= 10 query fib(8, y) // fib(8, y): {(8, 34)}

In this case, we are just looking at the 8-th fibonacci number, which is 34.