Skip to content
  • Getting Started
  • HELP
  • Error Messages
  • VARARGS

Error code: VARARGS

This guide explains why you may experience a varargs error and how to solve it.

Rel provides a varargs mechanism to write more general code that works for different arities. The vararg argument x... can represent multiple variables and as little as none. Refer to the Varargs section in Rel Primer: Advanced Syntax and the Bindings section in Rel Language Reference for further 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 cannot compute a certain arity, the error is returned.

Example: Multiple Varargs

Consider the following example where multiple vararg arguments are used:

def T = "a", "b", "c"
def output(x...) = T(x..., y...) from y...
Error example from the RAI Console

In the example above, you tried to return only a subset of arguments, but it is not clear how many are included in x... because it is ambiguous which elements are captured by x... or y.... There are multiple possible combinations: x... (y...) could represent only the first argument (two last arguments), all arguments (no argument), or no argument (all arguments). The system cannot resolve this ambiguity.

This ambiguity still exists even when more arguments are specified:

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

A solution to this problem could be to introduce a domain that binds x... or y... and resolve the arity ambiguity:

def T = "a", "b", "c"
def S = "c"
 
def output(x...) {
    T(x..., y...) and S(y...) 
    from y...
}

Now, thanks to the definition of the relation S, the arity of y... is not ambiguous and can only be 1.

Another approach to resolve the ambiguity could be 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 is 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"]
Error example from the RAI Console

It might be surprsing to see that the relation end_with_a, which just checks that each tuple ends with the string "a", leads to a varargs error.

The expression end_with_a[3, "a"] states that you are looking for all tuples starting with 3, "a". See this section of Rel Primer: Basic Syntax or of Rel Language Reference for details. The problem is there exists an infinite number of tuples that fulfill these two conditions.

To solve this, you can write the output query in a pointwise form, which specifies all variables leaving no ambiguity about the arity of x...:

// query
 
@inline
def end_with_a(x..., v) {v = "a"}
 
def output = end_with_a(3, "a")
Loading sol1-var...

Equally well, you could 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 could even test against a whole set of tuples and filter them:

// 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...)
Loading sol2-var...

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
Error example from the RAI Console
Was this doc helpful?