HELP
ERROR MESSAGES
VARARGS

# 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. The vararg argument `x...` can represent multiple variables or as few as 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 needs to compute the arity of the passed arguments. 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: Multiple Varargs

Consider the following relation with multiple vararg arguments:

``````def T = "a", "b", "c"
def output(x...) = T(x..., y...) from y...``````

The code above doesn’t specify how many arguments are included in `x...` and doesn’t indicate which elements are captured by `x...` or `y...`. There are multiple possible combinations: `x...` (`y...`) could represent only the first element of `T` (two last elements), all elements (no elements), or no element (all elements). The system can’t resolve this ambiguity.

This ambiguity still exists even when more arguments are specified:

``def output(x...) = T(x..., "b", y...) from y...``

One solution is to introduce a domain that binds `x...` or `y...` and resolves the arity ambiguity:

``````def T = "a", "b", "c"
def S = "c"

def output(x...) {
T(x..., y...) and S(y...)
from y...
}``````

Given the definition of the relation `S`, the arity of `y...` isn’t ambiguous and can only be `1`.

Another approach to resolve the ambiguity is to reduce the number of vararg arguments in the code:

``````def output(x...) {
T(x..., y)
from y
}``````

With only one vararg argument `x...`, no ambiguity exists, i.e., it’s clear that `x...` represents the first two arguments because the argument `y` has by definition arity 1.

## Example: Undefined Arity

Another example of a varargs error is the following:

``````@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 fulfill those two conditions.

To resolve this, you can write the output query in a point-wise form, which specifies all variables leaving no ambiguity about the arity of `x...`:

``````// 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...)``````

## Example: Unbound Varargs

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

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

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