Error Code: `VARARGS`

This guide explains why a varargs error may occur and describes how to fix it.

Rel provides a varargs mechanism to write more general code that works for different arities. A vararg argument such as `x...` can represent several variables, including none. See Varargs in Rel Primer: Advanced Syntax and Bindings in the Rel Language Reference manual for more details.

When using varargs, keep in mind that the system must be able to compute the number of variables represented by a vararg, commonly referred to as the vararg’s arity. For an overloaded relation, this should be a finite number of arities. If the system can’t compute a certain arity, it returns a varargs error.

Example: Undefined Arity

Here’s an example of a varargs error:

``````@inline
def end_with_a(x..., v) {v = "a"}

def output = end_with_a[3, "a"]``````

The relation `end_with_a`, which only checks that each tuple ends with the string `"a"`, leads to a varargs error.

The expression `end_with_a[3, "a"]` states that you’re looking for all tuples starting with `3, "a"`. See Relational Application in Rel Primer: Basic Syntax or Partial Relational Application in the Rel Language Reference manual for more details. The problem is there’s an infinite number of tuples that begin with `3, "a"` and end with `"a"`.

To resolve this, you can enclose the arguments in the query in parentheses. This makes it clear that `(x..., v)` is matched against a pair.

``````// read query

@inline
def end_with_a(x..., v) {v = "a"}

def output = end_with_a(3, "a")``````

Another solution is to replace `x...` with `x`, meaning that `end_with_a` is a relation of a fixed arity of 2 testing only tuples of length 2.

Now, you can test against a whole set of tuples and filter them:

``````// read query

@inline
def end_with_a(x..., v) {v = "a"}

def Data {
(3, "a");
(1, 2, "a");
("a", "b")
}

def output(x...) = end_with_a(x...) and Data(x...)``````

This particular example would work even if the query were `def output[x...] = end_with_a[x...] and Data[x...]`. But it’s good practice to enclose your arguments in parentheses if they include a vararg.

Here’s another example that raises an error similar to the one above:

``````// read query

def R = (1, "a", "A"); (2, "b", "B"); (3, "c", "C")

def output[x...] = R[x...]``````

Once again, the solution is to enclose the varargs in parentheses:

``````// read query

def R = (1, "a", "A"); (2, "b", "B"); (3, "c", "C")

def output(x...) = R(x...)``````

Example: Unbound Varargs

Also note that the `@inline` annotation is required in the example above. Without it, another varargs error will appear. This time the cause of the error is very similar in nature to the untyped variable error:

``````def end_with_a(x..., v) {v = "a"}

def output(x...) = end_with_a(3, "a")``````